Register prototype,
Label* miss) {
Isolate* isolate = masm->isolate();
- // Check we're still in the same context.
- __ Move(prototype, isolate->global_object());
- __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)),
- prototype);
- __ j(not_equal, miss);
// Get the global function with the given index.
Handle<JSFunction> function(
JSFunction::cast(isolate->native_context()->get(index)));
+
+ // Check we're still in the same context.
+ Register scratch = prototype;
+ const int offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX);
+ __ movp(scratch, Operand(rsi, offset));
+ __ movp(scratch, FieldOperand(scratch, GlobalObject::kNativeContextOffset));
+ __ Cmp(Operand(scratch, Context::SlotOffset(index)), function);
+ __ j(not_equal, miss);
+
// Load its initial map. The global functions all have initial maps.
__ Move(prototype, Handle<Map>(function->initial_map()));
// Load the prototype from the initial map.
}
-// Number of pointers to be reserved on stack for fast API call.
-static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
-
-
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Register holder,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- bool restore_context);
-
-
-// Generates call to API function.
-static void GenerateFastApiCall(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Handle<Map> map_to_holder,
- CallOptimization::HolderLookup holder_lookup) {
- Counters* counters = masm->isolate()->counters();
- __ IncrementCounter(counters->call_const_fast_api(), 1);
-
- // Move holder to a register
- Register holder_reg = rax;
- switch (holder_lookup) {
- case CallOptimization::kHolderIsReceiver:
- {
- ASSERT(map_to_holder.is_null());
- StackArgumentsAccessor args(rsp, argc);
- __ movp(holder_reg, args.GetReceiverOperand());
- }
- break;
- case CallOptimization::kHolderIsPrototypeOfMap:
- {
- Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
- if (!masm->isolate()->heap()->InNewSpace(*holder)) {
- __ Move(holder_reg, holder);
- } else {
- __ Move(holder_reg, map_to_holder);
- __ movp(holder_reg, FieldOperand(holder_reg, Map::kPrototypeOffset));
- }
- }
- break;
- case CallOptimization::kHolderNotFound:
- UNREACHABLE();
- }
- GenerateFastApiCallBody(masm,
- optimization,
- argc,
- holder_reg,
- rbx,
- rcx,
- rdx,
- false);
-}
-
-
// Generate call to api function.
-// This function uses push() to generate smaller, faster code than
-// the version above. It is an optimization that should will be removed
-// when api call ICs are generated in hydrogen.
static void GenerateFastApiCall(MacroAssembler* masm,
const CallOptimization& optimization,
+ Handle<Map> receiver_map,
Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
+ Register scratch_in,
int argc,
Register* values) {
- __ PopReturnAddressTo(scratch1);
+ ASSERT(optimization.is_simple_api_call());
+
+ __ PopReturnAddressTo(scratch_in);
// receiver
__ push(receiver);
// Write the arguments to stack frame.
for (int i = 0; i < argc; i++) {
Register arg = values[argc-1-i];
ASSERT(!receiver.is(arg));
- ASSERT(!scratch1.is(arg));
- ASSERT(!scratch2.is(arg));
- ASSERT(!scratch3.is(arg));
+ ASSERT(!scratch_in.is(arg));
__ push(arg);
}
- __ PushReturnAddressFrom(scratch1);
+ __ PushReturnAddressFrom(scratch_in);
// Stack now matches JSFunction abi.
- GenerateFastApiCallBody(masm,
- optimization,
- argc,
- receiver,
- scratch1,
- scratch2,
- scratch3,
- true);
-}
-
-
-static void GenerateFastApiCallBody(MacroAssembler* masm,
- const CallOptimization& optimization,
- int argc,
- Register holder,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- bool restore_context) {
- // ----------- S t a t e -------------
- // -- rsp[0] : return address
- // -- rsp[8] : last argument
- // -- ...
- // -- rsp[argc * 8] : first argument
- // -- rsp[(argc + 1) * 8] : receiver
- // -----------------------------------
- ASSERT(optimization.is_simple_api_call());
- typedef FunctionCallbackArguments FCA;
-
- STATIC_ASSERT(FCA::kHolderIndex == 0);
- STATIC_ASSERT(FCA::kIsolateIndex == 1);
- STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
- STATIC_ASSERT(FCA::kReturnValueOffset == 3);
- STATIC_ASSERT(FCA::kDataIndex == 4);
- STATIC_ASSERT(FCA::kCalleeIndex == 5);
- STATIC_ASSERT(FCA::kContextSaveIndex == 6);
- STATIC_ASSERT(FCA::kArgsLength == 7);
-
- __ PopReturnAddressTo(scratch1);
-
- ASSERT(!holder.is(rsi));
- // context save
- __ push(rsi);
-
- // Get the function and setup the context.
- Handle<JSFunction> function = optimization.constant_function();
- __ Move(scratch2, function);
- __ push(scratch2);
+ // Abi for CallApiFunctionStub.
+ Register callee = rax;
+ Register call_data = rbx;
+ Register holder = rcx;
+ Register api_function_address = rdx;
+ Register scratch = rdi; // scratch_in is no longer valid.
+
+ // Put holder in place.
+ CallOptimization::HolderLookup holder_lookup;
+ Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
+ receiver_map,
+ &holder_lookup);
+ switch (holder_lookup) {
+ case CallOptimization::kHolderIsReceiver:
+ __ Move(holder, receiver);
+ break;
+ case CallOptimization::kHolderFound:
+ __ Move(holder, api_holder);
+ break;
+ case CallOptimization::kHolderNotFound:
+ UNREACHABLE();
+ break;
+ }
Isolate* isolate = masm->isolate();
+ Handle<JSFunction> function = optimization.constant_function();
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
- Handle<Object> call_data(api_call_info->data(), isolate);
- // Push data from ExecutableAccessorInfo.
+ Handle<Object> call_data_obj(api_call_info->data(), isolate);
+
+ // Put callee in place.
+ __ Move(callee, function);
+
bool call_data_undefined = false;
- if (isolate->heap()->InNewSpace(*call_data)) {
- __ Move(scratch2, api_call_info);
- __ movp(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
- } else if (call_data->IsUndefined()) {
+ // Put call_data in place.
+ if (isolate->heap()->InNewSpace(*call_data_obj)) {
+ __ Move(scratch, api_call_info);
+ __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset));
+ } else if (call_data_obj->IsUndefined()) {
call_data_undefined = true;
- __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
+ __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
} else {
- __ Move(scratch3, call_data);
- }
- // call data
- __ push(scratch3);
- if (!call_data_undefined) {
- __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
+ __ Move(call_data, call_data_obj);
}
- // return value
- __ push(scratch3);
- // return value default
- __ push(scratch3);
- // isolate
- __ Move(scratch3,
- ExternalReference::isolate_address(masm->isolate()));
- __ push(scratch3);
- // holder
- __ push(holder);
-
- ASSERT(!scratch1.is(rax));
- __ movp(rax, rsp);
- // Push return address back on stack.
- __ PushReturnAddressFrom(scratch1);
- // Function address is a foreign pointer outside V8's heap.
+ // Put api_function_address in place.
Address function_address = v8::ToCData<Address>(api_call_info->callback());
+ __ Move(
+ api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE);
- // Allocate the v8::Arguments structure in the arguments' space since
- // it's not controlled by GC.
- const int kApiStackSpace = 4;
-
- __ PrepareCallApiFunction(kApiStackSpace);
-
- __ movp(StackSpaceOperand(0), rax); // FunctionCallbackInfo::implicit_args_.
- __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
- __ movp(StackSpaceOperand(1), rax); // FunctionCallbackInfo::values_.
- __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_.
- // FunctionCallbackInfo::is_construct_call_.
- __ Set(StackSpaceOperand(3), 0);
-
-#if defined(__MINGW64__) || defined(_WIN64)
- Register arguments_arg = rcx;
- Register callback_arg = rdx;
-#else
- Register arguments_arg = rdi;
- Register callback_arg = rsi;
-#endif
-
- // v8::InvocationCallback's argument.
- __ lea(arguments_arg, StackSpaceOperand(0));
-
- Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
-
- StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments,
- ARGUMENTS_DONT_CONTAIN_RECEIVER);
- Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
- kFastApiCallArguments - 1 - FCA::kContextSaveIndex);
- Operand return_value_operand = args_from_rbp.GetArgumentOperand(
- kFastApiCallArguments - 1 - FCA::kReturnValueOffset);
- __ CallApiFunctionAndReturn(
- function_address,
- thunk_address,
- callback_arg,
- argc + kFastApiCallArguments + 1,
- return_value_operand,
- restore_context ? &context_restore_operand : NULL);
+ // Jump to stub.
+ CallApiFunctionStub stub(true, call_data_undefined, argc);
+ __ TailCallStub(&stub);
}
-class CallInterceptorCompiler BASE_EMBEDDED {
- public:
- CallInterceptorCompiler(CallStubCompiler* stub_compiler,
- const ParameterCount& arguments,
- Register name)
- : stub_compiler_(stub_compiler),
- arguments_(arguments),
- name_(name) {}
-
- void Compile(MacroAssembler* masm,
- Handle<JSObject> object,
- Handle<JSObject> holder,
- Handle<Name> name,
- LookupResult* lookup,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Label* miss) {
- ASSERT(holder->HasNamedInterceptor());
- ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, miss);
-
- CallOptimization optimization(lookup);
- if (optimization.is_constant_call()) {
- CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3,
- holder, lookup, name, optimization, miss);
- } else {
- CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3,
- name, holder, miss);
- }
- }
-
- private:
- void CompileCacheable(MacroAssembler* masm,
- Handle<JSObject> object,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Handle<JSObject> interceptor_holder,
- LookupResult* lookup,
- Handle<Name> name,
- const CallOptimization& optimization,
- Label* miss_label) {
- ASSERT(optimization.is_constant_call());
- ASSERT(!lookup->holder()->IsGlobalObject());
-
- Counters* counters = masm->isolate()->counters();
- __ IncrementCounter(counters->call_const_interceptor(), 1);
-
- // Check that the maps from receiver to interceptor's holder
- // haven't changed and thus we can invoke interceptor.
- Label miss_cleanup;
- Register holder =
- stub_compiler_->CheckPrototypes(
- IC::CurrentTypeOf(object, masm->isolate()), receiver,
- interceptor_holder, scratch1, scratch2, scratch3,
- name, miss_label);
-
- // Invoke an interceptor and if it provides a value,
- // branch to |regular_invoke|.
- Label regular_invoke;
- LoadWithInterceptor(masm, receiver, holder, interceptor_holder,
- ®ular_invoke);
-
- // Interceptor returned nothing for this property. Try to use cached
- // constant function.
-
- // Check that the maps from interceptor's holder to constant function's
- // holder haven't changed and thus we can use cached constant function.
- if (*interceptor_holder != lookup->holder()) {
- stub_compiler_->CheckPrototypes(
- IC::CurrentTypeOf(interceptor_holder, masm->isolate()), holder,
- handle(lookup->holder()), scratch1, scratch2, scratch3,
- name, miss_label);
- }
-
- Handle<Map> lookup_map;
- CallOptimization::HolderLookup holder_lookup =
- CallOptimization::kHolderNotFound;
- if (optimization.is_simple_api_call() &&
- !lookup->holder()->IsGlobalObject()) {
- lookup_map = optimization.LookupHolderOfExpectedType(
- object, object, interceptor_holder, &holder_lookup);
- if (holder_lookup == CallOptimization::kHolderNotFound) {
- lookup_map =
- optimization.LookupHolderOfExpectedType(
- object,
- interceptor_holder,
- Handle<JSObject>(lookup->holder()),
- &holder_lookup);
- }
- }
-
- // Invoke function.
- if (holder_lookup != CallOptimization::kHolderNotFound) {
- int argc = arguments_.immediate();
- GenerateFastApiCall(masm,
- optimization,
- argc,
- lookup_map,
- holder_lookup);
- } else {
- Handle<JSFunction> fun = optimization.constant_function();
- stub_compiler_->GenerateJumpFunction(object, fun);
- }
-
- // Invoke a regular function.
- __ bind(®ular_invoke);
- }
-
- void CompileRegular(MacroAssembler* masm,
- Handle<JSObject> object,
- Register receiver,
- Register scratch1,
- Register scratch2,
- Register scratch3,
- Handle<Name> name,
- Handle<JSObject> interceptor_holder,
- Label* miss_label) {
- Register holder =
- stub_compiler_->CheckPrototypes(
- IC::CurrentTypeOf(object, masm->isolate()), receiver,
- interceptor_holder, scratch1, scratch2, scratch3, name, miss_label);
-
- FrameScope scope(masm, StackFrame::INTERNAL);
- // Save the name_ register across the call.
- __ push(name_);
-
- CompileCallLoadPropertyWithInterceptor(
- masm, receiver, holder, name_, interceptor_holder,
- IC::kLoadPropertyWithInterceptorForCall);
-
- // Restore the name_ register.
- __ pop(name_);
-
- // Leave the internal frame.
- }
-
- void LoadWithInterceptor(MacroAssembler* masm,
- Register receiver,
- Register holder,
- Handle<JSObject> holder_obj,
- Label* interceptor_succeeded) {
- {
- FrameScope scope(masm, StackFrame::INTERNAL);
- __ push(receiver);
- __ push(holder);
- __ push(name_);
-
- CompileCallLoadPropertyWithInterceptor(
- masm, receiver, holder, name_, holder_obj,
- IC::kLoadPropertyWithInterceptorOnly);
-
- __ pop(name_);
- __ pop(holder);
- __ pop(receiver);
- // Leave the internal frame.
- }
-
- __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
- __ j(not_equal, interceptor_succeeded);
- }
-
- CallStubCompiler* stub_compiler_;
- const ParameterCount& arguments_;
- Register name_;
-};
-
-
void StoreStubCompiler::GenerateRestoreName(MacroAssembler* masm,
Label* label,
Handle<Name> name) {
void LoadStubCompiler::GenerateLoadCallback(
- const CallOptimization& call_optimization) {
+ const CallOptimization& call_optimization,
+ Handle<Map> receiver_map) {
GenerateFastApiCall(
- masm(), call_optimization, receiver(),
- scratch1(), scratch2(), name(), 0, NULL);
+ masm(), call_optimization, receiver_map,
+ receiver(), scratch1(), 0, NULL);
}
// Save a pointer to where we pushed the arguments pointer. This will be
// passed as the const PropertyAccessorInfo& to the C++ callback.
- Address getter_address = v8::ToCData<Address>(callback->getter());
-
-#if defined(__MINGW64__) || defined(_WIN64)
- Register getter_arg = r8;
- Register accessor_info_arg = rdx;
- Register name_arg = rcx;
-#else
- Register getter_arg = rdx;
- Register accessor_info_arg = rsi;
- Register name_arg = rdi;
-#endif
-
- ASSERT(!name_arg.is(scratch4()));
- __ movp(name_arg, rsp);
__ PushReturnAddressFrom(scratch4());
- // v8::Arguments::values_ and handler for name.
- const int kStackSpace = PropertyCallbackArguments::kArgsLength + 1;
-
- // Allocate v8::AccessorInfo in non-GCed stack space.
- const int kArgStackSpace = 1;
-
- __ PrepareCallApiFunction(kArgStackSpace);
- __ lea(rax, Operand(name_arg, 1 * kPointerSize));
-
- // v8::PropertyAccessorInfo::args_.
- __ movp(StackSpaceOperand(0), rax);
-
- // The context register (rsi) has been saved in PrepareCallApiFunction and
- // could be used to pass arguments.
- __ lea(accessor_info_arg, StackSpaceOperand(0));
-
- Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
+ // Abi for CallApiGetter
+ Register api_function_address = r8;
+ Address getter_address = v8::ToCData<Address>(callback->getter());
+ __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE);
- // The name handler is counted as an argument.
- StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength);
- Operand return_value_operand = args.GetArgumentOperand(
- PropertyCallbackArguments::kArgsLength - 1 -
- PropertyCallbackArguments::kReturnValueOffset);
- __ CallApiFunctionAndReturn(getter_address,
- thunk_address,
- getter_arg,
- kStackSpace,
- return_value_operand,
- NULL);
+ CallApiGetterStub stub;
+ __ TailCallStub(&stub);
}
}
-void CallStubCompiler::GenerateNameCheck(Handle<Name> name, Label* miss) {
- if (kind_ == Code::KEYED_CALL_IC) {
- __ Cmp(rcx, name);
- __ j(not_equal, miss);
- }
-}
-
-
-void CallStubCompiler::GenerateFunctionCheck(Register function,
- Register scratch,
- Label* miss) {
- __ JumpIfSmi(function, miss);
- __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch);
- __ j(not_equal, miss);
-}
-
-
-void CallStubCompiler::GenerateLoadFunctionFromCell(
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Label* miss) {
- // Get the value from the cell.
- __ Move(rdi, cell);
- __ movp(rdi, FieldOperand(rdi, Cell::kValueOffset));
-
- // Check that the cell contains the same function.
- if (heap()->InNewSpace(*function)) {
- // We can't embed a pointer to a function in new space so we have
- // to verify that the shared function info is unchanged. This has
- // 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.
- GenerateFunctionCheck(rdi, rax, miss);
-
- // Check the shared function info. Make sure it hasn't changed.
- __ Move(rax, Handle<SharedFunctionInfo>(function->shared()));
- __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
- } else {
- __ Cmp(rdi, function);
- }
- __ j(not_equal, miss);
-}
-
-
-void CallStubCompiler::GenerateMissBranch() {
- Handle<Code> code =
- isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(),
- kind_,
- extra_state());
- __ Jump(code, RelocInfo::CODE_TARGET);
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
- Handle<JSObject> holder,
- PropertyIndex index,
- Handle<Name> name) {
- Label miss;
-
- Register reg = HandlerFrontendHeader(
- object, holder, name, RECEIVER_MAP_CHECK, &miss);
-
- GenerateFastPropertyLoad(masm(), rdi, reg, index.is_inobject(holder),
- index.translate(holder), Representation::Tagged());
- GenerateJumpFunction(object, rdi, &miss);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(Code::FAST, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileFastApiCall(
- const CallOptimization& optimization,
- Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Cell> cell,
- Handle<JSFunction> function,
- Handle<String> name) {
- ASSERT(optimization.is_simple_api_call());
- // Bail out if object is a global object as we don't want to
- // repatch it to global receiver.
- if (object->IsGlobalObject()) return Handle<Code>::null();
- if (!cell.is_null()) return Handle<Code>::null();
- if (!object->IsJSObject()) return Handle<Code>::null();
- Handle<JSObject> receiver = Handle<JSObject>::cast(object);
- CallOptimization::HolderLookup holder_lookup =
- CallOptimization::kHolderNotFound;
- Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
- receiver, receiver, holder, &holder_lookup);
- if (holder_lookup == CallOptimization::kHolderNotFound) {
- return Handle<Code>::null();
- }
-
- Label miss;
- GenerateNameCheck(name, &miss);
-
- const int argc = arguments().immediate();
- StackArgumentsAccessor args(rsp, argc);
- __ movp(rdx, args.GetReceiverOperand());
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(rdx, &miss);
-
- Counters* counters = isolate()->counters();
- __ IncrementCounter(counters->call_const(), 1);
-
- // Check that the maps haven't changed and find a Holder as a side effect.
- CheckPrototypes(IC::CurrentTypeOf(object, isolate()), rdx, holder,
- rbx, rax, rdi, name, &miss);
-
- GenerateFastApiCall(masm(), optimization, argc, lookup_map, holder_lookup);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(function);
-}
-
-
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success;
// Check that the object is a boolean.
- __ CompareRoot(object, Heap::kTrueValueRootIndex);
+ __ Cmp(object, factory()->true_value());
__ j(equal, &success);
- __ CompareRoot(object, Heap::kFalseValueRootIndex);
+ __ Cmp(object, factory()->false_value());
__ j(not_equal, miss);
__ bind(&success);
}
-void CallStubCompiler::PatchImplicitReceiver(Handle<Object> object) {
- if (object->IsGlobalObject()) {
- StackArgumentsAccessor args(rsp, arguments());
- __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
- __ movp(args.GetReceiverOperand(), rdx);
- }
-}
-
-
-Register CallStubCompiler::HandlerFrontendHeader(Handle<Object> object,
- Handle<JSObject> holder,
- Handle<Name> name,
- CheckType check,
- Label* miss) {
- GenerateNameCheck(name, miss);
-
- Register reg = rdx;
-
- StackArgumentsAccessor args(rsp, arguments());
- __ movp(reg, args.GetReceiverOperand());
-
- // Check that the receiver isn't a smi.
- if (check != NUMBER_CHECK) {
- __ JumpIfSmi(reg, miss);
- }
-
- // Make sure that it's okay not to patch the on stack receiver
- // unless we're doing a receiver map check.
- ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
-
- Counters* counters = isolate()->counters();
- switch (check) {
- case RECEIVER_MAP_CHECK:
- __ IncrementCounter(counters->call_const(), 1);
-
- // Check that the maps haven't changed.
- reg = CheckPrototypes(IC::CurrentTypeOf(object, isolate()), reg, holder,
- rbx, rax, rdi, name, miss);
- break;
-
- case STRING_CHECK: {
- // Check that the object is a string.
- __ CmpObjectType(reg, FIRST_NONSTRING_TYPE, rax);
- __ j(above_equal, miss);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::STRING_FUNCTION_INDEX, rax, miss);
- break;
- }
- case SYMBOL_CHECK: {
- // Check that the object is a symbol.
- __ CmpObjectType(reg, SYMBOL_TYPE, rax);
- __ j(not_equal, miss);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::SYMBOL_FUNCTION_INDEX, rax, miss);
- break;
- }
- case NUMBER_CHECK: {
- Label fast;
- // Check that the object is a smi or a heap number.
- __ JumpIfSmi(reg, &fast);
- __ CmpObjectType(reg, HEAP_NUMBER_TYPE, rax);
- __ j(not_equal, miss);
- __ bind(&fast);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::NUMBER_FUNCTION_INDEX, rax, miss);
- break;
- }
- case BOOLEAN_CHECK: {
- GenerateBooleanCheck(reg, miss);
- // Check that the maps starting from the prototype haven't changed.
- GenerateDirectLoadGlobalFunctionPrototype(
- masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, miss);
- break;
- }
- }
-
- if (check != RECEIVER_MAP_CHECK) {
- Handle<Object> prototype(object->GetPrototype(isolate()), isolate());
- reg = CheckPrototypes(
- IC::CurrentTypeOf(prototype, isolate()),
- rax, holder, rbx, rdx, rdi, name, miss);
- }
-
- return reg;
-}
-
-
-void CallStubCompiler::GenerateJumpFunction(Handle<Object> object,
- Register function,
- Label* miss) {
- // Check that the function really is a function.
- GenerateFunctionCheck(function, rbx, miss);
-
- if (!function.is(rdi)) __ movp(rdi, function);
- PatchImplicitReceiver(object);
-
- // Invoke the function.
- __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, NullCallWrapper());
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object,
- Handle<JSObject> holder,
- Handle<Name> name) {
- Label miss;
- GenerateNameCheck(name, &miss);
-
- LookupResult lookup(isolate());
- LookupPostInterceptor(holder, name, &lookup);
-
- // Get the receiver from the stack.
- StackArgumentsAccessor args(rsp, arguments());
- __ movp(rdx, args.GetReceiverOperand());
-
- CallInterceptorCompiler compiler(this, arguments(), rcx);
- compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax,
- &miss);
-
- // Restore receiver.
- __ movp(rdx, args.GetReceiverOperand());
-
- GenerateJumpFunction(object, rax, &miss);
-
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(Code::FAST, name);
-}
-
-
-Handle<Code> CallStubCompiler::CompileCallGlobal(
- Handle<JSObject> object,
- Handle<GlobalObject> holder,
- Handle<PropertyCell> cell,
- Handle<JSFunction> function,
- Handle<Name> name) {
- if (HasCustomCallGenerator(function)) {
- Handle<Code> code = CompileCustomCall(
- object, holder, cell, function, Handle<String>::cast(name),
- Code::NORMAL);
- // A null handle means bail out to the regular compiler code below.
- if (!code.is_null()) return code;
- }
-
- 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);
- Counters* counters = isolate()->counters();
- __ IncrementCounter(counters->call_global_inline(), 1);
- GenerateJumpFunction(object, rdi, function);
- HandlerFrontendFooter(&miss);
-
- // Return the generated code.
- return GetCode(Code::NORMAL, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<JSObject> object,
Handle<JSObject> holder,
Register values[] = { value() };
GenerateFastApiCall(
- masm(), call_optimization, receiver(), scratch1(),
- scratch2(), this->name(), 1, values);
+ masm(), call_optimization, handle(object->map()),
+ receiver(), scratch1(), 1, values);
// Return the generated code.
return GetCode(kind(), Code::FAST, name);
void StoreStubCompiler::GenerateStoreViaSetter(
MacroAssembler* masm,
+ Handle<HeapType> type,
Handle<JSFunction> setter) {
// ----------- S t a t e -------------
// -- rax : value
// -----------------------------------
{
FrameScope scope(masm, StackFrame::INTERNAL);
+ Register receiver = rdx;
+ Register value = rax;
// Save value register, so we can restore it later.
- __ push(rax);
+ __ push(value);
if (!setter.is_null()) {
// Call the JavaScript setter with receiver and value on the stack.
- __ push(rdx);
- __ push(rax);
+ if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
+ // Swap in the global receiver.
+ __ movp(receiver,
+ FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
+ }
+ __ push(receiver);
+ __ push(value);
ParameterCount actual(1);
ParameterCount expected(setter);
__ InvokeFunction(setter, expected, actual,
void LoadStubCompiler::GenerateLoadViaGetter(MacroAssembler* masm,
+ Handle<HeapType> type,
Register receiver,
Handle<JSFunction> getter) {
// ----------- S t a t e -------------
if (!getter.is_null()) {
// Call the JavaScript getter with the receiver on the stack.
+ if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
+ // Swap in the global receiver.
+ __ movp(receiver,
+ FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
+ }
__ push(receiver);
ParameterCount actual(0);
ParameterCount expected(getter);
__ Check(not_equal, kDontDeleteCellsCannotContainTheHole);
}
- HandlerFrontendFooter(name, &miss);
-
Counters* counters = isolate()->counters();
__ IncrementCounter(counters->named_load_global_stub(), 1);
__ movp(rax, rbx);
__ ret(0);
+ HandlerFrontendFooter(name, &miss);
+
// Return the generated code.
return GetCode(kind(), Code::NORMAL, name);
}