Simplify behavior of code stubs that accept a variable number of stack
authormvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 13 Nov 2013 10:07:04 +0000 (10:07 +0000)
committermvstanton@chromium.org <mvstanton@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 13 Nov 2013 10:07:04 +0000 (10:07 +0000)
arguments in addition to their parameters. Before, we'd add a special
variable to the environment with the value of a register with the
number of arguments. Now, that register just appears as a parameter to
the code stub.

BUG=
R=verwaest@chromium.org

Review URL: https://codereview.chromium.org/70203002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17680 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

15 files changed:
src/arm/code-stubs-arm.cc
src/arm/deoptimizer-arm.cc
src/arm/lithium-arm.cc
src/code-stubs-hydrogen.cc
src/code-stubs.cc
src/code-stubs.h
src/deoptimizer.cc
src/deoptimizer.h
src/ia32/code-stubs-ia32.cc
src/ia32/deoptimizer-ia32.cc
src/ia32/lithium-ia32.cc
src/runtime.cc
src/x64/code-stubs-x64.cc
src/x64/deoptimizer-x64.cc
src/x64/lithium-x64.cc

index 2607f9e..94e114f 100644 (file)
@@ -189,14 +189,21 @@ static void InitializeArrayConstructorDescriptor(
   // r0 -- number of arguments
   // r1 -- function
   // r2 -- type info cell with elements kind
-  static Register registers[] = { r1, r2 };
-  descriptor->register_param_count_ = 2;
-  if (constant_stack_parameter_count != 0) {
+  static Register registers_variable_args[] = { r1, r2, r0 };
+  static Register registers_no_args[] = { r1, r2 };
+
+  if (constant_stack_parameter_count == 0) {
+    descriptor->register_param_count_ = 2;
+    descriptor->register_params_ = registers_no_args;
+  } else {
     // stack param count needs (constructor pointer, and single argument)
+    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
     descriptor->stack_parameter_count_ = r0;
+    descriptor->register_param_count_ = 3;
+    descriptor->register_params_ = registers_variable_args;
   }
+
   descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
-  descriptor->register_params_ = registers;
   descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
@@ -210,15 +217,21 @@ static void InitializeInternalArrayConstructorDescriptor(
   // register state
   // r0 -- number of arguments
   // r1 -- constructor function
-  static Register registers[] = { r1 };
-  descriptor->register_param_count_ = 1;
+  static Register registers_variable_args[] = { r1, r0 };
+  static Register registers_no_args[] = { r1 };
 
-  if (constant_stack_parameter_count != 0) {
+  if (constant_stack_parameter_count == 0) {
+    descriptor->register_param_count_ = 1;
+    descriptor->register_params_ = registers_no_args;
+  } else {
     // stack param count needs (constructor pointer, and single argument)
+    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
     descriptor->stack_parameter_count_ = r0;
+    descriptor->register_param_count_ = 2;
+    descriptor->register_params_ = registers_variable_args;
   }
+
   descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
-  descriptor->register_params_ = registers;
   descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
index 9339c5f..c846f98 100644 (file)
@@ -107,7 +107,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
   ApiFunction function(descriptor->deoptimization_handler_);
   ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_);
   intptr_t handler = reinterpret_cast<intptr_t>(xref.address());
-  int params = descriptor->environment_length();
+  int params = descriptor->GetHandlerParameterCount();
   output_frame->SetRegister(r0.code(), params);
   output_frame->SetRegister(r1.code(), handler);
 }
index 480cf98..787fc81 100644 (file)
@@ -2499,7 +2499,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
     CodeStubInterfaceDescriptor* descriptor =
         info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
     int index = static_cast<int>(instr->index());
-    Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index);
+    Register reg = descriptor->GetParameterRegister(index);
     return DefineFixed(result, reg);
   }
 }
index 76786d1..a790179 100644 (file)
@@ -150,26 +150,24 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
   next_block->SetJoinId(BailoutId::StubEntry());
   set_current_block(next_block);
 
+  bool runtime_stack_params = descriptor_->stack_parameter_count_.is_valid();
+  HInstruction* stack_parameter_count = NULL;
   for (int i = 0; i < param_count; ++i) {
-    HParameter* param =
-        Add<HParameter>(i, HParameter::REGISTER_PARAMETER);
+    Representation r = descriptor_->IsParameterCountRegister(i)
+        ? Representation::Integer32()
+        : Representation::Tagged();
+    HParameter* param = Add<HParameter>(i, HParameter::REGISTER_PARAMETER, r);
     start_environment->Bind(i, param);
     parameters_[i] = param;
+    if (descriptor_->IsParameterCountRegister(i)) {
+      param->set_type(HType::Smi());
+      stack_parameter_count = param;
+      arguments_length_ = stack_parameter_count;
+    }
   }
 
-  HInstruction* stack_parameter_count;
-  if (descriptor_->stack_parameter_count_.is_valid()) {
-    ASSERT(descriptor_->environment_length() == (param_count + 1));
-    stack_parameter_count = New<HParameter>(param_count,
-                                            HParameter::REGISTER_PARAMETER,
-                                            Representation::Integer32());
-    stack_parameter_count->set_type(HType::Smi());
-    // It's essential to bind this value to the environment in case of deopt.
-    AddInstruction(stack_parameter_count);
-    start_environment->Bind(param_count, stack_parameter_count);
-    arguments_length_ = stack_parameter_count;
-  } else {
-    ASSERT(descriptor_->environment_length() == param_count);
+  ASSERT(!runtime_stack_params || arguments_length_ != NULL);
+  if (!runtime_stack_params) {
     stack_parameter_count = graph()->GetConstantMinus1();
     arguments_length_ = graph()->GetConstant0();
   }
@@ -189,10 +187,11 @@ bool CodeStubGraphBuilderBase::BuildGraph() {
   if (descriptor_->function_mode_ == JS_FUNCTION_STUB_MODE) {
     if (!stack_parameter_count->IsConstant() &&
         descriptor_->hint_stack_parameter_count_ < 0) {
-      HInstruction* amount = graph()->GetConstant1();
-      stack_pop_count = Add<HAdd>(stack_parameter_count, amount);
-      stack_pop_count->ChangeRepresentation(Representation::Integer32());
+      HInstruction* constant_one = graph()->GetConstant1();
+      stack_pop_count = Add<HAdd>(stack_parameter_count, constant_one);
       stack_pop_count->ClearFlag(HValue::kCanOverflow);
+      // TODO(mvstanton): verify that stack_parameter_count+1 really fits in a
+      // smi.
     } else {
       int count = descriptor_->hint_stack_parameter_count_;
       stack_pop_count = Add<HConstant>(count);
index e76bed3..f6e880f 100644 (file)
@@ -46,6 +46,7 @@ CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
       function_mode_(NOT_JS_FUNCTION_STUB_MODE),
       register_params_(NULL),
       deoptimization_handler_(NULL),
+      handler_arguments_mode_(DONT_PASS_ARGUMENTS),
       miss_handler_(),
       has_miss_handler_(false) { }
 
index b56a3ec..8f1b686 100644 (file)
@@ -277,23 +277,23 @@ class PlatformCodeStub : public CodeStub {
 
 
 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
-
+enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
 
 struct CodeStubInterfaceDescriptor {
   CodeStubInterfaceDescriptor();
   int register_param_count_;
+
   Register stack_parameter_count_;
   // if hint_stack_parameter_count_ > 0, the code stub can optimize the
   // return sequence. Default value is -1, which means it is ignored.
   int hint_stack_parameter_count_;
   StubFunctionMode function_mode_;
   Register* register_params_;
+
   Address deoptimization_handler_;
+  HandlerArgumentsMode handler_arguments_mode_;
 
   int environment_length() const {
-    if (stack_parameter_count_.is_valid()) {
-      return register_param_count_ + 1;
-    }
     return register_param_count_;
   }
 
@@ -302,6 +302,9 @@ struct CodeStubInterfaceDescriptor {
   void SetMissHandler(ExternalReference handler) {
     miss_handler_ = handler;
     has_miss_handler_ = true;
+    // Our miss handler infrastructure doesn't currently support
+    // variable stack parameter counts.
+    ASSERT(!stack_parameter_count_.is_valid());
   }
 
   ExternalReference miss_handler() {
@@ -313,18 +316,27 @@ struct CodeStubInterfaceDescriptor {
     return has_miss_handler_;
   }
 
+  Register GetParameterRegister(int index) {
+    return register_params_[index];
+  }
+
+  bool IsParameterCountRegister(int index) {
+    return GetParameterRegister(index).is(stack_parameter_count_);
+  }
+
+  int GetHandlerParameterCount() {
+    int params = environment_length();
+    if (handler_arguments_mode_ == PASS_ARGUMENTS) {
+      params += 1;
+    }
+    return params;
+  }
+
  private:
   ExternalReference miss_handler_;
   bool has_miss_handler_;
 };
 
-// A helper to make up for the fact that type Register is not fully
-// defined outside of the platform directories
-#define DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index) \
-  ((index) == (descriptor)->register_param_count_)           \
-      ? (descriptor)->stack_parameter_count_                 \
-      : (descriptor)->register_params_[(index)]
-
 
 class HydrogenCodeStub : public CodeStub {
  public:
index 4f2cd03..ef4e39e 100644 (file)
@@ -1586,15 +1586,34 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
   }
 
   // Copy the register parameters to the failure frame.
+  int arguments_length_offset = -1;
   for (int i = 0; i < descriptor->register_param_count_; ++i) {
     output_frame_offset -= kPointerSize;
     DoTranslateCommand(iterator, 0, output_frame_offset);
+
+    if (!arg_count_known && descriptor->IsParameterCountRegister(i)) {
+      arguments_length_offset = output_frame_offset;
+    }
   }
 
+  ASSERT(0 == output_frame_offset);
+
   if (!arg_count_known) {
-    DoTranslateCommand(iterator, 0, length_frame_offset,
-                       TRANSLATED_VALUE_IS_NATIVE);
-    caller_arg_count = output_frame->GetFrameSlot(length_frame_offset);
+    ASSERT(arguments_length_offset >= 0);
+    // We know it's a smi because 1) the code stub guarantees the stack
+    // parameter count is in smi range, and 2) the DoTranslateCommand in the
+    // parameter loop above translated that to a tagged value.
+    Smi* smi_caller_arg_count = reinterpret_cast<Smi*>(
+        output_frame->GetFrameSlot(arguments_length_offset));
+    caller_arg_count = smi_caller_arg_count->value();
+    output_frame->SetFrameSlot(length_frame_offset, caller_arg_count);
+    if (trace_scope_ != NULL) {
+      PrintF(trace_scope_->file(),
+             "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
+             V8PRIxPTR " ; args.length\n",
+             top_address + length_frame_offset, length_frame_offset,
+             caller_arg_count);
+    }
     value = frame_ptr + StandardFrameConstants::kCallerSPOffset +
         (caller_arg_count - 1) * kPointerSize;
     output_frame->SetFrameSlot(args_arguments_offset, value);
@@ -1602,12 +1621,11 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
       PrintF(trace_scope_->file(),
              "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
              V8PRIxPTR " ; args.arguments\n",
-             top_address + args_arguments_offset, args_arguments_offset, value);
+             top_address + args_arguments_offset, args_arguments_offset,
+             value);
     }
   }
 
-  ASSERT(0 == output_frame_offset);
-
   // Copy the double registers from the input into the output frame.
   CopyDoubleRegisters(output_frame);
 
@@ -1874,10 +1892,8 @@ void Deoptimizer::MaterializeHeapNumbersForDebuggerInspectableFrame(
 #endif
 
 
-static const char* TraceValueType(bool is_smi, bool is_native = false) {
-  if (is_native) {
-    return "native";
-  } else if (is_smi) {
+static const char* TraceValueType(bool is_smi) {
+  if (is_smi) {
     return "smi";
   }
 
@@ -2146,13 +2162,11 @@ void Deoptimizer::DoTranslateObject(TranslationIterator* iterator,
 
 
 void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
-    int frame_index,
-    unsigned output_offset,
-    DeoptimizerTranslatedValueType value_type) {
+                                     int frame_index,
+                                     unsigned output_offset) {
   disasm::NameConverter converter;
   // A GC-safe temporary placeholder that we can put in the output frame.
   const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0));
-  bool is_native = value_type == TRANSLATED_VALUE_IS_NATIVE;
 
   Translation::Opcode opcode =
       static_cast<Translation::Opcode>(iterator->Next());
@@ -2190,8 +2204,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
     case Translation::INT32_REGISTER: {
       int input_reg = iterator->Next();
       intptr_t value = input_->GetRegister(input_reg);
-      bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
-          Smi::IsValid(value);
+      bool is_smi = Smi::IsValid(value);
       if (trace_scope_ != NULL) {
         PrintF(
             trace_scope_->file(),
@@ -2200,18 +2213,15 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
             output_offset,
             value,
             converter.NameOfCPURegister(input_reg),
-            TraceValueType(is_smi, is_native));
+            TraceValueType(is_smi));
       }
       if (is_smi) {
         intptr_t tagged_value =
             reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
-      } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
-        output_[frame_index]->SetFrameSlot(output_offset, value);
       } else {
         // We save the untagged value on the side and store a GC-safe
         // temporary placeholder in the frame.
-        ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
         AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
                        static_cast<double>(static_cast<int32_t>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -2222,8 +2232,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
     case Translation::UINT32_REGISTER: {
       int input_reg = iterator->Next();
       uintptr_t value = static_cast<uintptr_t>(input_->GetRegister(input_reg));
-      bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
-          (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+      bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
       if (trace_scope_ != NULL) {
         PrintF(
             trace_scope_->file(),
@@ -2233,18 +2242,15 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
             output_offset,
             value,
             converter.NameOfCPURegister(input_reg),
-            TraceValueType(is_smi, is_native));
+            TraceValueType(is_smi));
       }
       if (is_smi) {
         intptr_t tagged_value =
             reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
-      } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
-        output_[frame_index]->SetFrameSlot(output_offset, value);
       } else {
         // We save the untagged value on the side and store a GC-safe
         // temporary placeholder in the frame.
-        ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
         AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
                        static_cast<double>(static_cast<uint32_t>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -2295,8 +2301,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
       int input_slot_index = iterator->Next();
       unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
       intptr_t value = input_->GetFrameSlot(input_offset);
-      bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
-          Smi::IsValid(value);
+      bool is_smi = Smi::IsValid(value);
       if (trace_scope_ != NULL) {
         PrintF(trace_scope_->file(),
                "    0x%08" V8PRIxPTR ": ",
@@ -2306,18 +2311,15 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
                output_offset,
                value,
                input_offset,
-               TraceValueType(is_smi, is_native));
+               TraceValueType(is_smi));
       }
       if (is_smi) {
         intptr_t tagged_value =
             reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
-      } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
-        output_[frame_index]->SetFrameSlot(output_offset, value);
       } else {
         // We save the untagged value on the side and store a GC-safe
         // temporary placeholder in the frame.
-        ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
         AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
                        static_cast<double>(static_cast<int32_t>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
@@ -2330,8 +2332,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
       unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
       uintptr_t value =
           static_cast<uintptr_t>(input_->GetFrameSlot(input_offset));
-      bool is_smi = (value_type == TRANSLATED_VALUE_IS_TAGGED) &&
-          (value <= static_cast<uintptr_t>(Smi::kMaxValue));
+      bool is_smi = value <= static_cast<uintptr_t>(Smi::kMaxValue);
       if (trace_scope_ != NULL) {
         PrintF(trace_scope_->file(),
                "    0x%08" V8PRIxPTR ": ",
@@ -2341,18 +2342,15 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
                output_offset,
                value,
                input_offset,
-               TraceValueType(is_smi, is_native));
+               TraceValueType(is_smi));
       }
       if (is_smi) {
         intptr_t tagged_value =
             reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
-      } else if (value_type == TRANSLATED_VALUE_IS_NATIVE) {
-        output_[frame_index]->SetFrameSlot(output_offset, value);
       } else {
         // We save the untagged value on the side and store a GC-safe
         // temporary placeholder in the frame.
-        ASSERT(value_type == TRANSLATED_VALUE_IS_TAGGED);
         AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
                        static_cast<double>(static_cast<uint32_t>(value)));
         output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
index f5530a8..52e4e24 100644 (file)
@@ -333,15 +333,9 @@ class Deoptimizer : public Malloced {
                          int object_index,
                          int field_index);
 
-  enum DeoptimizerTranslatedValueType {
-    TRANSLATED_VALUE_IS_NATIVE,
-    TRANSLATED_VALUE_IS_TAGGED
-  };
-
   void DoTranslateCommand(TranslationIterator* iterator,
-      int frame_index,
-      unsigned output_offset,
-      DeoptimizerTranslatedValueType value_type = TRANSLATED_VALUE_IS_TAGGED);
+                          int frame_index,
+                          unsigned output_offset);
 
   unsigned ComputeInputFrameSize() const;
   unsigned ComputeFixedSize(JSFunction* function) const;
index 264e300..adc2d50 100644 (file)
@@ -168,15 +168,21 @@ static void InitializeArrayConstructorDescriptor(
   // eax -- number of arguments
   // edi -- function
   // ebx -- type info cell with elements kind
-  static Register registers[] = { edi, ebx };
-  descriptor->register_param_count_ = 2;
+  static Register registers_variable_args[] = { edi, ebx, eax };
+  static Register registers_no_args[] = { edi, ebx };
 
-  if (constant_stack_parameter_count != 0) {
+  if (constant_stack_parameter_count == 0) {
+    descriptor->register_param_count_ = 2;
+    descriptor->register_params_ = registers_no_args;
+  } else {
     // stack param count needs (constructor pointer, and single argument)
+    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
     descriptor->stack_parameter_count_ = eax;
+    descriptor->register_param_count_ = 3;
+    descriptor->register_params_ = registers_variable_args;
   }
+
   descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
-  descriptor->register_params_ = registers;
   descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
@@ -190,15 +196,21 @@ static void InitializeInternalArrayConstructorDescriptor(
   // register state
   // eax -- number of arguments
   // edi -- constructor function
-  static Register registers[] = { edi };
-  descriptor->register_param_count_ = 1;
+  static Register registers_variable_args[] = { edi, eax };
+  static Register registers_no_args[] = { edi };
 
-  if (constant_stack_parameter_count != 0) {
+  if (constant_stack_parameter_count == 0) {
+    descriptor->register_param_count_ = 1;
+    descriptor->register_params_ = registers_no_args;
+  } else {
     // stack param count needs (constructor pointer, and single argument)
+    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
     descriptor->stack_parameter_count_ = eax;
+    descriptor->register_param_count_ = 2;
+    descriptor->register_params_ = registers_variable_args;
   }
+
   descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
-  descriptor->register_params_ = registers;
   descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
index e339b3a..e043aa4 100644 (file)
@@ -202,7 +202,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
     FrameDescription* output_frame, CodeStubInterfaceDescriptor* descriptor) {
   intptr_t handler =
       reinterpret_cast<intptr_t>(descriptor->deoptimization_handler_);
-  int params = descriptor->environment_length();
+  int params = descriptor->GetHandlerParameterCount();
   output_frame->SetRegister(eax.code(), params);
   output_frame->SetRegister(ebx.code(), handler);
 }
index b7818c8..29b42fe 100644 (file)
@@ -2569,7 +2569,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
     CodeStubInterfaceDescriptor* descriptor =
         info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
     int index = static_cast<int>(instr->index());
-    Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index);
+    Register reg = descriptor->GetParameterRegister(index);
     return DefineFixed(result, reg);
   }
 }
index 348e1df..cd2c123 100644 (file)
@@ -14734,18 +14734,25 @@ static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
   HandleScope scope(isolate);
   // If we get 2 arguments then they are the stub parameters (constructor, type
-  // info).  If we get 3, then the first one is a pointer to the arguments
-  // passed by the caller.
+  // info).  If we get 4, then the first one is a pointer to the arguments
+  // passed by the caller, and the last one is the length of the arguments
+  // passed to the caller (redundant, but useful to check on the deoptimizer
+  // with an assert).
   Arguments empty_args(0, NULL);
   bool no_caller_args = args.length() == 2;
-  ASSERT(no_caller_args || args.length() == 3);
+  ASSERT(no_caller_args || args.length() == 4);
   int parameters_start = no_caller_args ? 0 : 1;
   Arguments* caller_args = no_caller_args
       ? &empty_args
       : reinterpret_cast<Arguments*>(args[0]);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
   CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
-
+#ifdef DEBUG
+  if (!no_caller_args) {
+    CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 2);
+    ASSERT(arg_count == caller_args->length());
+  }
+#endif
   return ArrayConstructorCommon(isolate,
                                 constructor,
                                 type_info,
@@ -14757,13 +14764,18 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
   HandleScope scope(isolate);
   Arguments empty_args(0, NULL);
   bool no_caller_args = args.length() == 1;
-  ASSERT(no_caller_args || args.length() == 2);
+  ASSERT(no_caller_args || args.length() == 3);
   int parameters_start = no_caller_args ? 0 : 1;
   Arguments* caller_args = no_caller_args
       ? &empty_args
       : reinterpret_cast<Arguments*>(args[0]);
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
-
+#ifdef DEBUG
+  if (!no_caller_args) {
+    CONVERT_SMI_ARG_CHECKED(arg_count, parameters_start + 1);
+    ASSERT(arg_count == caller_args->length());
+  }
+#endif
   return ArrayConstructorCommon(isolate,
                                 constructor,
                                 Handle<Object>::null(),
index 0912661..9d95fc4 100644 (file)
@@ -176,14 +176,21 @@ static void InitializeArrayConstructorDescriptor(
   // rax -- number of arguments
   // rdi -- function
   // rbx -- type info cell with elements kind
-  static Register registers[] = { rdi, rbx };
-  descriptor->register_param_count_ = 2;
-  if (constant_stack_parameter_count != 0) {
+  static Register registers_variable_args[] = { rdi, rbx, rax };
+  static Register registers_no_args[] = { rdi, rbx };
+
+  if (constant_stack_parameter_count == 0) {
+    descriptor->register_param_count_ = 2;
+    descriptor->register_params_ = registers_no_args;
+  } else {
     // stack param count needs (constructor pointer, and single argument)
+    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
     descriptor->stack_parameter_count_ = rax;
+    descriptor->register_param_count_ = 3;
+    descriptor->register_params_ = registers_variable_args;
   }
+
   descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
-  descriptor->register_params_ = registers;
   descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kArrayConstructor)->entry;
@@ -197,15 +204,21 @@ static void InitializeInternalArrayConstructorDescriptor(
   // register state
   // rax -- number of arguments
   // rdi -- constructor function
-  static Register registers[] = { rdi };
-  descriptor->register_param_count_ = 1;
+  static Register registers_variable_args[] = { rdi, rax };
+  static Register registers_no_args[] = { rdi };
 
-  if (constant_stack_parameter_count != 0) {
+  if (constant_stack_parameter_count == 0) {
+    descriptor->register_param_count_ = 1;
+    descriptor->register_params_ = registers_no_args;
+  } else {
     // stack param count needs (constructor pointer, and single argument)
+    descriptor->handler_arguments_mode_ = PASS_ARGUMENTS;
     descriptor->stack_parameter_count_ = rax;
+    descriptor->register_param_count_ = 2;
+    descriptor->register_params_ = registers_variable_args;
   }
+
   descriptor->hint_stack_parameter_count_ = constant_stack_parameter_count;
-  descriptor->register_params_ = registers;
   descriptor->function_mode_ = JS_FUNCTION_STUB_MODE;
   descriptor->deoptimization_handler_ =
       Runtime::FunctionForId(Runtime::kInternalArrayConstructor)->entry;
index bf11e08..4528077 100644 (file)
@@ -106,7 +106,7 @@ void Deoptimizer::SetPlatformCompiledStubRegisters(
     FrameDescription* output_frame, CodeStubInterfaceDescriptor* descriptor) {
   intptr_t handler =
       reinterpret_cast<intptr_t>(descriptor->deoptimization_handler_);
-  int params = descriptor->environment_length();
+  int params = descriptor->GetHandlerParameterCount();
   output_frame->SetRegister(rax.code(), params);
   output_frame->SetRegister(rbx.code(), handler);
 }
index 530f153..a121646 100644 (file)
@@ -2422,7 +2422,7 @@ LInstruction* LChunkBuilder::DoParameter(HParameter* instr) {
     CodeStubInterfaceDescriptor* descriptor =
         info()->code_stub()->GetInterfaceDescriptor(info()->isolate());
     int index = static_cast<int>(instr->index());
-    Register reg = DESCRIPTOR_GET_PARAMETER_REGISTER(descriptor, index);
+    Register reg = descriptor->GetParameterRegister(index);
     return DefineFixed(result, reg);
   }
 }