Var JavascriptSet::EntryForEach(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); ARGUMENTS(args, callInfo); ScriptContext* scriptContext = function->GetScriptContext(); AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Set.prototype.forEach")); if (!JavascriptSet::Is(args[0])) { JavascriptError::ThrowTypeErrorVar(scriptContext, JSERR_NeedObjectOfType, _u("Set.prototype.forEach"), _u("Set")); } JavascriptSet* set = JavascriptSet::FromVar(args[0]); if (args.Info.Count < 2 || !JavascriptConversion::IsCallable(args[1])) { JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedFunction, _u("Set.prototype.forEach")); } RecyclableObject* callBackFn = RecyclableObject::FromVar(args[1]); Var thisArg = (args.Info.Count > 2) ? args[2] : scriptContext->GetLibrary()->GetUndefined(); auto iterator = set->GetIterator(); while (iterator.Next()) { Var value = iterator.Current(); CALL_FUNCTION(callBackFn, CallInfo(CallFlags_Value, 4), thisArg, value, value, args[0]); } return scriptContext->GetLibrary()->GetUndefined(); }
BOOL DynamicObject::CallToPrimitiveFunction(Var toPrimitiveFunction, PropertyId propertyId, Var* result, ScriptContext * requestContext) { if (JavascriptConversion::IsCallable(toPrimitiveFunction)) { RecyclableObject* toStringFunction = RecyclableObject::FromVar(toPrimitiveFunction); ThreadContext * threadContext = requestContext->GetThreadContext(); Var aResult = threadContext->ExecuteImplicitCall(toStringFunction, ImplicitCall_ToPrimitive, [=]() -> Js::Var { // Stack object should have a pre-op bail on implicit call. We shouldn't see them here. Assert(!ThreadContext::IsOnStack(this) || threadContext->HasNoSideEffect(toStringFunction)); return toStringFunction->GetEntryPoint()(toStringFunction, CallInfo(CallFlags_Value, 1), this); }); if (!aResult) { // There was an implicit call and implicit calls are disabled. This would typically cause a bailout. Assert(threadContext->IsDisableImplicitCall()); *result = requestContext->GetLibrary()->GetNull(); return true; } if (JavascriptOperators::GetTypeId(aResult) <= TypeIds_LastToPrimitiveType) { *result = aResult; return true; } } return false; }
CallInfo LuaMachine::getCallInfo(lua_Debug *ar) { auto name = ar->name ? ar->name : ""; auto source = ar->source ? ar->source : ""; auto line = ar->currentline; auto startLine = ar->linedefined; auto endLine = ar->lastlinedefined; return CallInfo(name, source, line, startLine, endLine); }
Var JavascriptWeakSet::NewInstance(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); ARGUMENTS(args, callInfo); ScriptContext* scriptContext = function->GetScriptContext(); JavascriptLibrary* library = scriptContext->GetLibrary(); Var newTarget = callInfo.Flags & CallFlags_NewTarget ? args.Values[args.Info.Count] : args[0]; bool isCtorSuperCall = (callInfo.Flags & CallFlags_New) && newTarget != nullptr && !JavascriptOperators::IsUndefined(newTarget); Assert(isCtorSuperCall || !(callInfo.Flags & CallFlags_New) || args[0] == nullptr); CHAKRATEL_LANGSTATS_INC_BUILTINCOUNT(WeakSetCount); JavascriptWeakSet* weakSetObject = nullptr; if (callInfo.Flags & CallFlags_New) { weakSetObject = library->CreateWeakSet(); } else { JavascriptError::ThrowTypeErrorVar(scriptContext, JSERR_NeedObjectOfType, _u("WeakSet"), _u("WeakSet")); } Assert(weakSetObject != nullptr); Var iterable = (args.Info.Count > 1) ? args[1] : library->GetUndefined(); RecyclableObject* iter = nullptr; RecyclableObject* adder = nullptr; if (JavascriptConversion::CheckObjectCoercible(iterable, scriptContext)) { iter = JavascriptOperators::GetIterator(iterable, scriptContext); Var adderVar = JavascriptOperators::GetProperty(weakSetObject, PropertyIds::add, scriptContext); if (!JavascriptConversion::IsCallable(adderVar)) { JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction); } adder = RecyclableObject::FromVar(adderVar); } if (iter != nullptr) { Var nextItem; while (JavascriptOperators::IteratorStepAndValue(iter, scriptContext, &nextItem)) { CALL_FUNCTION(adder, CallInfo(CallFlags_Value, 2), weakSetObject, nextItem); } } return isCtorSuperCall ? JavascriptOperators::OrdinaryCreateFromConstructor(RecyclableObject::FromVar(newTarget), weakSetObject, nullptr, scriptContext) : weakSetObject; }
void Interpreter::call() { uint16_t funId = getNext2Bytes(); pushContext(funId); loadFunParamsInCtx(funId); stackTrace.push(CallInfo(_bc, _insPtr)); _bc = ((BytecodeFunction*)_code->functionById(funId))->bytecode(); _insPtr = 0; // popContext(); }
void Semaphore::wait(){ CallInfo info = CallInfo(); (&info)->isSemaphore = TRUE; (&info)->id = myImpl; (&info)->call = SEMAPHORE_WAIT; (&info)->caller = (void*)this; unsigned off = FP_OFF((&info)); unsigned segg = FP_SEG((&info)); asm{//mozda treba WORD PTR mov cx, segg mov dx, off } asm int 60h; //delete info; }
int Semaphore::val() const{ CallInfo info = CallInfo(); (&info)->isSemaphore = TRUE; (&info)->id = myImpl; (&info)->call = SEMAPHORE_VALUE; (&info)->caller = (void*)this; unsigned off = FP_OFF((&info)); unsigned segg = FP_SEG((&info)); asm{//mozda treba WORD PTR mov cx, segg mov dx, off } asm int 60h; unsigned val = (&info)->arg1; //delete info; return val; }
Semaphore::Semaphore(int init){ lock CallInfo info = CallInfo(); unlock (&info)->isSemaphore = TRUE; (&info)->arg1 = init; (&info)->call = SEMAPHORE_CREATE; (&info)->caller = (void*)this; unsigned off = FP_OFF((&info)); unsigned segg = FP_SEG((&info)); asm{//mozda treba WORD PTR mov cx, segg mov dx, off } asm int 60h; myImpl = (&info)->id; //delete info; }
Var JavascriptGeneratorFunction::EntryAsyncFunctionImplementation(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); ARGUMENTS(stackArgs, callInfo); ScriptContext* scriptContext = function->GetScriptContext(); JavascriptLibrary* library = scriptContext->GetLibrary(); RecyclableObject* prototype = scriptContext->GetLibrary()->GetNull(); // InterpreterStackFrame takes a pointer to the args, so copy them to the recycler heap // and use that buffer for this InterpreterStackFrame. Var* argsHeapCopy = RecyclerNewArray(scriptContext->GetRecycler(), Var, stackArgs.Info.Count); js_memcpy_s(argsHeapCopy, sizeof(Var) * stackArgs.Info.Count, stackArgs.Values, sizeof(Var) * stackArgs.Info.Count); Arguments heapArgs(callInfo, argsHeapCopy); JavascriptExceptionObject* e = nullptr; JavascriptPromiseResolveOrRejectFunction* resolve; JavascriptPromiseResolveOrRejectFunction* reject; JavascriptPromiseAsyncSpawnExecutorFunction* executor = library->CreatePromiseAsyncSpawnExecutorFunction( JavascriptPromise::EntryJavascriptPromiseAsyncSpawnExecutorFunction, scriptContext->GetLibrary()->CreateGenerator(heapArgs, JavascriptAsyncFunction::FromVar(function)->GetGeneratorVirtualScriptFunction(), prototype), stackArgs[0]); JavascriptPromise* promise = library->CreatePromise(); JavascriptPromise::InitializePromise(promise, &resolve, &reject, scriptContext); try { CALL_FUNCTION(executor, CallInfo(CallFlags_Value, 3), library->GetUndefined(), resolve, reject); } catch (JavascriptExceptionObject* ex) { e = ex; } if (e != nullptr) { JavascriptPromise::TryRejectWithExceptionObject(e, reject, scriptContext); } return promise; }
static void func_trace (MonoMethod *method) { pthread_mutex_lock (&trace_list_mutex); static std::map<MonoMethod*, CallInfo>trace_log; static uint32_t order = 0; if (trace_switch == false) { order = 0; if (!trace_log.empty ()) { send_trace_log (trace_log); trace_log.clear (); } pthread_mutex_unlock (&trace_list_mutex); return; /*Fixme : 这个地方再考虑, 重复代码*/ } if (trace_log.find (method) != trace_log.end ()) { trace_log[method].times += 1; } else { trace_log[method] = CallInfo (); trace_log[method].order = order++; trace_log[method].times = 1; } pthread_mutex_unlock (&trace_list_mutex); return; }
Var BoundFunction::NewInstance(RecyclableObject* function, CallInfo callInfo, ...) { RUNTIME_ARGUMENTS(args, callInfo); ScriptContext* scriptContext = function->GetScriptContext(); if (args.Info.Count == 0) { JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction /* TODO-ERROR: get arg name - args[0] */); } BoundFunction *boundFunction = (BoundFunction *) function; Var targetFunction = boundFunction->targetFunction; // // var o = new boundFunction() // a new object should be created using the actual function object // Var newVarInstance = nullptr; if (callInfo.Flags & CallFlags_New) { if (JavascriptProxy::Is(targetFunction)) { JavascriptProxy* proxy = JavascriptProxy::FromVar(targetFunction); Arguments proxyArgs(CallInfo(CallFlags_New, 1), &targetFunction); args.Values[0] = newVarInstance = proxy->ConstructorTrap(proxyArgs, scriptContext, 0); } else { args.Values[0] = newVarInstance = JavascriptOperators::NewScObjectNoCtor(targetFunction, scriptContext); } } Js::Arguments actualArgs = args; if (boundFunction->count > 0) { BOOL isCrossSiteObject = boundFunction->IsCrossSiteObject(); // OACR thinks that this can change between here and the check in the for loop below const unsigned int argCount = args.Info.Count; if ((boundFunction->count + argCount) > CallInfo::kMaxCountArgs) { JavascriptError::ThrowRangeError(scriptContext, JSERR_ArgListTooLarge); } Var *newValues = RecyclerNewArray(scriptContext->GetRecycler(), Var, boundFunction->count + argCount); uint index = 0; // // For [[Construct]] use the newly created var instance // For [[Call]] use the "this" to which bind bound it. // if (callInfo.Flags & CallFlags_New) { newValues[index++] = args[0]; } else { newValues[index++] = boundFunction->boundThis; } // Copy the bound args if (!isCrossSiteObject) { for (uint i = 0; i < boundFunction->count; i++) { newValues[index++] = boundFunction->boundArgs[i]; } } else { // it is possible that the bound arguments are not marshalled yet. for (uint i = 0; i < boundFunction->count; i++) { newValues[index++] = CrossSite::MarshalVar(scriptContext, boundFunction->boundArgs[i]); } } // Copy the extra args for (uint i=1; i<argCount; i++) { newValues[index++] = args[i]; } actualArgs = Arguments(args.Info, newValues); actualArgs.Info.Count = boundFunction->count + argCount; } else { if (!(callInfo.Flags & CallFlags_New)) { actualArgs.Values[0] = boundFunction->boundThis; } } RecyclableObject* actualFunction = RecyclableObject::FromVar(targetFunction); Var aReturnValue = JavascriptFunction::CallFunction<true>(actualFunction, actualFunction->GetEntryPoint(), actualArgs); // // [[Construct]] and call returned a non-object // return the newly created var instance // if ((callInfo.Flags & CallFlags_New) && !JavascriptOperators::IsObject(aReturnValue)) { aReturnValue = newVarInstance; } return aReturnValue; }
Var JavascriptGeneratorFunction::EntryGeneratorFunctionImplementation(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); ARGUMENTS(stackArgs, callInfo); Assert(!(callInfo.Flags & CallFlags_New)); ScriptContext* scriptContext = function->GetScriptContext(); JavascriptGeneratorFunction* generatorFunction = JavascriptGeneratorFunction::FromVar(function); // InterpreterStackFrame takes a pointer to the args, so copy them to the recycler heap // and use that buffer for this InterpreterStackFrame. Field(Var)* argsHeapCopy = RecyclerNewArray(scriptContext->GetRecycler(), Field(Var), stackArgs.Info.Count); CopyArray(argsHeapCopy, stackArgs.Info.Count, stackArgs.Values, stackArgs.Info.Count); Arguments heapArgs(callInfo, (Var*)argsHeapCopy); DynamicObject* prototype = scriptContext->GetLibrary()->CreateGeneratorConstructorPrototypeObject(); JavascriptGenerator* generator = scriptContext->GetLibrary()->CreateGenerator(heapArgs, generatorFunction->scriptFunction, prototype); // Set the prototype from constructor JavascriptOperators::OrdinaryCreateFromConstructor(function, generator, prototype, scriptContext); // Call a next on the generator to execute till the beginning of the body CALL_ENTRYPOINT(scriptContext->GetThreadContext(), generator->EntryNext, function, CallInfo(CallFlags_Value, 1), generator); return generator; }
Var JavascriptMap::NewInstance(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); ARGUMENTS(args, callInfo); ScriptContext* scriptContext = function->GetScriptContext(); JavascriptLibrary* library = scriptContext->GetLibrary(); AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, _u("Map")); Var newTarget = callInfo.Flags & CallFlags_NewTarget ? args.Values[args.Info.Count] : args[0]; bool isCtorSuperCall = (callInfo.Flags & CallFlags_New) && newTarget != nullptr && !JavascriptOperators::IsUndefined(newTarget); Assert(isCtorSuperCall || !(callInfo.Flags & CallFlags_New) || args[0] == nullptr); CHAKRATEL_LANGSTATS_INC_BUILTINCOUNT(MapCount); JavascriptMap* mapObject = nullptr; if (callInfo.Flags & CallFlags_New) { mapObject = library->CreateMap(); } else { JavascriptError::ThrowTypeErrorVar(scriptContext, JSERR_NeedObjectOfType, _u("Map"), _u("Map")); } Assert(mapObject != nullptr); Var iterable = (args.Info.Count > 1) ? args[1] : library->GetUndefined(); RecyclableObject* iter = nullptr; RecyclableObject* adder = nullptr; if (JavascriptConversion::CheckObjectCoercible(iterable, scriptContext)) { iter = JavascriptOperators::GetIterator(iterable, scriptContext); Var adderVar = JavascriptOperators::GetProperty(mapObject, PropertyIds::set, scriptContext); if (!JavascriptConversion::IsCallable(adderVar)) { JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedFunction); } adder = RecyclableObject::FromVar(adderVar); } if (mapObject->map != nullptr) { JavascriptError::ThrowTypeErrorVar(scriptContext, JSERR_ObjectIsAlreadyInitialized, _u("Map"), _u("Map")); } mapObject->map = RecyclerNew(scriptContext->GetRecycler(), MapDataMap, scriptContext->GetRecycler()); if (iter != nullptr) { Var undefined = library->GetUndefined(); JavascriptOperators::DoIteratorStepAndValue(iter, scriptContext, [&](Var nextItem) { if (!JavascriptOperators::IsObject(nextItem)) { JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject); } RecyclableObject* obj = RecyclableObject::FromVar(nextItem); Var key, value; if (!JavascriptOperators::GetItem(obj, 0u, &key, scriptContext)) { key = undefined; } if (!JavascriptOperators::GetItem(obj, 1u, &value, scriptContext)) { value = undefined; } // CONSIDER: if adder is the default built-in, fast path it and skip the JS call? CALL_FUNCTION(adder, CallInfo(CallFlags_Value, 3), mapObject, key, value); }); } return isCtorSuperCall ? JavascriptOperators::OrdinaryCreateFromConstructor(RecyclableObject::FromVar(newTarget), mapObject, nullptr, scriptContext) : mapObject; }