Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions NativeScript/runtime/ArgConverter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -500,8 +500,7 @@
return;
}
} else if (value->IsString()) {
if (type == BinaryTypeEncodingType::IdEncoding ||
type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
if (type == BinaryTypeEncodingType::IdEncoding || typeEncoding->isInterfaceReference()) {
id data = tns::ToNSString(isolate, value);
// this feels wrong but follows the other CFBridgingRetain calls
// and also solves a leak
Expand All @@ -511,7 +510,7 @@
return;
}
} else if (value->IsObject()) {
if (type == BinaryTypeEncodingType::InterfaceDeclarationReference ||
if (typeEncoding->isInterfaceReference() ||
type == BinaryTypeEncodingType::InstanceTypeEncoding ||
type == BinaryTypeEncodingType::IdEncoding) {
BaseDataWrapper* baseWrapper = tns::GetValue(isolate, value);
Expand Down Expand Up @@ -720,8 +719,8 @@
}

Isolate* isolate = v8::Isolate::GetCurrent();
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
const char* name = typeEncoding->details.declarationReference.name.valuePtr();
if (typeEncoding->isInterfaceReference()) {
const char* name = typeEncoding->interfaceName();
if (strcmp(name, "NSNumber") == 0 && tns::IsNumber(arg)) {
return true;
}
Expand Down Expand Up @@ -978,9 +977,8 @@
}

const Meta* ArgConverter::FindMeta(Class klass, const TypeEncoding* typeEncoding) {
if (typeEncoding != nullptr &&
typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
const char* name = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
if (typeEncoding != nullptr && typeEncoding->isInterfaceReference()) {
const char* name = typeEncoding->interfaceName();
const Meta* result = GetMeta(name);
if (result != nullptr && result->type() == MetaType::Interface) {
return result;
Expand Down Expand Up @@ -1259,11 +1257,11 @@
}

const TypeEncoding* innerTypeEncoding = typeEncoding->details.pointer.getInnerType();
if (innerTypeEncoding->type != BinaryTypeEncodingType::InterfaceDeclarationReference) {
if (!innerTypeEncoding->isInterfaceReference()) {
return false;
}

const char* name = innerTypeEncoding->details.declarationReference.name.valuePtr();
const char* name = innerTypeEncoding->interfaceName();
if (name == nullptr) {
return false;
}
Expand Down
1 change: 1 addition & 0 deletions NativeScript/runtime/ClassBuilder.mm
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ void ScopeClassNameToIsolate(std::string& name, int isolateId) {
}
case BinaryTypeEncodingType::ProtocolEncoding:
case BinaryTypeEncodingType::InterfaceDeclarationReference:
case BinaryTypeEncodingType::InterfaceIndexReference:
case BinaryTypeEncodingType::InstanceTypeEncoding:
case BinaryTypeEncodingType::IdEncoding: {
return "@";
Expand Down
16 changes: 10 additions & 6 deletions NativeScript/runtime/FFICall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ ffi_type* FFICall::GetArgumentType(const TypeEncoding* typeEncoding, bool isStru
}
case BinaryTypeEncodingType::IdEncoding:
case BinaryTypeEncodingType::InterfaceDeclarationReference:
case BinaryTypeEncodingType::InterfaceIndexReference:
case BinaryTypeEncodingType::InstanceTypeEncoding:
case BinaryTypeEncodingType::SelectorEncoding:
case BinaryTypeEncodingType::BlockEncoding:
Expand Down Expand Up @@ -277,10 +278,11 @@ StructInfo FFICall::GetStructInfo(size_t fieldsCount, const TypeEncoding* fieldE
}

ParametrizedCall* ParametrizedCall::Get(const TypeEncoding* typeEncoding, const int initialParameterIndex, const int argsCount) {
auto it = callsCache_.find(typeEncoding);
if (it != callsCache_.end()) {
return it->second;
}
CallKey key{typeEncoding, initialParameterIndex, argsCount};
auto it = callsCache_.find(key);
if (it != callsCache_.end()) {
return it->second;
}

const ffi_type** parameterTypesFFITypes = new const ffi_type*[argsCount]();
ffi_type* returnType = FFICall::GetArgumentType(typeEncoding);
Expand All @@ -300,12 +302,14 @@ ParametrizedCall* ParametrizedCall::Get(const TypeEncoding* typeEncoding, const
tns::Assert(status == FFI_OK);

ParametrizedCall* call = new ParametrizedCall(cif);
callsCache_.emplace(typeEncoding, call);
callsCache_.emplace(key, call);

return call;
}

robin_hood::unordered_map<const TypeEncoding*, ParametrizedCall*> ParametrizedCall::callsCache_;
robin_hood::unordered_map<ParametrizedCall::CallKey, ParametrizedCall*,
ParametrizedCall::CallKeyHash>
ParametrizedCall::callsCache_;
robin_hood::unordered_map<std::string, StructInfo> FFICall::structInfosCache_;

}
26 changes: 25 additions & 1 deletion NativeScript/runtime/FFICall.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,31 @@ class ParametrizedCall {
std::vector<size_t> ArgValueOffsets;

private:
static robin_hood::unordered_map<const TypeEncoding*, ParametrizedCall*>
// The cif is built from the encoding *and* the two counts, so all three
// identify it. Keying on the encoding alone aliases distinct call shapes onto
// one cif, which mis-describes the stack rather than failing outright.
struct CallKey {
const TypeEncoding* encoding;
int initialParameterIndex;
int argsCount;

bool operator==(const CallKey& other) const {
return encoding == other.encoding &&
initialParameterIndex == other.initialParameterIndex &&
argsCount == other.argsCount;
}
};

struct CallKeyHash {
size_t operator()(const CallKey& key) const {
size_t hash = robin_hood::hash<const void*>()(key.encoding);
hash = hash * 31 + static_cast<size_t>(key.initialParameterIndex);
hash = hash * 31 + static_cast<size_t>(key.argsCount);
return hash;
}
};

static robin_hood::unordered_map<CallKey, ParametrizedCall*, CallKeyHash>
callsCache_;
};

Expand Down
44 changes: 21 additions & 23 deletions NativeScript/runtime/Interop.mm
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@
}

bool Interop::isRefTypeEqual(const TypeEncoding* typeEncoding, const char* clazz) {
std::string n(&typeEncoding->details.interfaceDeclarationReference.name.value());
return n.compare(clazz) == 0;
const char* name = typeEncoding->interfaceName();
return name != nullptr && std::string(name).compare(clazz) == 0;
}

// this is experimental. Maybe we can have something like this to wrap all Local<Value> to avoid
Expand Down Expand Up @@ -246,8 +246,7 @@ inline bool isBool() {
FFICall::DisposeFFIType(ffiType, typeEncoding);
memset(dest, 0, size);
} else if (argHelper.isBool()) {
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference &&
isRefTypeEqual(typeEncoding, "NSNumber")) {
if (typeEncoding->isInterfaceReference() && isRefTypeEqual(typeEncoding, "NSNumber")) {
bool value = tns::ToBool(arg);
NSNumber* num = [NSNumber numberWithBool:value];
Interop::SetValue(dest, num);
Expand Down Expand Up @@ -321,15 +320,14 @@ inline bool isBool() {
}
unichar c = (vector.size() == 0) ? 0 : vector[0];
Interop::SetValue(dest, c);
} else if (argHelper.isString() &&
(typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference ||
typeEncoding->type == BinaryTypeEncodingType::IdEncoding)) {
} else if (argHelper.isString() && (typeEncoding->isInterfaceReference() ||
typeEncoding->type == BinaryTypeEncodingType::IdEncoding)) {
NSString* result = tns::ToNSString(isolate, arg);
Interop::SetValue(dest, result);
} else if (Interop::IsNumbericType(typeEncoding->type) || tns::IsNumber(arg)) {
double value = tns::ToNumber(isolate, arg);

if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference ||
if (typeEncoding->isInterfaceReference() ||
typeEncoding->type == BinaryTypeEncodingType::IdEncoding) {
// NSNumber
NSNumber* num = [NSNumber numberWithDouble:value];
Expand Down Expand Up @@ -657,8 +655,8 @@ inline bool isBool() {
}

bool isNSArray = false;
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
std::string name = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
if (typeEncoding->isInterfaceReference()) {
std::string name = typeEncoding->interfaceName();
isNSArray = name == "NSArray";
}

Expand Down Expand Up @@ -1189,7 +1187,7 @@ inline bool isBool() {
return instance;
}

if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference ||
if (typeEncoding->isInterfaceReference() ||
typeEncoding->type == BinaryTypeEncodingType::IdEncoding ||
typeEncoding->type == BinaryTypeEncodingType::InstanceTypeEncoding) {
id result = call->GetResult<id>();
Expand Down Expand Up @@ -1222,8 +1220,8 @@ inline bool isBool() {
}

if (marshalToPrimitive && [result isKindOfClass:[NSString class]]) {
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
const char* returnClassName = typeEncoding->details.declarationReference.name.valuePtr();
if (typeEncoding->isInterfaceReference()) {
const char* returnClassName = typeEncoding->interfaceName();
Class returnClass = objc_getClass(returnClassName);
if (returnClass != nil && returnClass == [NSMutableString class]) {
marshalToPrimitive = false;
Expand All @@ -1249,9 +1247,9 @@ inline bool isBool() {
return poInstance->Get(isolate);
}

// For NSProxy we will try to read the metadata from
// typeEncoding->details.interfaceDeclarationReference.name because class_getSuperclass will
// directly return NSProxy and thus missing to attach all instance members
// For NSProxy we will try to read the metadata from the encoding's interface name because
// class_getSuperclass will directly return NSProxy and thus missing to attach all instance
// members
const TypeEncoding* te = [result isProxy] ? typeEncoding : nullptr;

ObjCDataWrapper* wrapper = new ObjCDataWrapper(result, te);
Expand Down Expand Up @@ -1398,9 +1396,7 @@ inline bool isBool() {
const char* protocolName = (*it).valuePtr();
additionalProtocols.push_back(protocolName);
}
} else if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference &&
typeEncoding->details.interfaceDeclarationReference._protocols.offset > 0) {
PtrTo<Array<String>> protocols = typeEncoding->details.interfaceDeclarationReference._protocols;
} else if (const Array<String>* protocols = typeEncoding->interfaceProtocols()) {
for (auto it = protocols->begin(); it != protocols->end(); it++) {
const char* protocolName = (*it).valuePtr();
additionalProtocols.push_back(protocolName);
Expand Down Expand Up @@ -1767,9 +1763,9 @@ void ExecuteWriteValueValidationsAndStopExecutionAndLogStackTrace(Local<Context>
const TypeEncoding* typeEncoding,
void* dest, Local<Value> arg) {
Isolate* isolate = v8::Isolate::GetCurrent();
std::string destName = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
Local<Value> originArg = arg;
if (typeEncoding->type == BinaryTypeEncodingType::InterfaceDeclarationReference) {
if (typeEncoding->isInterfaceReference()) {
std::string destName = typeEncoding->interfaceName();
if (originArg->IsObject()) {
Local<Object> originObj = originArg.As<Object>();
if ((originObj->IsArrayBuffer() || originObj->IsArrayBufferView() ||
Expand All @@ -1791,7 +1787,7 @@ void ExecuteWriteValueValidationsAndStopExecutionAndLogStackTrace(Local<Context>
}

bool IsTypeEncondingHandldedByDebugMessages(const TypeEncoding* typeEncoding) {
if (typeEncoding->type != BinaryTypeEncodingType::InterfaceDeclarationReference &&
if (!typeEncoding->isInterfaceReference() &&
typeEncoding->type != BinaryTypeEncodingType::StructDeclarationReference &&
typeEncoding->type != BinaryTypeEncodingType::IdEncoding) {
return true;
Expand All @@ -1803,7 +1799,9 @@ bool IsTypeEncondingHandldedByDebugMessages(const TypeEncoding* typeEncoding) {
void LogWriteValueTraceMessage(Local<Context> context, const TypeEncoding* typeEncoding, void* dest,
Local<Value> arg) {
Isolate* isolate = v8::Isolate::GetCurrent();
std::string destName = typeEncoding->details.interfaceDeclarationReference.name.valuePtr();
std::string destName = typeEncoding->isInterfaceReference()
? typeEncoding->interfaceName()
: typeEncoding->details.declarationReference.name.valuePtr();
std::string originName = tns::ToString(isolate, arg);
if (originName == "") {
// empty string
Expand Down
Loading
Loading