| Index: src/a64/stub-cache-a64.cc
|
| diff --git a/src/a64/stub-cache-a64.cc b/src/a64/stub-cache-a64.cc
|
| index f7a94c75006d32813d5d72399eec000974e37f01..6d78b8de311bb4faedd7ee5acc74fff95409f08c 100644
|
| --- a/src/a64/stub-cache-a64.cc
|
| +++ b/src/a64/stub-cache-a64.cc
|
| @@ -704,39 +704,6 @@ void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
|
| }
|
|
|
|
|
| -// The function to called must be passed in x1.
|
| -static void GenerateCallFunction(MacroAssembler* masm,
|
| - Handle<Object> object,
|
| - const ParameterCount& arguments,
|
| - Label* miss,
|
| - ExtraICState extra_ic_state,
|
| - Register function,
|
| - Register receiver,
|
| - Register scratch) {
|
| - ASSERT(!AreAliased(function, receiver, scratch));
|
| - ASSERT(function.Is(x1));
|
| -
|
| - // Check that the function really is a function.
|
| - __ JumpIfSmi(function, miss);
|
| - __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss);
|
| -
|
| - if (object->IsGlobalObject()) {
|
| - const int argc = arguments.immediate();
|
| - const int receiver_offset = argc * kPointerSize;
|
| - __ Ldr(scratch,
|
| - FieldMemOperand(receiver, GlobalObject::kGlobalReceiverOffset));
|
| - __ Poke(scratch, receiver_offset);
|
| - }
|
| -
|
| - // Invoke the function.
|
| - CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
|
| - ? CALL_AS_FUNCTION
|
| - : CALL_AS_METHOD;
|
| - __ InvokeFunction(
|
| - function, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
|
| -}
|
| -
|
| -
|
| static void PushInterceptorArguments(MacroAssembler* masm,
|
| Register receiver,
|
| Register holder,
|
| @@ -938,7 +905,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
|
|
|
| class CallInterceptorCompiler BASE_EMBEDDED {
|
| public:
|
| - CallInterceptorCompiler(StubCompiler* stub_compiler,
|
| + CallInterceptorCompiler(CallStubCompiler* stub_compiler,
|
| const ParameterCount& arguments,
|
| Register name,
|
| ExtraICState extra_ic_state)
|
| @@ -1053,13 +1020,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| GenerateFastApiDirectCall(
|
| masm, optimization, arguments_.immediate(), false);
|
| } else {
|
| - CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
|
| - ? CALL_AS_FUNCTION
|
| - : CALL_AS_METHOD;
|
| Handle<JSFunction> function = optimization.constant_function();
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(function, expected, arguments_,
|
| - JUMP_FUNCTION, NullCallWrapper(), call_kind);
|
| + stub_compiler_->GenerateJumpFunctionIgnoreReceiver(function);
|
| }
|
|
|
| // Deferred code for fast API call case, clean preallocated space.
|
| @@ -1124,7 +1086,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
|
| interceptor_succeeded);
|
| }
|
|
|
| - StubCompiler* stub_compiler_;
|
| + CallStubCompiler* stub_compiler_;
|
| const ParameterCount& arguments_;
|
| Register name_;
|
| ExtraICState extra_ic_state_;
|
| @@ -1569,6 +1531,14 @@ void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
|
| }
|
|
|
|
|
| +void CallStubCompiler::GenerateFunctionCheck(Register function,
|
| + Register scratch,
|
| + Label* miss) {
|
| + __ JumpIfSmi(function, miss);
|
| + __ JumpIfNotObjectType(function, scratch, scratch, JS_FUNCTION_TYPE, miss);
|
| +}
|
| +
|
| +
|
| // Load the function object into x1 register.
|
| void CallStubCompiler::GenerateLoadFunctionFromCell(
|
| Handle<Cell> cell,
|
| @@ -1586,8 +1556,7 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(
|
| // the nice side effect that multiple closures based on the same
|
| // function can all use this call IC. Before we load through the
|
| // function, we have to verify that it still is a function.
|
| - __ JumpIfSmi(function_reg, miss);
|
| - __ JumpIfNotObjectType(function_reg, x3, x3, JS_FUNCTION_TYPE, miss);
|
| + GenerateFunctionCheck(function_reg, x3, miss);
|
|
|
| // Check the shared function info. Make sure it hasn't changed.
|
| __ Mov(x3, Operand(Handle<SharedFunctionInfo>(function->shared())));
|
| @@ -1605,7 +1574,7 @@ void CallStubCompiler::GenerateMissBranch() {
|
| Handle<Code> code =
|
| isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
|
| kind_,
|
| - extra_state_);
|
| + extra_state());
|
| __ Jump(code, RelocInfo::CODE_TARGET);
|
| }
|
|
|
| @@ -1615,7 +1584,6 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
|
| PropertyIndex index,
|
| Handle<Name> name) {
|
| Label miss;
|
| - Register receiver = x0;
|
| Register function = x1;
|
|
|
| Register holder_reg = HandlerFrontendHeader(
|
| @@ -1625,9 +1593,7 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
|
| index.is_inobject(holder),
|
| index.translate(holder),
|
| Representation::Tagged());
|
| -
|
| - GenerateCallFunction(
|
| - masm(), object, arguments(), &miss, extra_state_, function, receiver, x3);
|
| + GenerateJumpFunction(object, function, &miss);
|
|
|
| HandlerFrontendFooter(&miss);
|
|
|
| @@ -1676,10 +1642,12 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall(
|
| Handle<JSFunction> function,
|
| Handle<String> name,
|
| Code::StubType type) {
|
| - // If object is not an array or is observed, bail out to regular call.
|
| + // If object is not an array or is observed or sealed, bail out to regular
|
| + // call.
|
| if (!object->IsJSArray() ||
|
| !cell.is_null() ||
|
| - Handle<JSArray>::cast(object)->map()->is_observed()) {
|
| + Handle<JSArray>::cast(object)->map()->is_observed() ||
|
| + !Handle<JSArray>::cast(object)->map()->is_extensible()) {
|
| return Handle<Code>::null();
|
| }
|
|
|
| @@ -1935,10 +1903,12 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
|
| Handle<JSFunction> function,
|
| Handle<String> name,
|
| Code::StubType type) {
|
| - // If object is not an array or is observed, bail out to regular call.
|
| + // If object is not an array or is observed or sealed, bail out to regular
|
| + // call.
|
| if (!object->IsJSArray() ||
|
| !cell.is_null() ||
|
| - Handle<JSArray>::cast(object)->map()->is_observed()) {
|
| + Handle<JSArray>::cast(object)->map()->is_observed() ||
|
| + !Handle<JSArray>::cast(object)->map()->is_extensible()) {
|
| return Handle<Code>::null();
|
| }
|
|
|
| @@ -2014,7 +1984,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
| Label* index_out_of_range_label = &index_out_of_range;
|
|
|
| if (kind_ == Code::CALL_IC &&
|
| - (CallICBase::StringStubState::decode(extra_state_) ==
|
| + (CallICBase::StringStubState::decode(extra_state()) ==
|
| DEFAULT_STRING_STUB)) {
|
| index_out_of_range_label = &miss;
|
| }
|
| @@ -2057,8 +2027,7 @@ Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
| __ Bind(&miss);
|
| // Restore function name in x2.
|
| __ Mov(x2, Operand(name));
|
| - __ Bind(&name_miss);
|
| - GenerateMissBranch();
|
| + HandlerFrontendFooter(&name_miss);
|
|
|
| // Return the generated code.
|
| return GetCode(type, name);
|
| @@ -2082,7 +2051,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
| Label* index_out_of_range_label = &index_out_of_range;
|
|
|
| if (kind_ == Code::CALL_IC &&
|
| - (CallICBase::StringStubState::decode(extra_state_) ==
|
| + (CallICBase::StringStubState::decode(extra_state()) ==
|
| DEFAULT_STRING_STUB)) {
|
| index_out_of_range_label = &miss;
|
| }
|
| @@ -2126,8 +2095,7 @@ Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
| __ Bind(&miss);
|
| // Restore function name in x2.
|
| __ Mov(x2, Operand(name));
|
| - __ Bind(&name_miss);
|
| - GenerateMissBranch();
|
| + HandlerFrontendFooter(&name_miss);
|
|
|
| // Return the generated code.
|
| return GetCode(type, name);
|
| @@ -2175,12 +2143,10 @@ Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
|
| StubRuntimeCallHelper call_helper;
|
| generator.GenerateSlow(masm(), call_helper);
|
|
|
| - // Tail call the full function. We do not have to patch the receiver
|
| - // because the function makes no use of it.
|
| __ Bind(&slow);
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(function, expected, arguments(),
|
| - JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
|
| + // We do not have to patch the receiver because the function makes no use of
|
| + // it.
|
| + GenerateJumpFunctionIgnoreReceiver(function);
|
|
|
| HandlerFrontendFooter(&miss);
|
|
|
| @@ -2275,11 +2241,9 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
|
| __ Ret();
|
|
|
| __ Bind(&slow);
|
| - // Tail call the full function. We do not have to patch the receiver
|
| - // because the function makes no use of it.
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(function, expected, arguments(),
|
| - JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
|
| + // We do not have to patch the receiver because the function makes no use of
|
| + // it.
|
| + GenerateJumpFunctionIgnoreReceiver(function);
|
|
|
| HandlerFrontendFooter(&miss);
|
|
|
| @@ -2343,12 +2307,10 @@ Handle<Code> CallStubCompiler::CompileMathAbsCall(
|
| __ Drop(argc + 1);
|
| __ Ret();
|
|
|
| - // Tail call the full function. We do not have to patch the receiver
|
| - // because the function makes no use of it.
|
| __ Bind(&slow);
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(function, expected, arguments(),
|
| - JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
|
| + // We do not have to patch the receiver because the function makes no use of
|
| + // it.
|
| + GenerateJumpFunctionIgnoreReceiver(function);
|
|
|
| HandlerFrontendFooter(&miss);
|
|
|
| @@ -2402,8 +2364,7 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
|
| __ Bind(&miss);
|
| FreeSpaceForFastApiCall(masm());
|
|
|
| - __ Bind(&miss_before_stack_reserved);
|
| - GenerateMissBranch();
|
| + HandlerFrontendFooter(&miss_before_stack_reserved);
|
|
|
| // Return the generated code.
|
| return GetCode(function);
|
| @@ -2517,39 +2478,17 @@ Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
|
| }
|
|
|
|
|
| -void CallStubCompiler::CompileHandlerBackend(Handle<JSFunction> function) {
|
| - CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
| - ? CALL_AS_FUNCTION
|
| - : CALL_AS_METHOD;
|
| - ParameterCount expected(function);
|
| - __ InvokeFunction(function, expected, arguments(),
|
| - JUMP_FUNCTION, NullCallWrapper(), call_kind);
|
| -}
|
| -
|
| -
|
| -Handle<Code> CallStubCompiler::CompileCallConstant(
|
| - Handle<Object> object,
|
| - Handle<JSObject> holder,
|
| - Handle<Name> name,
|
| - CheckType check,
|
| - Handle<JSFunction> function) {
|
| - if (HasCustomCallGenerator(function)) {
|
| - Handle<Code> code = CompileCustomCall(object, holder,
|
| - Handle<Cell>::null(),
|
| - function, Handle<String>::cast(name),
|
| - Code::FAST);
|
| - // A null handle means bail out to the regular compiler code below.
|
| - if (!code.is_null()) return code;
|
| - }
|
| -
|
| - Label miss;
|
| - HandlerFrontendHeader(object, holder, name, check, &miss);
|
| +void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
|
| + Register function,
|
| + Label* miss) {
|
| + ASSERT(function.Is(x1));
|
| + // Check that the function really is a function.
|
| + GenerateFunctionCheck(function, x3, miss);
|
| PatchGlobalProxy(object);
|
| - CompileHandlerBackend(function);
|
| - HandlerFrontendFooter(&miss);
|
|
|
| - // Return the generated code.
|
| - return GetCode(function);
|
| + // Invoke the function.
|
| + __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
|
| + NullCallWrapper(), call_kind());
|
| }
|
|
|
|
|
| @@ -2569,7 +2508,7 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
|
| Register receiver = x5;
|
| __ Peek(receiver, argc * kPointerSize);
|
|
|
| - CallInterceptorCompiler compiler(this, arguments(), name_reg, extra_state_);
|
| + CallInterceptorCompiler compiler(this, arguments(), name_reg, extra_state());
|
| compiler.Compile(
|
| masm(), object, holder, name, &lookup, receiver, x3, x4, x0, &miss);
|
|
|
| @@ -2581,12 +2520,9 @@ Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
|
| // Restore receiver.
|
| __ Peek(receiver, argc * kPointerSize);
|
|
|
| - GenerateCallFunction(
|
| - masm(), object, arguments(), &miss, extra_state_, function, receiver, x3);
|
| + GenerateJumpFunction(object, x1, &miss);
|
|
|
| - // Handle call cache miss.
|
| - __ Bind(&miss);
|
| - GenerateMissBranch();
|
| + HandlerFrontendFooter(&miss);
|
|
|
| // Return the generated code.
|
| return GetCode(Code::FAST, name);
|
| @@ -2609,29 +2545,15 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
|
|
|
| Label miss;
|
| HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
|
| + // Potentially loads a closure that matches the shared function info of the
|
| + // function, rather than function.
|
| GenerateLoadFunctionFromCell(cell, function, &miss);
|
| // After these two calls the receiver is left in x0 and the function in x1.
|
| Register function_reg = x1;
|
|
|
| - PatchGlobalProxy(object);
|
| -
|
| - // Set up the context.
|
| - __ Ldr(cp, FieldMemOperand(function_reg, JSFunction::kContextOffset));
|
| -
|
| - // Jump to the cached code (tail call).
|
| Counters* counters = isolate()->counters();
|
| __ IncrementCounter(counters->call_global_inline(), 1, x3, x4);
|
| - ParameterCount expected(function->shared()->formal_parameter_count());
|
| - CallKind call_kind = CallICBase::Contextual::decode(extra_state_)
|
| - ? CALL_AS_FUNCTION
|
| - : CALL_AS_METHOD;
|
| - // We call indirectly through the code field in the function to
|
| - // allow recompilation to take effect without changing any of the
|
| - // call sites.
|
| - __ Ldr(x3, FieldMemOperand(function_reg, JSFunction::kCodeEntryOffset));
|
| - __ InvokeCode(
|
| - x3, expected, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind);
|
| -
|
| + GenerateJumpFunction(object, function_reg, function);
|
| HandlerFrontendFooter(&miss);
|
|
|
| // Return the generated code.
|
|
|