Chromium Code Reviews| Index: src/x64/lithium-codegen-x64.cc |
| diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc |
| index f8204c5ca02b2663d09a12a0ef00cea0e7045ef8..44eff212e177a7ed3f5b4a41dfe0ecfd18354a0b 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,71 @@ 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()); |
| + Register scratch = ToRegister(instr->TempAt(0)); |
|
Rico
2011/02/18 16:49:11
Can't we use our normal kScratchRegister here?
Mads Ager (chromium)
2011/02/21 07:38:35
Done.
|
| + 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, scratch); |
| + 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); |
| } |