| Index: src/x64/lithium-codegen-x64.cc
|
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
|
| index 65bd1f8d776e74ffecbff4e75445194f408ac986..d6c7640bb48dcebdc6ecafa2384625f19efba1e4 100644
|
| --- a/src/x64/lithium-codegen-x64.cc
|
| +++ b/src/x64/lithium-codegen-x64.cc
|
| @@ -37,6 +37,37 @@ namespace v8 {
|
| namespace internal {
|
|
|
|
|
| +// When invoking builtins, we need to record the safepoint in the middle of
|
| +// the invoke instruction sequence generated by the macro assembler.
|
| +class SafepointGenerator : public PostCallGenerator {
|
| + public:
|
| + SafepointGenerator(LCodeGen* codegen,
|
| + LPointerMap* pointers,
|
| + int deoptimization_index,
|
| + bool ensure_reloc_space = false)
|
| + : codegen_(codegen),
|
| + pointers_(pointers),
|
| + deoptimization_index_(deoptimization_index),
|
| + ensure_reloc_space_(ensure_reloc_space) { }
|
| + virtual ~SafepointGenerator() { }
|
| +
|
| + virtual void Generate() {
|
| + // Ensure that we have enough space in the reloc info to patch
|
| + // this with calls when doing deoptimization.
|
| + if (ensure_reloc_space_) {
|
| + codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true);
|
| + }
|
| + codegen_->RecordSafepoint(pointers_, deoptimization_index_);
|
| + }
|
| +
|
| + private:
|
| + LCodeGen* codegen_;
|
| + LPointerMap* pointers_;
|
| + int deoptimization_index_;
|
| + bool ensure_reloc_space_;
|
| +};
|
| +
|
| +
|
| #define __ masm()->
|
|
|
| bool LCodeGen::GenerateCode() {
|
| @@ -1996,7 +2027,70 @@ void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) {
|
|
|
|
|
| void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
|
| - Abort("Unimplemented: %s", "DoApplyArguments");
|
| + Register receiver = ToRegister(instr->receiver());
|
| + Register function = ToRegister(instr->function());
|
| + Register length = ToRegister(instr->length());
|
| + Register elements = ToRegister(instr->elements());
|
| + ASSERT(receiver.is(rax)); // Used for parameter count.
|
| + ASSERT(function.is(rdi)); // Required by InvokeFunction.
|
| + ASSERT(ToRegister(instr->result()).is(rax));
|
| +
|
| + // If the receiver is null or undefined, we have to pass the global object
|
| + // as a receiver.
|
| + NearLabel global_object, receiver_ok;
|
| + __ CompareRoot(receiver, Heap::kNullValueRootIndex);
|
| + __ j(equal, &global_object);
|
| + __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
|
| + __ j(equal, &global_object);
|
| +
|
| + // The receiver should be a JS object.
|
| + Condition is_smi = __ CheckSmi(receiver);
|
| + DeoptimizeIf(is_smi, instr->environment());
|
| + __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, kScratchRegister);
|
| + DeoptimizeIf(below, instr->environment());
|
| + __ jmp(&receiver_ok);
|
| +
|
| + __ bind(&global_object);
|
| + // TODO(kmillikin): We have a hydrogen value for the global object. See
|
| + // if it's better to use it than to explicitly fetch it from the context
|
| + // here.
|
| + __ movq(receiver, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + __ movq(receiver, ContextOperand(receiver, Context::GLOBAL_INDEX));
|
| + __ bind(&receiver_ok);
|
| +
|
| + // Copy the arguments to this function possibly from the
|
| + // adaptor frame below it.
|
| + const uint32_t kArgumentsLimit = 1 * KB;
|
| + __ cmpq(length, Immediate(kArgumentsLimit));
|
| + DeoptimizeIf(above, instr->environment());
|
| +
|
| + __ push(receiver);
|
| + __ movq(receiver, length);
|
| +
|
| + // Loop through the arguments pushing them onto the execution
|
| + // stack.
|
| + NearLabel invoke, loop;
|
| + // length is a small non-negative integer, due to the test above.
|
| + __ testl(length, length);
|
| + __ j(zero, &invoke);
|
| + __ bind(&loop);
|
| + __ push(Operand(elements, length, times_pointer_size, 1 * kPointerSize));
|
| + __ decl(length);
|
| + __ j(not_zero, &loop);
|
| +
|
| + // Invoke the function.
|
| + __ bind(&invoke);
|
| + ASSERT(instr->HasPointerMap() && instr->HasDeoptimizationEnvironment());
|
| + LPointerMap* pointers = instr->pointer_map();
|
| + LEnvironment* env = instr->deoptimization_environment();
|
| + RecordPosition(pointers->position());
|
| + RegisterEnvironmentForDeoptimization(env);
|
| + SafepointGenerator safepoint_generator(this,
|
| + pointers,
|
| + env->deoptimization_index(),
|
| + true);
|
| + v8::internal::ParameterCount actual(rax);
|
| + __ InvokeFunction(function, actual, CALL_FUNCTION, &safepoint_generator);
|
| }
|
|
|
|
|
|
|