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); |
} |