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:
parent
5083dec67f
commit
cc4a2d7e76
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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()) {
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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()) {
|
||||
|
34
test/mjsunit/bugs/bug-1412.js
Normal file
34
test/mjsunit/bugs/bug-1412.js
Normal 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();
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user