Commit 185829c6 authored by palfia@homejinni.com's avatar palfia@homejinni.com

MIPS: This is a preview of a first step towards unification of the hydrogen call machinery.

Port r18626 (d3368a4c)

Original commit message:
The change replaces CallNamed, CallKeyed, CallConstantFunction and CallKnownGlobal hydrogen instructions with two new instructions with a more lower level semantics:

1. CallJSFunction for direct calls of JSFunction objects (no
   argument adaptation)

2. CallWithDescriptor for calls of a given Code object according to
   the supplied calling convention.

Details:

CallJSFunction should be straightforward, the main difference from the
existing InvokeFunction instruction is the absence of argument adaptor
handling. (As a next step, we will replace InvokeFunction with an
equivalent hydrogen code.)

For CallWithDescriptor, the calling conventions are represented by a
tweaked version of CallStubInterfaceDescriptor. In addition to the
parameter-register mapping, we also define parameter-representation
mapping there. The CallWithDescriptor instruction has variable number of
parameters now - this required some simple tweaks in Lithium, which
assumed fixed number of arguments in some places.

The calling conventions used in the calls are initialized in the
CallDescriptors class (code-stubs.h, <arch>/code-stubs-<arch>.cc), and
they live in a new table in the Isolate class. I should say I am not
quite sure about Representation::Integer32() representation for some of
the params of ArgumentAdaptorCall - it is not clear to me wether the
params could not end up on the stack and thus confuse the GC.

The change also includes an earlier small change to argument adaptor
(https://codereview.chromium.org/98463007) that avoids passing a naked
pointer to the code entry as a parameter. I am sorry for packaging that
with an already biggish change.

Performance implications:

Locally, I see a small regression (.2% or so). It is hard to say where
exactly it comes from, but I do see inefficient call sequences to the
adaptor trampoline. For example:

;;; <@78,#24> constant-t
bf85aa515a     mov edi,0x5a51aa85          ;; debug: position 29
;;; <@72,#53> load-named-field
8b7717         mov esi,[edi+0x17]          ;; debug: position 195
;;; <@80,#51> constant-s
b902000000     mov ecx,0x2                 ;; debug: position 195
;;; <@81,#51> gap
894df0         mov [ebp+0xf0],ecx
;;; <@82,#103> constant-i
bb01000000     mov ebx,0x1
;;; <@84,#102> constant-i
b902000000     mov ecx,0x2
;;; <@85,#102> gap
89d8           mov eax,ebx
89cb           mov ebx,ecx
8b4df0         mov ecx,[ebp+0xf0]
;;; <@86,#58> call-with-descriptor
e8ef57fcff     call ArgumentsAdaptorTrampoline  (0x2d80e6e0)    ;; code: BUILTIN

Note the silly handling of ecx; the hydrogen for this code is:

0 4 s27 Constant 1  range:1_1 <|@
0 3 t30 Constant 0x5bc1aa85 <JS Function xyz (SharedFunctionInfo 0x5bc1a919)> type:object <|@
0 1 t36 LoadNamedField t30.[in-object]@24 <|@
0 1 t38 Constant 0x2300e6a1 <Code> <|@
0 1 i102 Constant 2  range:2_2 <|@
0 1 i103 Constant 1  range:1_1 <|@
0 2 t41 CallWithDescriptor t38 t30 t36 s27 i103 i102 #2 changes[*] <|@

BUG=
R=plind44@gmail.com

Review URL: https://codereview.chromium.org/137663005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18630 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 33b3f563
...@@ -629,9 +629,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm, ...@@ -629,9 +629,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
Handle<Code> code = Handle<Code> code =
masm->isolate()->builtins()->HandleApiCallConstruct(); masm->isolate()->builtins()->HandleApiCallConstruct();
ParameterCount expected(0); __ Call(code, RelocInfo::CODE_TARGET);
__ InvokeCode(code, expected, expected,
RelocInfo::CODE_TARGET, CALL_FUNCTION);
} else { } else {
ParameterCount actual(a0); ParameterCount actual(a0);
__ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper());
...@@ -1178,12 +1176,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ...@@ -1178,12 +1176,12 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ push(a1); // Re-add proxy object as additional argument. __ push(a1); // Re-add proxy object as additional argument.
__ Addu(a0, a0, Operand(1)); __ Addu(a0, a0, Operand(1));
__ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
__ bind(&non_proxy); __ bind(&non_proxy);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
__ bind(&function); __ bind(&function);
...@@ -1198,11 +1196,11 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) { ...@@ -1198,11 +1196,11 @@ void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
__ lw(a2, __ lw(a2,
FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset));
__ sra(a2, a2, kSmiTagSize); __ sra(a2, a2, kSmiTagSize);
__ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
// Check formal and actual parameter counts. // Check formal and actual parameter counts.
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET, ne, a2, Operand(a0)); RelocInfo::CODE_TARGET, ne, a2, Operand(a0));
__ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
ParameterCount expected(0); ParameterCount expected(0);
__ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper()); __ InvokeCode(a3, expected, expected, JUMP_FUNCTION, NullCallWrapper());
} }
...@@ -1352,7 +1350,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) { ...@@ -1352,7 +1350,7 @@ void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
__ push(a1); // Add function proxy as last argument. __ push(a1); // Add function proxy as last argument.
__ Addu(a0, a0, Operand(1)); __ Addu(a0, a0, Operand(1));
__ li(a2, Operand(0, RelocInfo::NONE32)); __ li(a2, Operand(0, RelocInfo::NONE32));
__ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
__ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
// Tear down the internal frame and remove function, receiver and args. // Tear down the internal frame and remove function, receiver and args.
...@@ -1395,12 +1393,12 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ...@@ -1395,12 +1393,12 @@ void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
// -- a0: actual arguments count // -- a0: actual arguments count
// -- a1: function (passed through to callee) // -- a1: function (passed through to callee)
// -- a2: expected arguments count // -- a2: expected arguments count
// -- a3: callee code entry
// ----------------------------------- // -----------------------------------
Label invoke, dont_adapt_arguments; Label invoke, dont_adapt_arguments;
Label enough, too_few; Label enough, too_few;
__ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Branch(&dont_adapt_arguments, eq, __ Branch(&dont_adapt_arguments, eq,
a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); a2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
// We use Uless as the number of argument should always be greater than 0. // We use Uless as the number of argument should always be greater than 0.
......
...@@ -362,6 +362,56 @@ void NewStringAddStub::InitializeInterfaceDescriptor( ...@@ -362,6 +362,56 @@ void NewStringAddStub::InitializeInterfaceDescriptor(
} }
void CallDescriptors::InitializeForIsolate(Isolate* isolate) {
{
CallInterfaceDescriptor* descriptor =
isolate->call_descriptor(Isolate::ArgumentAdaptorCall);
static Register registers[] = { a1, // JSFunction
cp, // context
a0, // actual number of arguments
a2, // expected number of arguments
};
static Representation representations[] = {
Representation::Tagged(), // JSFunction
Representation::Tagged(), // context
Representation::Integer32(), // actual number of arguments
Representation::Integer32(), // expected number of arguments
};
descriptor->register_param_count_ = 4;
descriptor->register_params_ = registers;
descriptor->param_representations_ = representations;
}
{
CallInterfaceDescriptor* descriptor =
isolate->call_descriptor(Isolate::KeyedCall);
static Register registers[] = { cp, // context
a2, // key
};
static Representation representations[] = {
Representation::Tagged(), // context
Representation::Tagged(), // key
};
descriptor->register_param_count_ = 2;
descriptor->register_params_ = registers;
descriptor->param_representations_ = representations;
}
{
CallInterfaceDescriptor* descriptor =
isolate->call_descriptor(Isolate::NamedCall);
static Register registers[] = { cp, // context
a2, // name
};
static Representation representations[] = {
Representation::Tagged(), // context
Representation::Tagged(), // name
};
descriptor->register_param_count_ = 2;
descriptor->register_params_ = registers;
descriptor->param_representations_ = representations;
}
}
#define __ ACCESS_MASM(masm) #define __ ACCESS_MASM(masm)
...@@ -3362,7 +3412,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { ...@@ -3362,7 +3412,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ push(a1); // Put proxy as additional argument. __ push(a1); // Put proxy as additional argument.
__ li(a0, Operand(argc_ + 1, RelocInfo::NONE32)); __ li(a0, Operand(argc_ + 1, RelocInfo::NONE32));
__ li(a2, Operand(0, RelocInfo::NONE32)); __ li(a2, Operand(0, RelocInfo::NONE32));
__ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY); __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY);
{ {
Handle<Code> adaptor = Handle<Code> adaptor =
masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(); masm->isolate()->builtins()->ArgumentsAdaptorTrampoline();
...@@ -3375,7 +3425,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) { ...@@ -3375,7 +3425,7 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
__ sw(a1, MemOperand(sp, argc_ * kPointerSize)); __ sw(a1, MemOperand(sp, argc_ * kPointerSize));
__ li(a0, Operand(argc_)); // Set up the number of arguments. __ li(a0, Operand(argc_)); // Set up the number of arguments.
__ mov(a2, zero_reg); __ mov(a2, zero_reg);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION); __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION);
__ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} }
...@@ -3411,11 +3461,11 @@ void CallConstructStub::Generate(MacroAssembler* masm) { ...@@ -3411,11 +3461,11 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
Label do_call; Label do_call;
__ bind(&slow); __ bind(&slow);
__ Branch(&non_function_call, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE)); __ Branch(&non_function_call, ne, a3, Operand(JS_FUNCTION_PROXY_TYPE));
__ GetBuiltinEntry(a3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); __ GetBuiltinFunction(a1, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR);
__ jmp(&do_call); __ jmp(&do_call);
__ bind(&non_function_call); __ bind(&non_function_call);
__ GetBuiltinEntry(a3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); __ GetBuiltinFunction(a1, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR);
__ bind(&do_call); __ bind(&do_call);
// Set expected number of arguments to zero (not changing r0). // Set expected number of arguments to zero (not changing r0).
__ li(a2, Operand(0, RelocInfo::NONE32)); __ li(a2, Operand(0, RelocInfo::NONE32));
......
...@@ -3549,17 +3549,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function, ...@@ -3549,17 +3549,6 @@ void LCodeGen::CallKnownFunction(Handle<JSFunction> function,
} }
void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
__ mov(a0, v0);
CallKnownFunction(instr->hydrogen()->function(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
A1_UNINITIALIZED);
}
void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
ASSERT(instr->context() != NULL); ASSERT(instr->context() != NULL);
ASSERT(ToRegister(instr->context()).is(cp)); ASSERT(ToRegister(instr->context()).is(cp));
...@@ -3889,25 +3878,44 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { ...@@ -3889,25 +3878,44 @@ void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) {
} }
void LCodeGen::DoCallKeyed(LCallKeyed* instr) { void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
ASSERT(ToRegister(instr->context()).is(cp));
ASSERT(ToRegister(instr->result()).is(v0)); ASSERT(ToRegister(instr->result()).is(v0));
int arity = instr->arity(); LPointerMap* pointers = instr->pointer_map();
Handle<Code> ic = SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt);
isolate()->stub_cache()->ComputeKeyedCallInitialize(arity);
CallCode(ic, RelocInfo::CODE_TARGET, instr); if (instr->target()->IsConstantOperand()) {
LConstantOperand* target = LConstantOperand::cast(instr->target());
Handle<Code> code = Handle<Code>::cast(ToHandle(target));
generator.BeforeCall(__ CallSize(code, RelocInfo::CODE_TARGET));
__ Call(code, RelocInfo::CODE_TARGET);
} else {
ASSERT(instr->target()->IsRegister());
Register target = ToRegister(instr->target());
generator.BeforeCall(__ CallSize(target));
__ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(target);
}
generator.AfterCall();
} }
void LCodeGen::DoCallNamed(LCallNamed* instr) { void LCodeGen::DoCallJSFunction(LCallJSFunction* instr) {
ASSERT(ToRegister(instr->context()).is(cp)); ASSERT(ToRegister(instr->function()).is(a1));
ASSERT(ToRegister(instr->result()).is(v0)); ASSERT(ToRegister(instr->result()).is(v0));
int arity = instr->arity(); if (instr->hydrogen()->pass_argument_count()) {
Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity); __ li(a0, Operand(instr->arity()));
__ li(a2, Operand(instr->name())); }
CallCode(ic, RelocInfo::CODE_TARGET, instr);
// Change context.
__ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));
// Load the code entry address
__ lw(at, FieldMemOperand(a1, JSFunction::kCodeEntryOffset));
__ Call(at);
RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT);
} }
...@@ -3927,16 +3935,6 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { ...@@ -3927,16 +3935,6 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) {
} }
void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) {
ASSERT(ToRegister(instr->result()).is(v0));
CallKnownFunction(instr->hydrogen()->target(),
instr->hydrogen()->formal_parameter_count(),
instr->arity(),
instr,
A1_UNINITIALIZED);
}
void LCodeGen::DoCallNew(LCallNew* instr) { void LCodeGen::DoCallNew(LCallNew* instr) {
ASSERT(ToRegister(instr->context()).is(cp)); ASSERT(ToRegister(instr->context()).is(cp));
ASSERT(ToRegister(instr->constructor()).is(a1)); ASSERT(ToRegister(instr->constructor()).is(a1));
......
...@@ -282,7 +282,18 @@ void LInnerAllocatedObject::PrintDataTo(StringStream* stream) { ...@@ -282,7 +282,18 @@ void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
} }
void LCallConstantFunction::PrintDataTo(StringStream* stream) { void LCallJSFunction::PrintDataTo(StringStream* stream) {
stream->Add("= ");
function()->PrintTo(stream);
stream->Add("#%d / ", arity());
}
void LCallWithDescriptor::PrintDataTo(StringStream* stream) {
for (int i = 0; i < InputCount(); i++) {
InputAt(i)->PrintTo(stream);
stream->Add(" ");
}
stream->Add("#%d / ", arity()); stream->Add("#%d / ", arity());
} }
...@@ -307,22 +318,6 @@ void LInvokeFunction::PrintDataTo(StringStream* stream) { ...@@ -307,22 +318,6 @@ void LInvokeFunction::PrintDataTo(StringStream* stream) {
} }
void LCallKeyed::PrintDataTo(StringStream* stream) {
stream->Add("[a2] #%d / ", arity());
}
void LCallNamed::PrintDataTo(StringStream* stream) {
SmartArrayPointer<char> name_string = name()->ToCString();
stream->Add("%s #%d / ", name_string.get(), arity());
}
void LCallKnownGlobal::PrintDataTo(StringStream* stream) {
stream->Add("#%d / ", arity());
}
void LCallNew::PrintDataTo(StringStream* stream) { void LCallNew::PrintDataTo(StringStream* stream) {
stream->Add("= "); stream->Add("= ");
constructor()->PrintTo(stream); constructor()->PrintTo(stream);
...@@ -562,8 +557,7 @@ LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { ...@@ -562,8 +557,7 @@ LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) {
} }
template<int I, int T> LInstruction* LChunkBuilder::Define(LTemplateResultInstruction<1>* instr,
LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
LUnallocated* result) { LUnallocated* result) {
result->set_virtual_register(current_instruction_->id()); result->set_virtual_register(current_instruction_->id());
instr->set_result(result); instr->set_result(result);
...@@ -571,40 +565,35 @@ LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr, ...@@ -571,40 +565,35 @@ LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr,
} }
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsRegister( LInstruction* LChunkBuilder::DefineAsRegister(
LTemplateInstruction<1, I, T>* instr) { LTemplateResultInstruction<1>* instr) {
return Define(instr, return Define(instr,
new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER));
} }
template<int I, int T>
LInstruction* LChunkBuilder::DefineAsSpilled( LInstruction* LChunkBuilder::DefineAsSpilled(
LTemplateInstruction<1, I, T>* instr, int index) { LTemplateResultInstruction<1>* instr, int index) {
return Define(instr, return Define(instr,
new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index)); new(zone()) LUnallocated(LUnallocated::FIXED_SLOT, index));
} }
template<int I, int T>
LInstruction* LChunkBuilder::DefineSameAsFirst( LInstruction* LChunkBuilder::DefineSameAsFirst(
LTemplateInstruction<1, I, T>* instr) { LTemplateResultInstruction<1>* instr) {
return Define(instr, return Define(instr,
new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); new(zone()) LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT));
} }
template<int I, int T>
LInstruction* LChunkBuilder::DefineFixed( LInstruction* LChunkBuilder::DefineFixed(
LTemplateInstruction<1, I, T>* instr, Register reg) { LTemplateResultInstruction<1>* instr, Register reg) {
return Define(instr, ToUnallocated(reg)); return Define(instr, ToUnallocated(reg));
} }
template<int I, int T>
LInstruction* LChunkBuilder::DefineFixedDouble( LInstruction* LChunkBuilder::DefineFixedDouble(
LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) { LTemplateResultInstruction<1>* instr, DoubleRegister reg) {
return Define(instr, ToUnallocated(reg)); return Define(instr, ToUnallocated(reg));
} }
...@@ -1080,9 +1069,32 @@ LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { ...@@ -1080,9 +1069,32 @@ LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) {
} }
LInstruction* LChunkBuilder::DoCallConstantFunction( LInstruction* LChunkBuilder::DoCallJSFunction(
HCallConstantFunction* instr) { HCallJSFunction* instr) {
return MarkAsCall(DefineFixed(new(zone()) LCallConstantFunction, v0), instr); LOperand* function = UseFixed(instr->function(), a1);
LCallJSFunction* result = new(zone()) LCallJSFunction(function);
return MarkAsCall(DefineFixed(result, v0), instr);
}
LInstruction* LChunkBuilder::DoCallWithDescriptor(
HCallWithDescriptor* instr) {
const CallInterfaceDescriptor* descriptor = instr->descriptor();
LOperand* target = UseRegisterOrConstantAtStart(instr->target());
ZoneList<LOperand*> ops(instr->OperandCount(), zone());
ops.Add(target, zone());
for (int i = 1; i < instr->OperandCount(); i++) {
LOperand* op = UseFixed(instr->OperandAt(i),
descriptor->GetParameterRegister(i - 1));
ops.Add(op, zone());
}
LCallWithDescriptor* result = new(zone()) LCallWithDescriptor(
descriptor, ops, zone());
return MarkAsCall(DefineFixed(result, v0), instr);
} }
...@@ -1173,26 +1185,6 @@ LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) { ...@@ -1173,26 +1185,6 @@ LInstruction* LChunkBuilder::DoMathRound(HUnaryMathOperation* instr) {
} }
LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) {
ASSERT(instr->key()->representation().IsTagged());
LOperand* context = UseFixed(instr->context(), cp);
LOperand* key = UseFixed(instr->key(), a2);
return MarkAsCall(
DefineFixed(new(zone()) LCallKeyed(context, key), v0), instr);
}
LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) {
LOperand* context = UseFixed(instr->context(), cp);
return MarkAsCall(DefineFixed(new(zone()) LCallNamed(context), v0), instr);
}
LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) {
return MarkAsCall(DefineFixed(new(zone()) LCallKnownGlobal, v0), instr);
}
LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) {
LOperand* context = UseFixed(instr->context(), cp); LOperand* context = UseFixed(instr->context(), cp);
LOperand* constructor = UseFixed(instr->constructor(), a1); LOperand* constructor = UseFixed(instr->constructor(), a1);
......
...@@ -52,11 +52,9 @@ class LCodeGen; ...@@ -52,11 +52,9 @@ class LCodeGen;
V(BitI) \ V(BitI) \
V(BoundsCheck) \ V(BoundsCheck) \
V(Branch) \ V(Branch) \
V(CallConstantFunction) \ V(CallJSFunction) \
V(CallWithDescriptor) \
V(CallFunction) \ V(CallFunction) \
V(CallKeyed) \
V(CallKnownGlobal) \
V(CallNamed) \
V(CallNew) \ V(CallNew) \
V(CallNewArray) \ V(CallNewArray) \
V(CallRuntime) \ V(CallRuntime) \
...@@ -299,10 +297,8 @@ class LInstruction : public ZoneObject { ...@@ -299,10 +297,8 @@ class LInstruction : public ZoneObject {
// R = number of result operands (0 or 1). // R = number of result operands (0 or 1).
// I = number of input operands. template<int R>
// T = number of temporary operands. class LTemplateResultInstruction : public LInstruction {
template<int R, int I, int T>
class LTemplateInstruction : public LInstruction {
public: public:
// Allow 0 or 1 output operands. // Allow 0 or 1 output operands.
STATIC_ASSERT(R == 0 || R == 1); STATIC_ASSERT(R == 0 || R == 1);
...@@ -314,10 +310,20 @@ class LTemplateInstruction : public LInstruction { ...@@ -314,10 +310,20 @@ class LTemplateInstruction : public LInstruction {
protected: protected:
EmbeddedContainer<LOperand*, R> results_; EmbeddedContainer<LOperand*, R> results_;
};
// R = number of result operands (0 or 1).
// I = number of input operands.
// T = number of temporary operands.
template<int R, int I, int T>
class LTemplateInstruction : public LTemplateResultInstruction<R> {
protected:
EmbeddedContainer<LOperand*, I> inputs_; EmbeddedContainer<LOperand*, I> inputs_;
EmbeddedContainer<LOperand*, T> temps_; EmbeddedContainer<LOperand*, T> temps_;
private: private:
// Iterator support.
virtual int InputCount() V8_FINAL V8_OVERRIDE { return I; } virtual int InputCount() V8_FINAL V8_OVERRIDE { return I; }
virtual LOperand* InputAt(int i) V8_FINAL V8_OVERRIDE { return inputs_[i]; } virtual LOperand* InputAt(int i) V8_FINAL V8_OVERRIDE { return inputs_[i]; }
...@@ -1813,71 +1819,78 @@ class LGlobalReceiver V8_FINAL : public LTemplateInstruction<1, 1, 0> { ...@@ -1813,71 +1819,78 @@ class LGlobalReceiver V8_FINAL : public LTemplateInstruction<1, 1, 0> {
}; };
class LCallConstantFunction V8_FINAL : public LTemplateInstruction<1, 0, 0> { class LCallJSFunction V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public: public:
DECLARE_CONCRETE_INSTRUCTION(CallConstantFunction, "call-constant-function") explicit LCallJSFunction(LOperand* function) {
DECLARE_HYDROGEN_ACCESSOR(CallConstantFunction) inputs_[0] = function;
}
LOperand* function() { return inputs_[0]; }
DECLARE_CONCRETE_INSTRUCTION(CallJSFunction, "call-js-function")
DECLARE_HYDROGEN_ACCESSOR(CallJSFunction)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<JSFunction> function() { return hydrogen()->function(); }
int arity() const { return hydrogen()->argument_count() - 1; } int arity() const { return hydrogen()->argument_count() - 1; }
}; };
class LInvokeFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> { class LCallWithDescriptor V8_FINAL : public LTemplateResultInstruction<1> {
public: public:
LInvokeFunction(LOperand* context, LOperand* function) { LCallWithDescriptor(const CallInterfaceDescriptor* descriptor,
inputs_[0] = context; ZoneList<LOperand*>& operands,
inputs_[1] = function; Zone* zone)
: descriptor_(descriptor),
inputs_(descriptor->environment_length() + 1, zone) {
ASSERT(descriptor->environment_length() + 1 == operands.length());
inputs_.AddAll(operands, zone);
} }
LOperand* context() { return inputs_[0]; } LOperand* target() const { return inputs_[0]; }
LOperand* function() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function") const CallInterfaceDescriptor* descriptor() { return descriptor_; }
DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
private:
DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; } int arity() const { return hydrogen()->argument_count() - 1; }
};
const CallInterfaceDescriptor* descriptor_;
ZoneList<LOperand*> inputs_;
class LCallKeyed V8_FINAL : public LTemplateInstruction<1, 2, 0> { virtual void InternalSetOperandAt(int index,
public: LOperand* value) V8_FINAL V8_OVERRIDE {
LCallKeyed(LOperand* context, LOperand* key) { inputs_[index] = value;
inputs_[0] = context;
inputs_[1] = key;
} }
LOperand* context() { return inputs_[0]; } // Iterator support.
LOperand* key() { return inputs_[1]; } virtual int InputCount() V8_FINAL V8_OVERRIDE { return inputs_.length(); }
virtual LOperand* InputAt(int i) V8_FINAL V8_OVERRIDE { return inputs_[i]; }
DECLARE_CONCRETE_INSTRUCTION(CallKeyed, "call-keyed")
DECLARE_HYDROGEN_ACCESSOR(CallKeyed)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; } virtual int TempCount() V8_FINAL V8_OVERRIDE { return 0; }
virtual LOperand* TempAt(int i) V8_FINAL V8_OVERRIDE { return NULL; }
}; };
class LInvokeFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
class LCallNamed V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public: public:
explicit LCallNamed(LOperand* context) { LInvokeFunction(LOperand* context, LOperand* function) {
inputs_[0] = context; inputs_[0] = context;
inputs_[1] = function;
} }
LOperand* context() { return inputs_[0]; } LOperand* context() { return inputs_[0]; }
LOperand* function() { return inputs_[1]; }
DECLARE_CONCRETE_INSTRUCTION(CallNamed, "call-named") DECLARE_CONCRETE_INSTRUCTION(InvokeFunction, "invoke-function")
DECLARE_HYDROGEN_ACCESSOR(CallNamed) DECLARE_HYDROGEN_ACCESSOR(InvokeFunction)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE; virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
Handle<String> name() const { return hydrogen()->name(); }
int arity() const { return hydrogen()->argument_count() - 1; } int arity() const { return hydrogen()->argument_count() - 1; }
}; };
...@@ -1899,17 +1912,6 @@ class LCallFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> { ...@@ -1899,17 +1912,6 @@ class LCallFunction V8_FINAL : public LTemplateInstruction<1, 2, 0> {
}; };
class LCallKnownGlobal V8_FINAL : public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(CallKnownGlobal, "call-known-global")
DECLARE_HYDROGEN_ACCESSOR(CallKnownGlobal)
virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
int arity() const { return hydrogen()->argument_count() - 1; }
};
class LCallNew V8_FINAL : public LTemplateInstruction<1, 2, 0> { class LCallNew V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public: public:
LCallNew(LOperand* context, LOperand* constructor) { LCallNew(LOperand* context, LOperand* constructor) {
...@@ -2762,22 +2764,16 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase { ...@@ -2762,22 +2764,16 @@ class LChunkBuilder V8_FINAL : public LChunkBuilderBase {
// Methods for setting up define-use relationships. // Methods for setting up define-use relationships.
// Return the same instruction that they are passed. // Return the same instruction that they are passed.
template<int I, int T> LInstruction* Define(LTemplateResultInstruction<1>* instr,
LInstruction* Define(LTemplateInstruction<1, I, T>* instr, LUnallocated* result);
LUnallocated* result); LInstruction* DefineAsRegister(LTemplateResultInstruction<1>* instr);
template<int I, int T> LInstruction* DefineAsSpilled(LTemplateResultInstruction<1>* instr,
LInstruction* DefineAsRegister(LTemplateInstruction<1, I, T>* instr); int index);
template<int I, int T> LInstruction* DefineSameAsFirst(LTemplateResultInstruction<1>* instr);
LInstruction* DefineAsSpilled(LTemplateInstruction<1, I, T>* instr, LInstruction* DefineFixed(LTemplateResultInstruction<1>* instr,
int index); Register reg);
template<int I, int T> LInstruction* DefineFixedDouble(LTemplateResultInstruction<1>* instr,
LInstruction* DefineSameAsFirst(LTemplateInstruction<1, I, T>* instr); DoubleRegister reg);
template<int I, int T>
LInstruction* DefineFixed(LTemplateInstruction<1, I, T>* instr,
Register reg);
template<int I, int T>
LInstruction* DefineFixedDouble(LTemplateInstruction<1, I, T>* instr,
DoubleRegister reg);
LInstruction* AssignEnvironment(LInstruction* instr); LInstruction* AssignEnvironment(LInstruction* instr);
LInstruction* AssignPointerMap(LInstruction* instr); LInstruction* AssignPointerMap(LInstruction* instr);
......
...@@ -3591,7 +3591,6 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, ...@@ -3591,7 +3591,6 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// a0: actual arguments count // a0: actual arguments count
// a1: function (passed through to callee) // a1: function (passed through to callee)
// a2: expected arguments count // a2: expected arguments count
// a3: callee code entry
// The code below is made a lot easier because the calling code already sets // The code below is made a lot easier because the calling code already sets
// up actual and expected registers according to the contract if values are // up actual and expected registers according to the contract if values are
...@@ -3678,33 +3677,6 @@ void MacroAssembler::InvokeCode(Register code, ...@@ -3678,33 +3677,6 @@ void MacroAssembler::InvokeCode(Register code,
} }
void MacroAssembler::InvokeCode(Handle<Code> code,
const ParameterCount& expected,
const ParameterCount& actual,
RelocInfo::Mode rmode,
InvokeFlag flag) {
// You can't call a function without a valid frame.
ASSERT(flag == JUMP_FUNCTION || has_frame());
Label done;
bool definitely_mismatches = false;
InvokePrologue(expected, actual, code, no_reg,
&done, &definitely_mismatches, flag,
NullCallWrapper());
if (!definitely_mismatches) {
if (flag == CALL_FUNCTION) {
Call(code, rmode);
} else {
Jump(code, rmode);
}
// Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts.
bind(&done);
}
}
void MacroAssembler::InvokeFunction(Register function, void MacroAssembler::InvokeFunction(Register function,
const ParameterCount& actual, const ParameterCount& actual,
InvokeFlag flag, InvokeFlag flag,
......
...@@ -901,12 +901,6 @@ class MacroAssembler: public Assembler { ...@@ -901,12 +901,6 @@ class MacroAssembler: public Assembler {
InvokeFlag flag, InvokeFlag flag,
const CallWrapper& call_wrapper); const CallWrapper& call_wrapper);
void InvokeCode(Handle<Code> code,
const ParameterCount& expected,
const ParameterCount& actual,
RelocInfo::Mode rmode,
InvokeFlag flag);
// Invoke the JavaScript function in the given register. Changes the // Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking. // current context to the context in the function before invoking.
void InvokeFunction(Register function, void InvokeFunction(Register function,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment