| Index: runtime/vm/stub_code_x64.cc
|
| ===================================================================
|
| --- runtime/vm/stub_code_x64.cc (revision 3170)
|
| +++ runtime/vm/stub_code_x64.cc (working copy)
|
| @@ -676,7 +676,7 @@
|
| // R10: Array length as Smi.
|
| {
|
| Label size_tag_overflow, done;
|
| - __ leaq(RBX, Address(R10, TIMES_2, fixed_size)); // R10 is Smi.
|
| + __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi.
|
| ASSERT(kSmiTagShift == 1);
|
| __ andq(RBX, Immediate(-kObjectAlignment));
|
| __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag));
|
| @@ -730,8 +730,102 @@
|
| }
|
|
|
|
|
| +// Input parameters:
|
| +// R10: Arguments descriptor array (num_args is first Smi element, closure
|
| +// object is not included in num_args).
|
| +// Note: The closure object is pushed before the first argument to the function
|
| +// being called, the stub accesses the closure from this location directly
|
| +// when setting up the context and resolving the entry point.
|
| +// Uses R13.
|
| void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
|
| - __ Unimplemented("CallClosureFunction stub");
|
| + const Immediate raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| +
|
| + // Total number of args is the first Smi in args descriptor array (R10).
|
| + __ movq(RAX, FieldAddress(R10, Array::data_offset())); // Load num_args.
|
| + // Load closure object in R13.
|
| + __ movq(R13, Address(RSP, RAX, TIMES_4, kWordSize)); // RAX is a Smi.
|
| +
|
| + // Verify that R13 is a closure by checking its class.
|
| + Label not_closure;
|
| + __ cmpq(R13, raw_null);
|
| + // Not a closure, but null object.
|
| + __ j(EQUAL, ¬_closure, Assembler::kNearJump);
|
| + __ testq(R13, Immediate(kSmiTagMask));
|
| + __ j(ZERO, ¬_closure, Assembler::kNearJump); // Not a closure, but a smi.
|
| + // Verify that the class of the object is a closure class by checking that
|
| + // class.signature_function() is not null.
|
| + __ movq(RAX, FieldAddress(R13, Object::class_offset()));
|
| + __ movq(RAX, FieldAddress(RAX, Class::signature_function_offset()));
|
| + __ cmpq(RAX, raw_null);
|
| + // Actual class is not a closure class.
|
| + __ j(EQUAL, ¬_closure, Assembler::kNearJump);
|
| +
|
| + // RAX is just the signature function. Load the actual closure function.
|
| + __ movq(RBX, FieldAddress(R13, Closure::function_offset()));
|
| +
|
| + // Load closure context in CTX; note that CTX has already been preserved.
|
| + __ movq(CTX, FieldAddress(R13, Closure::context_offset()));
|
| +
|
| + // Load closure function code in RAX.
|
| + __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
|
| + __ cmpq(RAX, raw_null);
|
| + Label function_compiled;
|
| + __ j(NOT_EQUAL, &function_compiled, Assembler::kNearJump);
|
| +
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| + __ EnterFrame(0);
|
| +
|
| + __ pushq(R10); // Preserve arguments descriptor array.
|
| + __ pushq(RBX);
|
| + __ CallRuntimeFromStub(kCompileFunctionRuntimeEntry);
|
| + __ popq(RBX); // Restore read-only function object argument in RBX.
|
| + __ popq(R10); // Restore arguments descriptor array.
|
| + // Restore RAX.
|
| + __ movq(RAX, FieldAddress(RBX, Function::code_offset()));
|
| +
|
| + // Remove the stub frame as we are about to jump to the closure function.
|
| + __ LeaveFrame();
|
| +
|
| + __ Bind(&function_compiled);
|
| + // RAX: Code.
|
| + // RBX: Function.
|
| + // R10: Arguments descriptor array (num_args is first Smi element).
|
| +
|
| + __ movq(RBX, FieldAddress(RAX, Code::instructions_offset()));
|
| + __ addq(RBX, Immediate(Instructions::HeaderSize() - kHeapObjectTag));
|
| + __ jmp(RBX);
|
| +
|
| + __ Bind(¬_closure);
|
| + // Call runtime to report that a closure call was attempted on a non-closure
|
| + // object, passing the non-closure object and its arguments array.
|
| + // R13: non-closure object.
|
| + // R10: arguments descriptor array (num_args is first Smi element, closure
|
| + // object is not included in num_args).
|
| +
|
| + // Create a stub frame as we are pushing some objects on the stack before
|
| + // calling into the runtime.
|
| + __ EnterFrame(0);
|
| +
|
| + __ pushq(raw_null); // Setup space on stack for result from error reporting.
|
| + __ pushq(R13); // Non-closure object.
|
| + // Total number of args is the first Smi in args descriptor array (R10).
|
| + __ movq(R13, FieldAddress(R10, Array::data_offset())); // Load num_args.
|
| + __ SmiUntag(R13);
|
| + // See stack layout below explaining "wordSize * 4" offset.
|
| + PushArgumentsArray(assembler, (kWordSize * 4));
|
| +
|
| + // Stack:
|
| + // TOS + 0: Argument array.
|
| + // TOS + 1: Non-closure object.
|
| + // TOS + 2: Place for result from reporting the error.
|
| + // TOS + 3: Saved RBP of previous frame. <== RBP
|
| + // TOS + 4: Dart code return address
|
| + // TOS + 5: Last argument of caller.
|
| + // ....
|
| + __ CallRuntimeFromStub(kReportObjectNotClosureRuntimeEntry);
|
| + __ Stop("runtime call throws an exception");
|
| }
|
|
|
|
|
| @@ -853,10 +947,9 @@
|
|
|
| // Called for inline allocation of contexts.
|
| // Input:
|
| -// RDX: number of context variables.
|
| +// R10: number of context variables.
|
| // Output:
|
| // RAX: new allocated RawContext object.
|
| -// RBX and RDX are destroyed.
|
| void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
|
| const Immediate raw_null =
|
| Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| @@ -867,8 +960,8 @@
|
| // Create the stub frame.
|
| __ EnterFrame(0);
|
| __ pushq(raw_null); // Setup space on stack for the return value.
|
| - __ SmiTag(RDX);
|
| - __ pushq(RDX); // Push number of context variables.
|
| + __ SmiTag(R10);
|
| + __ pushq(R10); // Push number of context variables.
|
| __ CallRuntimeFromStub(kAllocateContextRuntimeEntry); // Allocate context.
|
| __ popq(RAX); // Pop number of context variables argument.
|
| __ popq(RAX); // Pop the new context object.
|
| @@ -879,8 +972,6 @@
|
| }
|
|
|
|
|
| -
|
| -
|
| // Called for inline allocation of objects.
|
| // Input parameters:
|
| // RSP + 16 : type arguments object (only if class is parameterized).
|
| @@ -1141,11 +1232,68 @@
|
| }
|
|
|
|
|
| +// Called for invoking noSuchMethod function from the entry code of a dart
|
| +// function after an error in passed named arguments is detected.
|
| +// Input parameters:
|
| +// RBP : points to previous frame pointer.
|
| +// RBP + 8 : points to return address.
|
| +// RBP + 16 : address of last argument (arg n-1).
|
| +// RBP + 16 + 8*(n-1) : address of first argument (arg 0).
|
| +// RBX : ic-data array.
|
| +// R10 : arguments descriptor array.
|
| void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
|
| - __ Unimplemented("CallNoSuchMethodFunction stub");
|
| + // The target function was not found, so invoke method
|
| + // "void noSuchMethod(function_name, Array arguments)".
|
| + // TODO(regis): For now, we simply pass the actual arguments, both positional
|
| + // and named, as the argument array. This is not correct if out-of-order
|
| + // named arguments were passed.
|
| + // The signature of the "noSuchMethod" method has to change from
|
| + // noSuchMethod(String name, Array arguments) to something like
|
| + // noSuchMethod(InvocationMirror call).
|
| + // Also, the class NoSuchMethodException has to be modified accordingly.
|
| + // Total number of args is the first Smi in args descriptor array (R10).
|
| + const Immediate raw_null =
|
| + Immediate(reinterpret_cast<intptr_t>(Object::null()));
|
| + __ movq(R13, FieldAddress(R10, Array::data_offset())); // R13 is Smi.
|
| + __ movq(RAX, Address(RBP, R13, TIMES_4, kWordSize)); // Get receiver.
|
| +
|
| + __ EnterFrame(0);
|
| + __ pushq(raw_null); // Setup space on stack for result from noSuchMethod.
|
| + __ pushq(RAX); // Receiver.
|
| + __ pushq(RBX); // IC data array.
|
| + __ pushq(R10); // Arguments descriptor array.
|
| + __ SmiUntag(R13);
|
| + __ subq(R13, Immediate(1)); // Arguments array length, minus the receiver.
|
| + // See stack layout below explaining "wordSize * 8" offset.
|
| + PushArgumentsArray(assembler, (kWordSize * 8));
|
| +
|
| + // Stack:
|
| + // TOS + 0: Argument array.
|
| + // TOS + 1: Arguments descriptor array.
|
| + // TOS + 2: Ic-data array.
|
| + // TOS + 3: Receiver.
|
| + // TOS + 4: Place for result from noSuchMethod.
|
| + // TOS + 5: Saved RBP of previous frame. <== RBP
|
| + // TOS + 6: Dart callee (or stub) code return address
|
| + // TOS + 7: Saved RBP of dart caller frame.
|
| + // TOS + 8: Dart caller code return address
|
| + // TOS + 9: Last argument of caller.
|
| + // ....
|
| + __ CallRuntimeFromStub(kInvokeNoSuchMethodFunctionRuntimeEntry);
|
| + // Remove arguments.
|
| + __ popq(RAX);
|
| + __ popq(RAX);
|
| + __ popq(RAX);
|
| + __ popq(RAX);
|
| + __ popq(RAX); // Get result into RAX.
|
| +
|
| + // Remove the stub frame as we are about to return.
|
| + __ LeaveFrame();
|
| + __ ret();
|
| }
|
|
|
|
|
| +
|
| // Generate inline cache check for 'num_args'.
|
| // RBX: Inline cache data array.
|
| // R10: Arguments array.
|
|
|