Fix a number of IC stubs to correctly set the call kind.

Make the call kind and call wrapper arguments explicit to force
developers to make a choice. This would have avoided the bug in the
first case.

R=fschneider@chromium.org
TEST=mjsunit/strict-mode-implicit-receiver.js

Review URL: http://codereview.chromium.org/7086029

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8109 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ager@chromium.org 2011-05-30 13:23:17 +00:00
parent 5083dec67f
commit cc4a2d7e76
28 changed files with 307 additions and 142 deletions

View File

@ -915,10 +915,11 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
masm->isolate()->builtins()->HandleApiCallConstruct();
ParameterCount expected(0);
__ InvokeCode(code, expected, expected,
RelocInfo::CODE_TARGET, CALL_FUNCTION);
RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD);
} else {
ParameterCount actual(r0);
__ InvokeFunction(r1, actual, CALL_FUNCTION);
__ InvokeFunction(r1, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// Pop the function from the stack.
@ -1050,7 +1051,8 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
RelocInfo::CODE_TARGET);
} else {
ParameterCount actual(r0);
__ InvokeFunction(r1, actual, CALL_FUNCTION);
__ InvokeFunction(r1, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// Exit the JS frame and remove the parameters (except function), and return.
@ -1379,7 +1381,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
ne);
ParameterCount expected(0);
__ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
__ InvokeCode(r3, expected, expected, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
@ -1515,7 +1518,8 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
ParameterCount actual(r0);
__ mov(r0, Operand(r0, ASR, kSmiTagSize));
__ ldr(r1, MemOperand(fp, kFunctionOffset));
__ InvokeFunction(r1, actual, CALL_FUNCTION);
__ InvokeFunction(r1, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
// Tear down the internal frame and remove function, receiver and args.
__ LeaveInternalFrame();

View File

@ -4540,7 +4540,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
Label call_as_function;
__ CompareRoot(r4, Heap::kTheHoleValueRootIndex);
__ b(eq, &call_as_function);
__ InvokeFunction(r1, actual, JUMP_FUNCTION);
__ InvokeFunction(r1,
actual,
JUMP_FUNCTION,
NullCallWrapper(),
CALL_AS_METHOD);
__ bind(&call_as_function);
}
__ InvokeFunction(r1,

View File

@ -3175,7 +3175,8 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
// InvokeFunction requires the function in r1. Move it in there.
__ mov(r1, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(r1, count, CALL_FUNCTION);
__ InvokeFunction(r1, count, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
context()->Plug(r0);
}

View File

@ -557,7 +557,8 @@ static void GenerateFunctionTailCall(MacroAssembler* masm,
// Invoke the function.
ParameterCount actual(argc);
__ InvokeFunction(r1, actual, JUMP_FUNCTION);
__ InvokeFunction(r1, actual, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}

View File

@ -2707,6 +2707,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(function.is(r1)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(r0));
// TODO(1412): This is not correct if the called function is a
// strict mode function or a native.
//
// If the receiver is null or undefined, we have to pass the global object
// as a receiver.
Label global_object, receiver_ok;
@ -2726,6 +2729,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
__ bind(&global_object);
__ ldr(receiver, GlobalObjectOperand());
__ ldr(receiver,
FieldMemOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
__ bind(&receiver_ok);
// Copy the arguments to this function possibly from the
@ -2765,7 +2770,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// The number of arguments is stored in receiver which is r0, as expected
// by InvokeFunction.
v8::internal::ParameterCount actual(receiver);
__ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}
@ -3213,7 +3219,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator generator(this, pointers, env->deoptimization_index());
ParameterCount count(instr->arity());
__ InvokeFunction(r1, count, CALL_FUNCTION, generator);
__ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
__ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
}

View File

@ -1048,7 +1048,8 @@ void MacroAssembler::InvokeFunction(Register fun,
void MacroAssembler::InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag) {
InvokeFlag flag,
CallKind call_kind) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
@ -1063,9 +1064,9 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
// code field in the function to allow recompilation to take effect
// without changing any of the call sites.
ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
InvokeCode(r3, expected, actual, flag);
InvokeCode(r3, expected, actual, flag, NullCallWrapper(), call_kind);
} else {
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag);
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag, call_kind);
}
}
@ -2369,10 +2370,12 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
GetBuiltinEntry(r2, id);
if (flag == CALL_FUNCTION) {
call_wrapper.BeforeCall(CallSize(r2));
SetCallKind(r5, CALL_AS_METHOD);
Call(r2);
call_wrapper.AfterCall();
} else {
ASSERT(flag == JUMP_FUNCTION);
SetCallKind(r5, CALL_AS_METHOD);
Jump(r2);
}
}

View File

@ -356,27 +356,28 @@ class MacroAssembler: public Assembler {
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeCode(Handle<Code> code,
const ParameterCount& expected,
const ParameterCount& actual,
RelocInfo::Mode rmode,
InvokeFlag flag,
CallKind call_kind = CALL_AS_METHOD);
CallKind call_kind);
// Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking.
void InvokeFunction(Register function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag);
InvokeFlag flag,
CallKind call_kind);
void IsObjectJSObjectType(Register heap_object,
Register map,
@ -1036,8 +1037,8 @@ class MacroAssembler: public Assembler {
Register code_reg,
Label* done,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
// Activation support.
void EnterFrame(StackFrame::Type type);

View File

@ -476,7 +476,8 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
static void GenerateCallFunction(MacroAssembler* masm,
Object* object,
const ParameterCount& arguments,
Label* miss) {
Label* miss,
Code::ExtraICState extra_ic_state) {
// ----------- S t a t e -------------
// -- r0: receiver
// -- r1: function to call
@ -495,7 +496,10 @@ static void GenerateCallFunction(MacroAssembler* masm,
}
// Invoke the function.
__ InvokeFunction(r1, arguments, JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
@ -625,10 +629,12 @@ class CallInterceptorCompiler BASE_EMBEDDED {
public:
CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments,
Register name)
Register name,
Code::ExtraICState extra_ic_state)
: stub_compiler_(stub_compiler),
arguments_(arguments),
name_(name) {}
name_(name),
extra_ic_state_(extra_ic_state) {}
MaybeObject* Compile(MacroAssembler* masm,
JSObject* object,
@ -756,8 +762,11 @@ class CallInterceptorCompiler BASE_EMBEDDED {
arguments_.immediate());
if (result->IsFailure()) return result;
} else {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION);
JUMP_FUNCTION, call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@ -839,6 +848,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
Register name_;
Code::ExtraICState extra_ic_state_;
};
@ -1492,7 +1502,7 @@ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
GenerateCallFunction(masm(), object, arguments(), &miss);
GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_);
// Handle call cache miss.
__ bind(&miss);
@ -1992,7 +2002,7 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
@ -2140,7 +2150,7 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
__ bind(&slow);
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
@ -2242,7 +2252,7 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
__ bind(&miss);
// r2: function name.
@ -2430,7 +2440,10 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
UNREACHABLE();
}
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind);
// Handle call cache miss.
__ bind(&miss);
@ -2463,7 +2476,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the receiver from the stack.
__ ldr(r1, MemOperand(sp, argc * kPointerSize));
CallInterceptorCompiler compiler(this, arguments(), r2);
CallInterceptorCompiler compiler(this, arguments(), r2, extra_ic_state_);
MaybeObject* result = compiler.Compile(masm(),
object,
holder,
@ -2483,7 +2496,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Restore receiver.
__ ldr(r0, MemOperand(sp, argc * kPointerSize));
GenerateCallFunction(masm(), object, arguments(), &miss);
GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_);
// Handle call cache miss.
__ bind(&miss);
@ -2495,13 +2508,11 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
}
MaybeObject* CallStubCompiler::CompileCallGlobal(
JSObject* object,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name,
Code::ExtraICState extra_ic_state) {
MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name) {
// ----------- S t a t e -------------
// -- r2 : name
// -- lr : return address
@ -2543,7 +2554,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(
ASSERT(function->is_compiled());
Handle<Code> code(function->code());
ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
if (V8::UseCrankshaft()) {

View File

@ -340,11 +340,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Handle<Code> code =
masm->isolate()->builtins()->HandleApiCallConstruct();
ParameterCount expected(0);
__ InvokeCode(code, expected, expected,
RelocInfo::CODE_TARGET, CALL_FUNCTION);
__ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
ParameterCount actual(eax);
__ InvokeFunction(edi, actual, CALL_FUNCTION);
__ InvokeFunction(edi, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// Restore context from the frame.
@ -443,7 +444,8 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
RelocInfo::CODE_TARGET);
} else {
ParameterCount actual(eax);
__ InvokeFunction(edi, actual, CALL_FUNCTION);
__ InvokeFunction(edi, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// Exit the JS frame. Notice that this also removes the empty
@ -715,7 +717,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
masm->isolate()->builtins()->ArgumentsAdaptorTrampoline());
ParameterCount expected(0);
__ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION);
__ InvokeCode(Operand(edx), expected, expected, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
@ -845,7 +848,8 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
ParameterCount actual(eax);
__ SmiUntag(eax);
__ mov(edi, Operand(ebp, 4 * kPointerSize));
__ InvokeFunction(edi, actual, CALL_FUNCTION);
__ InvokeFunction(edi, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ LeaveInternalFrame();
__ ret(3 * kPointerSize); // remove this, receiver, and arguments

View File

@ -3981,7 +3981,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
Label call_as_function;
__ cmp(eax, masm->isolate()->factory()->the_hole_value());
__ j(equal, &call_as_function);
__ InvokeFunction(edi, actual, JUMP_FUNCTION);
__ InvokeFunction(edi,
actual,
JUMP_FUNCTION,
NullCallWrapper(),
CALL_AS_METHOD);
__ bind(&call_as_function);
}
__ InvokeFunction(edi,

View File

@ -3115,7 +3115,8 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
// InvokeFunction requires the function in edi. Move it in there.
__ mov(edi, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(edi, count, CALL_FUNCTION);
__ InvokeFunction(edi, count, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
context()->Plug(eax);
}

View File

@ -877,7 +877,8 @@ static void GenerateFunctionTailCall(MacroAssembler* masm,
// Invoke the function.
ParameterCount actual(argc);
__ InvokeFunction(edi, actual, JUMP_FUNCTION);
__ InvokeFunction(edi, actual, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// The generated code falls through if the call should be handled by runtime.

View File

@ -2602,6 +2602,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(function.is(edi)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(eax));
// TODO(1412): This is not correct if the called function is a
// strict mode function or a native.
//
// If the receiver is null or undefined, we have to pass the global object
// as a receiver.
Label global_object, receiver_ok;
@ -2623,6 +2626,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// here.
__ mov(receiver, Operand(ebp, StandardFrameConstants::kContextOffset));
__ mov(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
__ mov(receiver,
FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
__ bind(&receiver_ok);
// Copy the arguments to this function possibly from the
@ -2656,7 +2661,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
pointers,
env->deoptimization_index());
ParameterCount actual(eax);
__ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
}
@ -3083,7 +3089,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator generator(this, pointers, env->deoptimization_index());
ParameterCount count(instr->arity());
__ InvokeFunction(edi, count, CALL_FUNCTION, generator);
__ InvokeFunction(edi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
}

View File

@ -1690,7 +1690,8 @@ void MacroAssembler::InvokeFunction(Register fun,
void MacroAssembler::InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper) {
const CallWrapper& call_wrapper,
CallKind call_kind) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
mov(edi, Immediate(Handle<JSFunction>(function)));
@ -1702,11 +1703,11 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
// code field in the function to allow recompilation to take effect
// without changing any of the call sites.
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, actual, flag, call_wrapper);
expected, actual, flag, call_wrapper, call_kind);
} else {
Handle<Code> code(function->code());
InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET,
flag, call_wrapper);
flag, call_wrapper, call_kind);
}
}
@ -1723,7 +1724,7 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
ParameterCount expected(0);
GetBuiltinFunction(edi, id);
InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
expected, expected, flag, call_wrapper);
expected, expected, flag, call_wrapper, CALL_AS_METHOD);
}
void MacroAssembler::GetBuiltinFunction(Register target,

View File

@ -163,29 +163,30 @@ class MacroAssembler: public Assembler {
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeCode(Handle<Code> code,
const ParameterCount& expected,
const ParameterCount& actual,
RelocInfo::Mode rmode,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
// Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking.
void InvokeFunction(Register function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper());
const CallWrapper& call_wrapper,
CallKind call_kind);
// Invoke specified builtin JavaScript function. Adds an entry to
// the unresolved list if the name does not resolve.

View File

@ -488,10 +488,12 @@ class CallInterceptorCompiler BASE_EMBEDDED {
public:
CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments,
Register name)
Register name,
Code::ExtraICState extra_ic_state)
: stub_compiler_(stub_compiler),
arguments_(arguments),
name_(name) {}
name_(name),
extra_ic_state_(extra_ic_state) {}
MaybeObject* Compile(MacroAssembler* masm,
JSObject* object,
@ -616,8 +618,11 @@ class CallInterceptorCompiler BASE_EMBEDDED {
GenerateFastApiCall(masm, optimization, arguments_.immediate());
if (result->IsFailure()) return result;
} else {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION);
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@ -696,6 +701,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
Register name_;
Code::ExtraICState extra_ic_state_;
};
@ -1383,7 +1389,11 @@ MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField(
}
// Invoke the function.
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
@ -1869,7 +1879,11 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ bind(&miss);
// ecx: function name.
@ -1999,7 +2013,8 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object,
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// ecx: function name.
@ -2104,7 +2119,8 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ bind(&miss);
// ecx: function name.
@ -2178,11 +2194,12 @@ MaybeObject* CallStubCompiler::CompileFastApiCall(
}
MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
String* name,
CheckType check) {
MaybeObject* CallStubCompiler::CompileCallConstant(
Object* object,
JSObject* holder,
JSFunction* function,
String* name,
CheckType check) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
@ -2300,7 +2317,11 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
UNREACHABLE();
}
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
@ -2335,7 +2356,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the receiver from the stack.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
CallInterceptorCompiler compiler(this, arguments(), ecx);
CallInterceptorCompiler compiler(this, arguments(), ecx, extra_ic_state_);
MaybeObject* result = compiler.Compile(masm(),
object,
holder,
@ -2366,7 +2387,11 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Invoke the function.
__ mov(edi, eax);
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle load cache miss.
__ bind(&miss);
@ -2383,8 +2408,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name,
Code::ExtraICState extra_ic_state) {
String* name) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
@ -2427,7 +2451,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(
__ IncrementCounter(counters->call_global_inline(), 1);
ASSERT(function->is_compiled());
ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
if (V8::UseCrankshaft()) {

View File

@ -929,12 +929,7 @@ MaybeObject* StubCache::ComputeCallGlobal(int argc,
CallStubCompiler compiler(
argc, in_loop, kind, extra_ic_state, cache_holder);
{ MaybeObject* maybe_code =
compiler.CompileCallGlobal(receiver,
holder,
cell,
function,
name,
extra_ic_state);
compiler.CompileCallGlobal(receiver, holder, cell, function, name);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
ASSERT_EQ(flags, Code::cast(code)->flags());

View File

@ -748,25 +748,30 @@ class CallStubCompiler: public StubCompiler {
Code::ExtraICState extra_ic_state,
InlineCacheHolderFlag cache_holder);
MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
JSObject* holder,
int index,
String* name);
MUST_USE_RESULT MaybeObject* CompileCallConstant(Object* object,
JSObject* holder,
JSFunction* function,
String* name,
CheckType check);
MUST_USE_RESULT MaybeObject* CompileCallInterceptor(JSObject* object,
JSObject* holder,
String* name);
MUST_USE_RESULT MaybeObject* CompileCallField(
JSObject* object,
JSObject* holder,
int index,
String* name);
MUST_USE_RESULT MaybeObject* CompileCallConstant(
Object* object,
JSObject* holder,
JSFunction* function,
String* name,
CheckType check);
MUST_USE_RESULT MaybeObject* CompileCallInterceptor(
JSObject* object,
JSObject* holder,
String* name);
MUST_USE_RESULT MaybeObject* CompileCallGlobal(
JSObject* object,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name,
Code::ExtraICState extra_ic_state);
String* name);
static bool HasCustomCallGenerator(JSFunction* function);

View File

@ -343,11 +343,12 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
Handle<Code> code =
masm->isolate()->builtins()->HandleApiCallConstruct();
ParameterCount expected(0);
__ InvokeCode(code, expected, expected,
RelocInfo::CODE_TARGET, CALL_FUNCTION);
__ InvokeCode(code, expected, expected, RelocInfo::CODE_TARGET,
CALL_FUNCTION, NullCallWrapper(), CALL_AS_METHOD);
} else {
ParameterCount actual(rax);
__ InvokeFunction(rdi, actual, CALL_FUNCTION);
__ InvokeFunction(rdi, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// Restore context from the frame.
@ -499,7 +500,8 @@ static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
} else {
ParameterCount actual(rax);
// Function must be in rdi.
__ InvokeFunction(rdi, actual, CALL_FUNCTION);
__ InvokeFunction(rdi, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
// Exit the JS frame. Notice that this also removes the empty
@ -774,7 +776,8 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
RelocInfo::CODE_TARGET);
ParameterCount expected(0);
__ InvokeCode(rdx, expected, expected, JUMP_FUNCTION);
__ InvokeCode(rdx, expected, expected, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}
@ -914,7 +917,8 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
ParameterCount actual(rax);
__ SmiToInteger32(rax, rax);
__ movq(rdi, Operand(rbp, kFunctionOffset));
__ InvokeFunction(rdi, actual, CALL_FUNCTION);
__ InvokeFunction(rdi, actual, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ LeaveInternalFrame();
__ ret(3 * kPointerSize); // remove function, receiver, and arguments

View File

@ -2982,7 +2982,11 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
Label call_as_function;
__ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
__ j(equal, &call_as_function);
__ InvokeFunction(rdi, actual, JUMP_FUNCTION);
__ InvokeFunction(rdi,
actual,
JUMP_FUNCTION,
NullCallWrapper(),
CALL_AS_METHOD);
__ bind(&call_as_function);
}
__ InvokeFunction(rdi,

View File

@ -3067,7 +3067,8 @@ void FullCodeGenerator::EmitCallFunction(ZoneList<Expression*>* args) {
// InvokeFunction requires the function in rdi. Move it in there.
__ movq(rdi, result_register());
ParameterCount count(arg_count);
__ InvokeFunction(rdi, count, CALL_FUNCTION);
__ InvokeFunction(rdi, count, CALL_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
context()->Plug(rax);
}

View File

@ -892,7 +892,8 @@ static void GenerateFunctionTailCall(MacroAssembler* masm,
// Invoke the function.
ParameterCount actual(argc);
__ InvokeFunction(rdi, actual, JUMP_FUNCTION);
__ InvokeFunction(rdi, actual, JUMP_FUNCTION,
NullCallWrapper(), CALL_AS_METHOD);
}

View File

@ -2608,6 +2608,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
ASSERT(function.is(rdi)); // Required by InvokeFunction.
ASSERT(ToRegister(instr->result()).is(rax));
// TODO(1412): This is not correct if the called function is a
// strict mode function or a native.
//
// If the receiver is null or undefined, we have to pass the global object
// as a receiver.
Label global_object, receiver_ok;
@ -2627,8 +2630,9 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
// TODO(kmillikin): We have a hydrogen value for the global object. See
// if it's better to use it than to explicitly fetch it from the context
// here.
__ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
__ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
__ movq(receiver, ContextOperand(rsi, Context::GLOBAL_INDEX));
__ movq(receiver,
FieldOperand(receiver, JSGlobalObject::kGlobalReceiverOffset));
__ bind(&receiver_ok);
// Copy the arguments to this function possibly from the
@ -2662,7 +2666,8 @@ void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
pointers,
env->deoptimization_index());
v8::internal::ParameterCount actual(rax);
__ InvokeFunction(function, actual, CALL_FUNCTION, safepoint_generator);
__ InvokeFunction(function, actual, CALL_FUNCTION,
safepoint_generator, CALL_AS_METHOD);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}
@ -3075,7 +3080,7 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
RegisterEnvironmentForDeoptimization(env);
SafepointGenerator generator(this, pointers, env->deoptimization_index());
ParameterCount count(instr->arity());
__ InvokeFunction(rdi, count, CALL_FUNCTION, generator);
__ InvokeFunction(rdi, count, CALL_FUNCTION, generator, CALL_AS_METHOD);
__ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
}

View File

@ -800,7 +800,7 @@ void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
// parameter count to avoid emitting code to do the check.
ParameterCount expected(0);
GetBuiltinEntry(rdx, id);
InvokeCode(rdx, expected, expected, flag, call_wrapper);
InvokeCode(rdx, expected, expected, flag, call_wrapper, CALL_AS_METHOD);
}
@ -2878,7 +2878,8 @@ void MacroAssembler::InvokeFunction(Register function,
void MacroAssembler::InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper) {
const CallWrapper& call_wrapper,
CallKind call_kind) {
ASSERT(function->is_compiled());
// Get the function and setup the context.
Move(rdi, Handle<JSFunction>(function));
@ -2889,7 +2890,7 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
// the Code object every time we call the function.
movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
ParameterCount expected(function->shared()->formal_parameter_count());
InvokeCode(rdx, expected, actual, flag, call_wrapper);
InvokeCode(rdx, expected, actual, flag, call_wrapper, call_kind);
} else {
// Invoke the cached code.
Handle<Code> code(function->code());
@ -2899,7 +2900,8 @@ void MacroAssembler::InvokeFunction(JSFunction* function,
actual,
RelocInfo::CODE_TARGET,
flag,
call_wrapper);
call_wrapper,
call_kind);
}
}

View File

@ -251,29 +251,30 @@ class MacroAssembler: public Assembler {
const ParameterCount& expected,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeCode(Handle<Code> code,
const ParameterCount& expected,
const ParameterCount& actual,
RelocInfo::Mode rmode,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
// Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking.
void InvokeFunction(Register function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper(),
CallKind call_kind = CALL_AS_METHOD);
const CallWrapper& call_wrapper,
CallKind call_kind);
void InvokeFunction(JSFunction* function,
const ParameterCount& actual,
InvokeFlag flag,
const CallWrapper& call_wrapper = NullCallWrapper());
const CallWrapper& call_wrapper,
CallKind call_kind);
// Invoke specified builtin JavaScript function. Adds an entry to
// the unresolved list if the name does not resolve.

View File

@ -478,10 +478,12 @@ class CallInterceptorCompiler BASE_EMBEDDED {
public:
CallInterceptorCompiler(StubCompiler* stub_compiler,
const ParameterCount& arguments,
Register name)
Register name,
Code::ExtraICState extra_ic_state)
: stub_compiler_(stub_compiler),
arguments_(arguments),
name_(name) {}
name_(name),
extra_ic_state_(extra_ic_state) {}
MaybeObject* Compile(MacroAssembler* masm,
JSObject* object,
@ -606,8 +608,11 @@ class CallInterceptorCompiler BASE_EMBEDDED {
arguments_.immediate());
if (result->IsFailure()) return result;
} else {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION);
JUMP_FUNCTION, NullCallWrapper(), call_kind);
}
// Deferred code for fast API call case---clean preallocated space.
@ -686,6 +691,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
StubCompiler* stub_compiler_;
const ParameterCount& arguments_;
Register name_;
Code::ExtraICState extra_ic_state_;
};
@ -1348,7 +1354,11 @@ MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
}
// Invoke the function.
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
@ -1831,7 +1841,11 @@ MaybeObject* CallStubCompiler::CompileStringFromCharCodeCall(
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ bind(&miss);
// rcx: function name.
@ -1944,7 +1958,11 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object,
// Tail call the full function. We do not have to patch the receiver
// because the function makes no use of it.
__ bind(&slow);
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
__ bind(&miss);
// rcx: function name.
@ -2138,7 +2156,11 @@ MaybeObject* CallStubCompiler::CompileCallConstant(Object* object,
UNREACHABLE();
}
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(function, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle call cache miss.
__ bind(&miss);
@ -2175,7 +2197,7 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Get the receiver from the stack.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
CallInterceptorCompiler compiler(this, arguments(), rcx);
CallInterceptorCompiler compiler(this, arguments(), rcx, extra_ic_state_);
MaybeObject* result = compiler.Compile(masm(),
object,
holder,
@ -2205,7 +2227,11 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
// Invoke the function.
__ movq(rdi, rax);
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION);
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
__ InvokeFunction(rdi, arguments(), JUMP_FUNCTION,
NullCallWrapper(), call_kind);
// Handle load cache miss.
__ bind(&miss);
@ -2217,13 +2243,11 @@ MaybeObject* CallStubCompiler::CompileCallInterceptor(JSObject* object,
}
MaybeObject* CallStubCompiler::CompileCallGlobal(
JSObject* object,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name,
Code::ExtraICState extra_ic_state) {
MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
GlobalObject* holder,
JSGlobalPropertyCell* cell,
JSFunction* function,
String* name) {
// ----------- S t a t e -------------
// rcx : function name
// rsp[0] : return address
@ -2268,7 +2292,7 @@ MaybeObject* CallStubCompiler::CompileCallGlobal(
__ IncrementCounter(counters->call_global_inline(), 1);
ASSERT(function->is_compiled());
ParameterCount expected(function->shared()->formal_parameter_count());
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
: CALL_AS_METHOD;
if (V8::UseCrankshaft()) {

View File

@ -0,0 +1,34 @@
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function f() { "use strict"; print(this); }
function g() { assertEquals(void 0, f.apply(undefined, arguments)); }
for (var i = 0; i < 10; i++) g();
%OptimizeFunctionOnNextCall(g);
g();

View File

@ -174,3 +174,19 @@ outer_eval_conversion3(non_strict_eval, 'object');
// global context is used and the global object is passed as the
// receiver.
outer_eval_conversion3(eval, 'object');
function test_constant_function() {
var o = { f: function() { "use strict"; return this; } };
this.__proto__ = o;
for (var i = 0; i < 10; i++) assertEquals(void 0, f());
}
test_constant_function();
function test_field() {
var o = { };
o.f = function() {};
o.f = function() { "use strict"; return this; };
this.__proto__ = o;
for (var i = 0; i < 10; i++) assertEquals(void 0, f());
}
test_field();