Revert of [Interpreter] Support for operator new. (patchset #17 id:290001 of https://codereview.chromium.org/1402943002/ )
Reason for revert: [Sheriff] Breaks arm64 debug: http://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20arm64%20-%20sim%20-%20debug/builds/4595 Original issue's description: > [Interpreter] Support for operator new. > > This change add a new bytecode for operator new and implements it using > the Construct() builtin. > > BUG=v8:4280 > LOG=N > > Committed: https://crrev.com/8e4f9963d53913eab7fbd2f61a5733d8dc2169e7 > Cr-Commit-Position: refs/heads/master@{#31293} TBR=rmcilroy@chromium.org,bmeurer@chromium.org,oth@chromium.org NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:4280 Review URL: https://codereview.chromium.org/1402153004 Cr-Commit-Position: refs/heads/master@{#31298}
This commit is contained in:
parent
f4c9f2221b
commit
0937cdbfbd
@ -976,19 +976,6 @@ void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
|
||||||
Register limit, Register scratch) {
|
|
||||||
Label loop_header, loop_check;
|
|
||||||
__ b(al, &loop_check);
|
|
||||||
__ bind(&loop_header);
|
|
||||||
__ ldr(scratch, MemOperand(index, -kPointerSize, PostIndex));
|
|
||||||
__ push(scratch);
|
|
||||||
__ bind(&loop_check);
|
|
||||||
__ cmp(index, limit);
|
|
||||||
__ b(gt, &loop_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
@ -997,40 +984,27 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -- r1 : the target to call (can be any Object).
|
// -- r1 : the target to call (can be any Object).
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
// Find the address of the last argument.
|
||||||
__ add(r3, r0, Operand(1)); // Add one for receiver.
|
__ add(r3, r0, Operand(1)); // Add one for receiver.
|
||||||
__ mov(r3, Operand(r3, LSL, kPointerSizeLog2));
|
__ mov(r3, Operand(r3, LSL, kPointerSizeLog2));
|
||||||
__ sub(r3, r2, r3);
|
__ sub(r3, r2, r3);
|
||||||
|
|
||||||
Generate_InterpreterPushArgs(masm, r2, r3, r4);
|
// Push the arguments.
|
||||||
|
Label loop_header, loop_check;
|
||||||
|
__ b(al, &loop_check);
|
||||||
|
__ bind(&loop_header);
|
||||||
|
__ ldr(r4, MemOperand(r2, -kPointerSize, PostIndex));
|
||||||
|
__ push(r4);
|
||||||
|
__ bind(&loop_check);
|
||||||
|
__ cmp(r2, r3);
|
||||||
|
__ b(gt, &loop_header);
|
||||||
|
|
||||||
// Call the target.
|
// Call the target.
|
||||||
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- r0 : argument count (not including receiver)
|
|
||||||
// -- r3 : original constructor
|
|
||||||
// -- r1 : constructor to call
|
|
||||||
// -- r2 : address of the first argument
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
|
||||||
__ mov(r4, Operand(r0, LSL, kPointerSizeLog2));
|
|
||||||
__ sub(r4, r2, r4);
|
|
||||||
|
|
||||||
Generate_InterpreterPushArgs(masm, r2, r4, r5);
|
|
||||||
|
|
||||||
// Call the constructor with r0, r1, and r3 unmodified.
|
|
||||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||||
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
||||||
GenerateTailCallToReturnedCode(masm);
|
GenerateTailCallToReturnedCode(masm);
|
||||||
|
@ -420,18 +420,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
r0, // argument count (not including receiver)
|
|
||||||
r3, // original constructor
|
|
||||||
r1, // constructor to call
|
|
||||||
r2 // address of the first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -1769,7 +1769,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -- x1 : the target to call (can be any Object).
|
// -- x1 : the target to call (can be any Object).
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
// Find the address of the last argument.
|
||||||
__ add(x3, x0, Operand(1)); // Add one for receiver.
|
__ add(x3, x0, Operand(1)); // Add one for receiver.
|
||||||
@ -1794,37 +1793,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- x0 : argument count (not including receiver)
|
|
||||||
// -- x3 : original constructor
|
|
||||||
// -- x1 : constructor to call
|
|
||||||
// -- x2 : address of the first argument
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
|
||||||
__ lsl(x5, x0, kPointerSizeLog2);
|
|
||||||
__ sub(x4, x2, x5);
|
|
||||||
|
|
||||||
// Push the arguments.
|
|
||||||
Label loop_header, loop_check;
|
|
||||||
__ Mov(x6, jssp);
|
|
||||||
__ Claim(x5, 1);
|
|
||||||
__ B(&loop_check);
|
|
||||||
__ Bind(&loop_header);
|
|
||||||
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
|
|
||||||
__ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
|
|
||||||
__ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
|
|
||||||
__ Bind(&loop_check);
|
|
||||||
__ Cmp(x2, x4);
|
|
||||||
__ B(gt, &loop_header);
|
|
||||||
|
|
||||||
// Call the constructor with x0, x1, and x3 unmodified.
|
|
||||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
|
||||||
ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline");
|
ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline");
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
|
@ -449,18 +449,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
x0, // argument count (not including receiver)
|
|
||||||
x3, // original constructor
|
|
||||||
x1, // constructor to call
|
|
||||||
x2 // address of the first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -104,7 +104,6 @@ enum BuiltinExtraArguments {
|
|||||||
V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||||
V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||||
V(InterpreterPushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
V(InterpreterPushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||||
V(InterpreterPushArgsAndConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
|
||||||
\
|
\
|
||||||
V(LoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
V(LoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||||
V(KeyedLoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
V(KeyedLoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||||
@ -309,7 +308,6 @@ class Builtins {
|
|||||||
static void Generate_InterpreterEntryTrampoline(MacroAssembler* masm);
|
static void Generate_InterpreterEntryTrampoline(MacroAssembler* masm);
|
||||||
static void Generate_InterpreterExitTrampoline(MacroAssembler* masm);
|
static void Generate_InterpreterExitTrampoline(MacroAssembler* masm);
|
||||||
static void Generate_InterpreterPushArgsAndCall(MacroAssembler* masm);
|
static void Generate_InterpreterPushArgsAndCall(MacroAssembler* masm);
|
||||||
static void Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm);
|
|
||||||
|
|
||||||
#define DECLARE_CODE_AGE_BUILTIN_GENERATOR(C) \
|
#define DECLARE_CODE_AGE_BUILTIN_GENERATOR(C) \
|
||||||
static void Generate_Make##C##CodeYoungAgainEvenMarking( \
|
static void Generate_Make##C##CodeYoungAgainEvenMarking( \
|
||||||
|
@ -275,13 +275,6 @@ Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
Callable CodeFactory::InterpreterPushArgsAndConstruct(Isolate* isolate) {
|
|
||||||
return Callable(isolate->builtins()->InterpreterPushArgsAndConstruct(),
|
|
||||||
InterpreterPushArgsAndConstructDescriptor(isolate));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Callable CodeFactory::InterpreterCEntry(Isolate* isolate) {
|
Callable CodeFactory::InterpreterCEntry(Isolate* isolate) {
|
||||||
// TODO(rmcilroy): Deal with runtime functions that return two values.
|
// TODO(rmcilroy): Deal with runtime functions that return two values.
|
||||||
|
@ -98,7 +98,6 @@ class CodeFactory final {
|
|||||||
CallFunctionFlags flags);
|
CallFunctionFlags flags);
|
||||||
|
|
||||||
static Callable InterpreterPushArgsAndCall(Isolate* isolate);
|
static Callable InterpreterPushArgsAndCall(Isolate* isolate);
|
||||||
static Callable InterpreterPushArgsAndConstruct(Isolate* isolate);
|
|
||||||
static Callable InterpreterCEntry(Isolate* isolate);
|
static Callable InterpreterCEntry(Isolate* isolate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -357,12 +357,6 @@ void BytecodeGraphBuilder::VisitCallRuntime(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGraphBuilder::VisitNew(
|
|
||||||
const interpreter::BytecodeArrayIterator& iterator) {
|
|
||||||
UNIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGraphBuilder::BuildBinaryOp(
|
void BytecodeGraphBuilder::BuildBinaryOp(
|
||||||
const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
|
const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
|
||||||
Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
|
Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
|
||||||
|
@ -317,26 +317,6 @@ Node* InterpreterAssembler::LoadTypeFeedbackVector() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Node* InterpreterAssembler::CallConstruct(Node* original_constructor,
|
|
||||||
Node* constructor, Node* first_arg,
|
|
||||||
Node* arg_count) {
|
|
||||||
Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(isolate());
|
|
||||||
CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
|
|
||||||
isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);
|
|
||||||
|
|
||||||
Node* code_target = HeapConstant(callable.code());
|
|
||||||
|
|
||||||
Node** args = zone()->NewArray<Node*>(5);
|
|
||||||
args[0] = arg_count;
|
|
||||||
args[1] = original_constructor;
|
|
||||||
args[2] = constructor;
|
|
||||||
args[3] = first_arg;
|
|
||||||
args[4] = GetContext();
|
|
||||||
|
|
||||||
return CallN(descriptor, code_target, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
|
Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
|
||||||
Node** args) {
|
Node** args) {
|
||||||
Node* stack_pointer_before_call = nullptr;
|
Node* stack_pointer_before_call = nullptr;
|
||||||
|
@ -101,17 +101,8 @@ class InterpreterAssembler {
|
|||||||
// Load the TypeFeedbackVector for the current function.
|
// Load the TypeFeedbackVector for the current function.
|
||||||
Node* LoadTypeFeedbackVector();
|
Node* LoadTypeFeedbackVector();
|
||||||
|
|
||||||
// Call constructor |constructor| with |arg_count| arguments (not
|
// Call JSFunction or Callable |function| with |arg_count| (not including
|
||||||
// including receiver) and the first argument located at
|
// receiver) and the first argument located at |first_arg|.
|
||||||
// |first_arg|. The |original_constructor| is the same as the
|
|
||||||
// |constructor| for the new keyword, but differs for the super
|
|
||||||
// keyword.
|
|
||||||
Node* CallConstruct(Node* original_constructor, Node* constructor,
|
|
||||||
Node* first_arg, Node* arg_count);
|
|
||||||
|
|
||||||
// Call JSFunction or Callable |function| with |arg_count|
|
|
||||||
// arguments (not including receiver) and the first argument
|
|
||||||
// located at |first_arg|.
|
|
||||||
Node* CallJS(Node* function, Node* first_arg, Node* arg_count);
|
Node* CallJS(Node* function, Node* first_arg, Node* arg_count);
|
||||||
|
|
||||||
// Call an IC code stub.
|
// Call an IC code stub.
|
||||||
|
@ -724,24 +724,6 @@ void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
|
|
||||||
Register array_limit) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- ebx : Pointer to the last argument in the args array.
|
|
||||||
// -- array_limit : Pointer to one before the first argument in the
|
|
||||||
// args array.
|
|
||||||
// -----------------------------------
|
|
||||||
Label loop_header, loop_check;
|
|
||||||
__ jmp(&loop_check);
|
|
||||||
__ bind(&loop_header);
|
|
||||||
__ Push(Operand(ebx, 0));
|
|
||||||
__ sub(ebx, Immediate(kPointerSize));
|
|
||||||
__ bind(&loop_check);
|
|
||||||
__ cmp(ebx, array_limit);
|
|
||||||
__ j(greater, &loop_header, Label::kNear);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
@ -750,7 +732,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -- edi : the target to call (can be any Object).
|
// -- edi : the target to call (can be any Object).
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Pop return address to allow tail-call after pushing arguments.
|
// Pop return address to allow tail-call after pushing arguments.
|
||||||
__ Pop(edx);
|
__ Pop(edx);
|
||||||
@ -762,7 +743,15 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
__ neg(ecx);
|
__ neg(ecx);
|
||||||
__ add(ecx, ebx);
|
__ add(ecx, ebx);
|
||||||
|
|
||||||
Generate_InterpreterPushArgs(masm, ecx);
|
// Push the arguments.
|
||||||
|
Label loop_header, loop_check;
|
||||||
|
__ jmp(&loop_check);
|
||||||
|
__ bind(&loop_header);
|
||||||
|
__ Push(Operand(ebx, 0));
|
||||||
|
__ sub(ebx, Immediate(kPointerSize));
|
||||||
|
__ bind(&loop_check);
|
||||||
|
__ cmp(ebx, ecx);
|
||||||
|
__ j(greater, &loop_header, Label::kNear);
|
||||||
|
|
||||||
// Call the target.
|
// Call the target.
|
||||||
__ Push(edx); // Re-push return address.
|
__ Push(edx); // Re-push return address.
|
||||||
@ -770,53 +759,13 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- eax : the number of arguments (not including the receiver)
|
|
||||||
// -- edx : the original constructor
|
|
||||||
// -- edi : the constructor
|
|
||||||
// -- ebx : the address of the first argument to be pushed. Subsequent
|
|
||||||
// arguments should be consecutive above this, in the same order as
|
|
||||||
// they are to be pushed onto the stack.
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Save number of arguments on the stack below where arguments are going
|
|
||||||
// to be pushed.
|
|
||||||
__ mov(ecx, eax);
|
|
||||||
__ neg(ecx);
|
|
||||||
__ mov(Operand(esp, ecx, times_pointer_size, -kPointerSize), eax);
|
|
||||||
__ mov(eax, ecx);
|
|
||||||
|
|
||||||
// Pop return address to allow tail-call after pushing arguments.
|
|
||||||
__ Pop(ecx);
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
|
||||||
__ shl(eax, kPointerSizeLog2);
|
|
||||||
__ add(eax, ebx);
|
|
||||||
|
|
||||||
// Push padding for receiver.
|
|
||||||
__ Push(Immediate(0));
|
|
||||||
|
|
||||||
Generate_InterpreterPushArgs(masm, eax);
|
|
||||||
|
|
||||||
// Restore number of arguments from slot on stack.
|
|
||||||
__ mov(eax, Operand(esp, -kPointerSize));
|
|
||||||
|
|
||||||
// Re-push return address.
|
|
||||||
__ Push(ecx);
|
|
||||||
|
|
||||||
// Call the constructor with unmodified eax, edi, ebi values.
|
|
||||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||||
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
||||||
GenerateTailCallToReturnedCode(masm);
|
GenerateTailCallToReturnedCode(masm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
|
static void CallCompileOptimized(MacroAssembler* masm, bool concurrent) {
|
||||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
// Push a copy of the function.
|
// Push a copy of the function.
|
||||||
|
@ -401,18 +401,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
eax, // argument count (not including receiver)
|
|
||||||
edx, // original constructor
|
|
||||||
edi, // constructor
|
|
||||||
ebx, // address of first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -71,7 +71,6 @@ class PlatformInterfaceDescriptor;
|
|||||||
V(MathRoundVariantCallFromUnoptimizedCode) \
|
V(MathRoundVariantCallFromUnoptimizedCode) \
|
||||||
V(MathRoundVariantCallFromOptimizedCode) \
|
V(MathRoundVariantCallFromOptimizedCode) \
|
||||||
V(InterpreterPushArgsAndCall) \
|
V(InterpreterPushArgsAndCall) \
|
||||||
V(InterpreterPushArgsAndConstruct) \
|
|
||||||
V(InterpreterCEntry)
|
V(InterpreterCEntry)
|
||||||
|
|
||||||
|
|
||||||
@ -717,14 +716,6 @@ class InterpreterPushArgsAndCallDescriptor : public CallInterfaceDescriptor {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class InterpreterPushArgsAndConstructDescriptor
|
|
||||||
: public CallInterfaceDescriptor {
|
|
||||||
public:
|
|
||||||
DECLARE_DESCRIPTOR(InterpreterPushArgsAndConstructDescriptor,
|
|
||||||
CallInterfaceDescriptor)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class InterpreterCEntryDescriptor : public CallInterfaceDescriptor {
|
class InterpreterCEntryDescriptor : public CallInterfaceDescriptor {
|
||||||
public:
|
public:
|
||||||
DECLARE_DESCRIPTOR(InterpreterCEntryDescriptor, CallInterfaceDescriptor)
|
DECLARE_DESCRIPTOR(InterpreterCEntryDescriptor, CallInterfaceDescriptor)
|
||||||
|
@ -599,16 +599,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
|
|
||||||
Register first_arg,
|
|
||||||
size_t arg_count) {
|
|
||||||
DCHECK(FitsInIdx8Operand(arg_count));
|
|
||||||
Output(Bytecode::kNew, constructor.ToOperand(), first_arg.ToOperand(),
|
|
||||||
static_cast<uint8_t>(arg_count));
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
|
BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
|
||||||
Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
|
Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
|
||||||
DCHECK(FitsInIdx16Operand(function_id));
|
DCHECK(FitsInIdx16Operand(function_id));
|
||||||
|
@ -100,19 +100,13 @@ class BytecodeArrayBuilder {
|
|||||||
BytecodeArrayBuilder& Call(Register callable, Register receiver,
|
BytecodeArrayBuilder& Call(Register callable, Register receiver,
|
||||||
size_t arg_count);
|
size_t arg_count);
|
||||||
|
|
||||||
// Call the new operator. The |constructor| register is followed by
|
|
||||||
// |arg_count| consecutive registers containing arguments to be
|
|
||||||
// applied to the constructor.
|
|
||||||
BytecodeArrayBuilder& New(Register constructor, Register first_arg,
|
|
||||||
size_t arg_count);
|
|
||||||
|
|
||||||
// Call the runtime function with |function_id|. The first argument should be
|
// Call the runtime function with |function_id|. The first argument should be
|
||||||
// in |first_arg| and all subsequent arguments should be in registers
|
// in |first_arg| and all subsequent arguments should be in registers
|
||||||
// <first_arg + 1> to <first_arg + 1 + arg_count>.
|
// <first_arg + 1> to <first_arg + 1 + arg_count>.
|
||||||
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
|
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
|
||||||
Register first_arg, size_t arg_count);
|
Register first_arg, size_t arg_count);
|
||||||
|
|
||||||
// Operators (register holds the lhs value, accumulator holds the rhs value).
|
// Operators (register == lhs, accumulator = rhs).
|
||||||
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
|
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
|
||||||
Strength strength);
|
Strength strength);
|
||||||
|
|
||||||
|
@ -934,25 +934,6 @@ void BytecodeGenerator::VisitProperty(Property* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Register BytecodeGenerator::VisitArguments(
|
|
||||||
ZoneList<Expression*>* args, TemporaryRegisterScope* register_scope) {
|
|
||||||
// Visit arguments and place in a contiguous block of temporary registers.
|
|
||||||
// Return the first temporary register corresponding to the first argument.
|
|
||||||
DCHECK_GT(args->length(), 0);
|
|
||||||
Register first_arg = register_scope->NewRegister();
|
|
||||||
Visit(args->at(0));
|
|
||||||
builder()->StoreAccumulatorInRegister(first_arg);
|
|
||||||
for (int i = 1; i < static_cast<int>(args->length()); i++) {
|
|
||||||
Register ith_arg = register_scope->NewRegister();
|
|
||||||
Visit(args->at(i));
|
|
||||||
builder()->StoreAccumulatorInRegister(ith_arg);
|
|
||||||
DCHECK(ith_arg.index() - i == first_arg.index());
|
|
||||||
}
|
|
||||||
|
|
||||||
return first_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGenerator::VisitCall(Call* expr) {
|
void BytecodeGenerator::VisitCall(Call* expr) {
|
||||||
Expression* callee_expr = expr->expression();
|
Expression* callee_expr = expr->expression();
|
||||||
Call::CallType call_type = expr->GetCallType(isolate());
|
Call::CallType call_type = expr->GetCallType(isolate());
|
||||||
@ -1000,9 +981,11 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
|||||||
// Evaluate all arguments to the function call and store in sequential
|
// Evaluate all arguments to the function call and store in sequential
|
||||||
// registers.
|
// registers.
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
if (args->length() > 0) {
|
for (int i = 0; i < args->length(); ++i) {
|
||||||
Register first_arg = VisitArguments(args, &temporary_register_scope);
|
Visit(args->at(i));
|
||||||
CHECK_EQ(first_arg.index(), receiver.index() + 1);
|
Register arg = temporary_register_scope.NewRegister();
|
||||||
|
DCHECK(arg.index() - i == receiver.index() + 1);
|
||||||
|
builder()->StoreAccumulatorInRegister(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(rmcilroy): Deal with possible direct eval here?
|
// TODO(rmcilroy): Deal with possible direct eval here?
|
||||||
@ -1011,22 +994,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGenerator::VisitCallNew(CallNew* expr) {
|
void BytecodeGenerator::VisitCallNew(CallNew* expr) { UNIMPLEMENTED(); }
|
||||||
TemporaryRegisterScope temporary_register_scope(builder());
|
|
||||||
Register constructor = temporary_register_scope.NewRegister();
|
|
||||||
Visit(expr->expression());
|
|
||||||
builder()->StoreAccumulatorInRegister(constructor);
|
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
|
||||||
if (args->length() > 0) {
|
|
||||||
Register first_arg = VisitArguments(args, &temporary_register_scope);
|
|
||||||
builder()->New(constructor, first_arg, args->length());
|
|
||||||
} else {
|
|
||||||
// The second argument here will be ignored as there are zero
|
|
||||||
// arguments. Using the constructor register avoids avoid
|
|
||||||
// allocating a temporary just to fill the operands.
|
|
||||||
builder()->New(constructor, constructor, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
||||||
@ -1035,21 +1003,22 @@ void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate all arguments to the runtime call.
|
// Evaluate all arguments to the runtime call.
|
||||||
TemporaryRegisterScope temporary_register_scope(&builder_);
|
ZoneList<Expression*>* args = expr->arguments();
|
||||||
|
TemporaryRegisterScope temporary_register_scope(builder());
|
||||||
|
// Ensure we always have a valid first_arg register even if there are no
|
||||||
|
// arguments to pass.
|
||||||
|
Register first_arg = temporary_register_scope.NewRegister();
|
||||||
|
for (int i = 0; i < args->length(); ++i) {
|
||||||
|
Register arg =
|
||||||
|
(i == 0) ? first_arg : temporary_register_scope.NewRegister();
|
||||||
|
Visit(args->at(i));
|
||||||
|
DCHECK_EQ(arg.index() - i, first_arg.index());
|
||||||
|
builder()->StoreAccumulatorInRegister(arg);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(rmcilroy): support multiple return values.
|
// TODO(rmcilroy): support multiple return values.
|
||||||
DCHECK_LE(expr->function()->result_size, 1);
|
DCHECK_LE(expr->function()->result_size, 1);
|
||||||
Runtime::FunctionId function_id = expr->function()->function_id;
|
Runtime::FunctionId function_id = expr->function()->function_id;
|
||||||
ZoneList<Expression*>* args = expr->arguments();
|
|
||||||
Register first_arg;
|
|
||||||
if (args->length() > 0) {
|
|
||||||
first_arg = VisitArguments(args, &temporary_register_scope);
|
|
||||||
} else {
|
|
||||||
// Allocation here is just to fullfil the requirement that there
|
|
||||||
// is a register operand for the start of the arguments though
|
|
||||||
// there are zero when this is generated.
|
|
||||||
first_arg = temporary_register_scope.NewRegister();
|
|
||||||
}
|
|
||||||
builder()->CallRuntime(function_id, first_arg, args->length());
|
builder()->CallRuntime(function_id, first_arg, args->length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,8 +36,6 @@ class BytecodeGenerator : public AstVisitor {
|
|||||||
|
|
||||||
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
|
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
|
||||||
|
|
||||||
Register VisitArguments(ZoneList<Expression*>* arguments,
|
|
||||||
TemporaryRegisterScope* caller_scope);
|
|
||||||
void VisitArithmeticExpression(BinaryOperation* binop);
|
void VisitArithmeticExpression(BinaryOperation* binop);
|
||||||
void VisitCommaExpression(BinaryOperation* binop);
|
void VisitCommaExpression(BinaryOperation* binop);
|
||||||
void VisitLogicalOrExpression(BinaryOperation* binop);
|
void VisitLogicalOrExpression(BinaryOperation* binop);
|
||||||
|
@ -89,14 +89,11 @@ namespace interpreter {
|
|||||||
V(LogicalNot, OperandType::kNone) \
|
V(LogicalNot, OperandType::kNone) \
|
||||||
V(TypeOf, OperandType::kNone) \
|
V(TypeOf, OperandType::kNone) \
|
||||||
\
|
\
|
||||||
/* Call operations */ \
|
/* Call operations. */ \
|
||||||
V(Call, OperandType::kReg8, OperandType::kReg8, OperandType::kCount8) \
|
V(Call, OperandType::kReg8, OperandType::kReg8, OperandType::kCount8) \
|
||||||
V(CallRuntime, OperandType::kIdx16, OperandType::kReg8, \
|
V(CallRuntime, OperandType::kIdx16, OperandType::kReg8, \
|
||||||
OperandType::kCount8) \
|
OperandType::kCount8) \
|
||||||
\
|
\
|
||||||
/* New operator */ \
|
|
||||||
V(New, OperandType::kReg8, OperandType::kReg8, OperandType::kCount8) \
|
|
||||||
\
|
|
||||||
/* Test Operators */ \
|
/* Test Operators */ \
|
||||||
V(TestEqual, OperandType::kReg8) \
|
V(TestEqual, OperandType::kReg8) \
|
||||||
V(TestNotEqual, OperandType::kReg8) \
|
V(TestNotEqual, OperandType::kReg8) \
|
||||||
|
@ -537,25 +537,6 @@ void Interpreter::DoCallRuntime(compiler::InterpreterAssembler* assembler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// New <constructor> <arg_count>
|
|
||||||
//
|
|
||||||
// Call operator new with |constructor| and the first argument in
|
|
||||||
// register |first_arg| and |arg_count| arguments in subsequent
|
|
||||||
//
|
|
||||||
void Interpreter::DoNew(compiler::InterpreterAssembler* assembler) {
|
|
||||||
Callable ic = CodeFactory::InterpreterPushArgsAndConstruct(isolate_);
|
|
||||||
Node* constructor_index = __ BytecodeOperandReg8(0);
|
|
||||||
Node* constructor = __ LoadRegister(constructor_index);
|
|
||||||
Node* first_arg_reg = __ BytecodeOperandReg8(1);
|
|
||||||
Node* first_arg = __ RegisterLocation(first_arg_reg);
|
|
||||||
Node* args_count = __ BytecodeOperandCount8(2);
|
|
||||||
Node* result =
|
|
||||||
__ CallConstruct(constructor, constructor, first_arg, args_count);
|
|
||||||
__ SetAccumulator(result);
|
|
||||||
__ Dispatch();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TestEqual <src>
|
// TestEqual <src>
|
||||||
//
|
//
|
||||||
// Test if the value in the <src> register equals the accumulator.
|
// Test if the value in the <src> register equals the accumulator.
|
||||||
|
@ -986,7 +986,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -- a1 : the target to call (can be any Object).
|
// -- a1 : the target to call (can be any Object).
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
// Find the address of the last argument.
|
||||||
__ Addu(a3, a0, Operand(1)); // Add one for receiver.
|
__ Addu(a3, a0, Operand(1)); // Add one for receiver.
|
||||||
@ -1008,34 +1007,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- a0 : argument count (not including receiver)
|
|
||||||
// -- a3 : original constructor
|
|
||||||
// -- a1 : constructor to call
|
|
||||||
// -- a2 : address of the first argument
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
|
||||||
__ sll(t0, a0, kPointerSizeLog2);
|
|
||||||
__ Subu(t0, a2, Operand(t0));
|
|
||||||
|
|
||||||
// Push the arguments.
|
|
||||||
Label loop_header, loop_check;
|
|
||||||
__ Branch(&loop_check);
|
|
||||||
__ bind(&loop_header);
|
|
||||||
__ lw(t1, MemOperand(a2));
|
|
||||||
__ Addu(a2, a2, Operand(-kPointerSize));
|
|
||||||
__ push(t1);
|
|
||||||
__ bind(&loop_check);
|
|
||||||
__ Branch(&loop_header, gt, a2, Operand(t0));
|
|
||||||
|
|
||||||
// Call the constructor with a0, a1, and a3 unmodified.
|
|
||||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||||
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
||||||
GenerateTailCallToReturnedCode(masm);
|
GenerateTailCallToReturnedCode(masm);
|
||||||
|
@ -395,18 +395,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
a0, // argument count (not including receiver)
|
|
||||||
a3, // original constructor
|
|
||||||
a1, // constructor to call
|
|
||||||
a2 // address of the first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -982,7 +982,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -- a1 : the target to call (can be any Object).
|
// -- a1 : the target to call (can be any Object).
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
// Find the address of the last argument.
|
||||||
__ Daddu(a3, a0, Operand(1)); // Add one for receiver.
|
__ Daddu(a3, a0, Operand(1)); // Add one for receiver.
|
||||||
@ -1004,34 +1003,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- a0 : argument count (not including receiver)
|
|
||||||
// -- a3 : original constructor
|
|
||||||
// -- a1 : constructor to call
|
|
||||||
// -- a2 : address of the first argument
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Find the address of the last argument.
|
|
||||||
__ dsll(t0, a0, kPointerSizeLog2);
|
|
||||||
__ Dsubu(t0, a2, Operand(t0));
|
|
||||||
|
|
||||||
// Push the arguments.
|
|
||||||
Label loop_header, loop_check;
|
|
||||||
__ Branch(&loop_check);
|
|
||||||
__ bind(&loop_header);
|
|
||||||
__ ld(t1, MemOperand(a2));
|
|
||||||
__ Daddu(a2, a2, Operand(-kPointerSize));
|
|
||||||
__ push(t1);
|
|
||||||
__ bind(&loop_check);
|
|
||||||
__ Branch(&loop_header, gt, a2, Operand(t0));
|
|
||||||
|
|
||||||
// Call the constructor with a0, a1, and a3 unmodified.
|
|
||||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||||
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
||||||
GenerateTailCallToReturnedCode(masm);
|
GenerateTailCallToReturnedCode(masm);
|
||||||
|
@ -395,18 +395,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
a0, // argument count (not including receiver)
|
|
||||||
a3, // original constructor
|
|
||||||
a1, // constructor to call
|
|
||||||
a2 // address of the first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -983,7 +983,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -- r4 : the target to call (can be any Object).
|
// -- r4 : the target to call (can be any Object).
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Calculate number of arguments (add one for receiver).
|
// Calculate number of arguments (add one for receiver).
|
||||||
__ addi(r6, r3, Operand(1));
|
__ addi(r6, r3, Operand(1));
|
||||||
@ -1002,32 +1001,6 @@ void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- r3 : argument count (not including receiver)
|
|
||||||
// -- r6 : original constructor
|
|
||||||
// -- r4 : constructor to call
|
|
||||||
// -- r5 : address of the first argument
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Calculate number of arguments (add one for receiver).
|
|
||||||
__ mr(r11, r3);
|
|
||||||
|
|
||||||
// Push the arguments.
|
|
||||||
Label loop;
|
|
||||||
__ addi(r5, r5, Operand(kPointerSize)); // Bias up for LoadPU
|
|
||||||
__ mtctr(r11);
|
|
||||||
__ bind(&loop);
|
|
||||||
__ LoadPU(r11, MemOperand(r5, -kPointerSize));
|
|
||||||
__ push(r11);
|
|
||||||
__ bdnz(&loop);
|
|
||||||
|
|
||||||
// Call the constructor with r3, r4, and r6 unmodified.
|
|
||||||
__ Jump(masm->isolate()->builtins()->Constuct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||||
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
||||||
GenerateTailCallToReturnedCode(masm);
|
GenerateTailCallToReturnedCode(masm);
|
||||||
|
@ -394,18 +394,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
r3, // argument count (not including receiver)
|
|
||||||
r6, // original constructor
|
|
||||||
r4, // constructor to call
|
|
||||||
r5 // address of the first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -785,21 +785,21 @@ void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
|
// static
|
||||||
bool push_receiver) {
|
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
||||||
// ----------- S t a t e -------------
|
// ----------- S t a t e -------------
|
||||||
// -- rax : the number of arguments (not including the receiver)
|
// -- rax : the number of arguments (not including the receiver)
|
||||||
// -- rbx : the address of the first argument to be pushed. Subsequent
|
// -- rbx : the address of the first argument to be pushed. Subsequent
|
||||||
// arguments should be consecutive above this, in the same order as
|
// arguments should be consecutive above this, in the same order as
|
||||||
// they are to be pushed onto the stack.
|
// they are to be pushed onto the stack.
|
||||||
// -----------------------------------
|
// -- rdi : the target to call (can be any Object).
|
||||||
|
|
||||||
|
// Pop return address to allow tail-call after pushing arguments.
|
||||||
|
__ Pop(rdx);
|
||||||
|
|
||||||
// Find the address of the last argument.
|
// Find the address of the last argument.
|
||||||
__ movp(rcx, rax);
|
__ movp(rcx, rax);
|
||||||
if (push_receiver) {
|
|
||||||
__ addp(rcx, Immediate(1)); // Add one for receiver.
|
__ addp(rcx, Immediate(1)); // Add one for receiver.
|
||||||
}
|
|
||||||
|
|
||||||
__ shlp(rcx, Immediate(kPointerSizeLog2));
|
__ shlp(rcx, Immediate(kPointerSizeLog2));
|
||||||
__ negp(rcx);
|
__ negp(rcx);
|
||||||
__ addp(rcx, rbx);
|
__ addp(rcx, rbx);
|
||||||
@ -813,58 +813,13 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
|
|||||||
__ bind(&loop_check);
|
__ bind(&loop_check);
|
||||||
__ cmpp(rbx, rcx);
|
__ cmpp(rbx, rcx);
|
||||||
__ j(greater, &loop_header, Label::kNear);
|
__ j(greater, &loop_header, Label::kNear);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- rax : the number of arguments (not including the receiver)
|
|
||||||
// -- rbx : the address of the first argument to be pushed. Subsequent
|
|
||||||
// arguments should be consecutive above this, in the same order as
|
|
||||||
// they are to be pushed onto the stack.
|
|
||||||
// -- rdi : the target to call (can be any Object).
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Pop return address to allow tail-call after pushing arguments.
|
|
||||||
__ PopReturnAddressTo(kScratchRegister);
|
|
||||||
|
|
||||||
Generate_InterpreterPushArgs(masm, true);
|
|
||||||
|
|
||||||
// Call the target.
|
// Call the target.
|
||||||
__ PushReturnAddressFrom(kScratchRegister); // Re-push return address.
|
__ Push(rdx); // Re-push return address.
|
||||||
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
__ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
|
||||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
|
||||||
// ----------- S t a t e -------------
|
|
||||||
// -- rax : the number of arguments (not including the receiver)
|
|
||||||
// -- rdx : the original constructor (either the same as the constructor or
|
|
||||||
// the JSFunction on which new was invoked initially)
|
|
||||||
// -- rdi : the constructor to call (can be any Object)
|
|
||||||
// -- rbx : the address of the first argument to be pushed. Subsequent
|
|
||||||
// arguments should be consecutive above this, in the same order as
|
|
||||||
// they are to be pushed onto the stack.
|
|
||||||
// -----------------------------------
|
|
||||||
|
|
||||||
// Pop return address to allow tail-call after pushing arguments.
|
|
||||||
__ PopReturnAddressTo(kScratchRegister);
|
|
||||||
|
|
||||||
// Push slot for the receiver to be constructed.
|
|
||||||
__ Push(Immediate(0));
|
|
||||||
|
|
||||||
Generate_InterpreterPushArgs(masm, false);
|
|
||||||
|
|
||||||
// Push return address in preparation for the tail-call.
|
|
||||||
__ PushReturnAddressFrom(kScratchRegister);
|
|
||||||
|
|
||||||
// Call the constructor (rax, rdx, rdi passed on).
|
|
||||||
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CONSTRUCT_CALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
|
||||||
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
CallRuntimePassFunction(masm, Runtime::kCompileLazy);
|
||||||
GenerateTailCallToReturnedCode(masm);
|
GenerateTailCallToReturnedCode(masm);
|
||||||
|
@ -395,18 +395,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
|
||||||
CallInterfaceDescriptorData* data) {
|
|
||||||
Register registers[] = {
|
|
||||||
rax, // argument count (not including receiver)
|
|
||||||
rdx, // original constructor
|
|
||||||
rdi, // constructor
|
|
||||||
rbx, // address of first argument
|
|
||||||
};
|
|
||||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
void InterpreterCEntryDescriptor::InitializePlatformSpecific(
|
||||||
CallInterfaceDescriptorData* data) {
|
CallInterfaceDescriptorData* data) {
|
||||||
Register registers[] = {
|
Register registers[] = {
|
||||||
|
@ -1015,14 +1015,14 @@ TEST(PropertyCall) {
|
|||||||
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
|
B(LoadICSloppy), R(1), U8(vector->GetIndex(slot2)), //
|
||||||
B(Star), R(0), //
|
B(Star), R(0), //
|
||||||
B(Ldar), R(helper.kLastParamIndex), //
|
B(Ldar), R(helper.kLastParamIndex), //
|
||||||
B(Star), R(3), //
|
B(Star), R(2), //
|
||||||
B(Ldar), R(helper.kLastParamIndex), //
|
B(Ldar), R(helper.kLastParamIndex), //
|
||||||
B(Add), R(3), //
|
B(Add), R(2), //
|
||||||
B(Star), R(2), //
|
B(Star), R(2), //
|
||||||
B(Ldar), R(helper.kLastParamIndex), //
|
B(Ldar), R(helper.kLastParamIndex), //
|
||||||
B(Star), R(3), //
|
B(Star), R(3), //
|
||||||
B(Call), R(0), R(1), U8(2), //
|
B(Call), R(0), R(1), U8(2), //
|
||||||
B(Return), //
|
B(Return) //
|
||||||
},
|
},
|
||||||
1,
|
1,
|
||||||
{"func"}}};
|
{"func"}}};
|
||||||
@ -2670,72 +2670,6 @@ TEST(TryFinally) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(CallNew) {
|
|
||||||
InitializedHandleScope handle_scope;
|
|
||||||
BytecodeGeneratorHelper helper;
|
|
||||||
|
|
||||||
ExpectedSnippet<InstanceType> snippets[] = {
|
|
||||||
{"function bar() { this.value = 0; }\n"
|
|
||||||
"function f() { return new bar(); }\n"
|
|
||||||
"f()",
|
|
||||||
kPointerSize,
|
|
||||||
1,
|
|
||||||
9,
|
|
||||||
{
|
|
||||||
B(LdaGlobal), _, //
|
|
||||||
B(Star), R(0), //
|
|
||||||
B(New), R(0), R(0), U8(0), //
|
|
||||||
B(Return), //
|
|
||||||
},
|
|
||||||
0},
|
|
||||||
{"function bar(x) { this.value = 18; this.x = x;}\n"
|
|
||||||
"function f() { return new bar(3); }\n"
|
|
||||||
"f()",
|
|
||||||
2 * kPointerSize,
|
|
||||||
1,
|
|
||||||
13,
|
|
||||||
{
|
|
||||||
B(LdaGlobal), _, //
|
|
||||||
B(Star), R(0), //
|
|
||||||
B(LdaSmi8), U8(3), //
|
|
||||||
B(Star), R(1), //
|
|
||||||
B(New), R(0), R(1), U8(1), //
|
|
||||||
B(Return), //
|
|
||||||
},
|
|
||||||
0},
|
|
||||||
{"function bar(w, x, y, z) {\n"
|
|
||||||
" this.value = 18;\n"
|
|
||||||
" this.x = x;\n"
|
|
||||||
" this.y = y;\n"
|
|
||||||
" this.z = z;\n"
|
|
||||||
"}\n"
|
|
||||||
"function f() { return new bar(3, 4, 5); }\n"
|
|
||||||
"f()",
|
|
||||||
4 * kPointerSize,
|
|
||||||
1,
|
|
||||||
21,
|
|
||||||
{
|
|
||||||
B(LdaGlobal), _, //
|
|
||||||
B(Star), R(0), //
|
|
||||||
B(LdaSmi8), U8(3), //
|
|
||||||
B(Star), R(1), //
|
|
||||||
B(LdaSmi8), U8(4), //
|
|
||||||
B(Star), R(2), //
|
|
||||||
B(LdaSmi8), U8(5), //
|
|
||||||
B(Star), R(3), //
|
|
||||||
B(New), R(0), R(1), U8(3), //
|
|
||||||
B(Return), //
|
|
||||||
},
|
|
||||||
0}};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
|
||||||
Handle<BytecodeArray> bytecode_array =
|
|
||||||
helper.MakeBytecode(snippets[i].code_snippet, "f");
|
|
||||||
CheckBytecodeArrayEqual(snippets[i], bytecode_array, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace interpreter
|
} // namespace interpreter
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
@ -1728,65 +1728,6 @@ TEST(InterpreterObjectLiterals) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(InterpreterConstruct) {
|
|
||||||
HandleAndZoneScope handles;
|
|
||||||
|
|
||||||
std::string source(
|
|
||||||
"function counter() { this.count = 0; }\n"
|
|
||||||
"function " +
|
|
||||||
InterpreterTester::function_name() +
|
|
||||||
"() {\n"
|
|
||||||
" var c = new counter();\n"
|
|
||||||
" return c.count;\n"
|
|
||||||
"}");
|
|
||||||
InterpreterTester tester(handles.main_isolate(), source.c_str());
|
|
||||||
auto callable = tester.GetCallable<>();
|
|
||||||
|
|
||||||
Handle<Object> return_val = callable().ToHandleChecked();
|
|
||||||
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(InterpreterConstructWithArgument) {
|
|
||||||
HandleAndZoneScope handles;
|
|
||||||
|
|
||||||
std::string source(
|
|
||||||
"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
|
|
||||||
"function " +
|
|
||||||
InterpreterTester::function_name() +
|
|
||||||
"() {\n"
|
|
||||||
" var c = new counter(3);\n"
|
|
||||||
" return c.x;\n"
|
|
||||||
"}");
|
|
||||||
InterpreterTester tester(handles.main_isolate(), source.c_str());
|
|
||||||
auto callable = tester.GetCallable<>();
|
|
||||||
|
|
||||||
Handle<Object> return_val = callable().ToHandleChecked();
|
|
||||||
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(InterpreterConstructWithArguments) {
|
|
||||||
HandleAndZoneScope handles;
|
|
||||||
|
|
||||||
std::string source(
|
|
||||||
"function counter(arg0, arg1) {\n"
|
|
||||||
" this.count = 7; this.x = arg0; this.y = arg1;\n"
|
|
||||||
"}\n"
|
|
||||||
"function " +
|
|
||||||
InterpreterTester::function_name() +
|
|
||||||
"() {\n"
|
|
||||||
" var c = new counter(3, 5);\n"
|
|
||||||
" return c.count + c.x + c.y;\n"
|
|
||||||
"}");
|
|
||||||
InterpreterTester tester(handles.main_isolate(), source.c_str());
|
|
||||||
auto callable = tester.GetCallable<>();
|
|
||||||
|
|
||||||
Handle<Object> return_val = callable().ToHandleChecked();
|
|
||||||
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TEST(InterpreterComma) {
|
TEST(InterpreterComma) {
|
||||||
HandleAndZoneScope handles;
|
HandleAndZoneScope handles;
|
||||||
i::Isolate* isolate = handles.main_isolate();
|
i::Isolate* isolate = handles.main_isolate();
|
||||||
|
@ -90,9 +90,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
|||||||
// Emit unary operator invocations.
|
// Emit unary operator invocations.
|
||||||
builder.LogicalNot().TypeOf();
|
builder.LogicalNot().TypeOf();
|
||||||
|
|
||||||
// Emit new.
|
|
||||||
builder.New(reg, reg, 0);
|
|
||||||
|
|
||||||
// Emit test operator invocations.
|
// Emit test operator invocations.
|
||||||
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK)
|
||||||
.CompareOperation(Token::Value::NE, reg, Strength::WEAK)
|
.CompareOperation(Token::Value::NE, reg, Strength::WEAK)
|
||||||
|
Loading…
Reference in New Issue
Block a user