Cleanup Generate_JSConstructStubHelper a bit.
authormstarzinger <mstarzinger@chromium.org>
Mon, 13 Jul 2015 15:13:00 +0000 (08:13 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 13 Jul 2015 15:13:11 +0000 (15:13 +0000)
R=bmeurer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#29617}

src/arm/builtins-arm.cc
src/arm64/builtins-arm64.cc
src/ia32/builtins-ia32.cc
src/mips/builtins-mips.cc
src/mips64/builtins-mips64.cc
src/x64/builtins-x64.cc

index 7708e5a..d08216c 100644 (file)
@@ -311,36 +311,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
 }
 
 
-static void Generate_Runtime_NewObject(MacroAssembler* masm,
-                                       bool create_memento,
-                                       Register original_constructor,
-                                       Label* count_incremented,
-                                       Label* allocated) {
-  if (create_memento) {
-    // Get the cell or allocation site.
-    __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
-    __ push(r2);
-  }
-
-  __ push(r1);                    // argument for Runtime_NewObject
-  __ push(original_constructor);  // original constructor
-  if (create_memento) {
-    __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
-  } else {
-    __ CallRuntime(Runtime::kNewObject, 2);
-  }
-  __ mov(r4, r0);
-
-  // Runtime_NewObjectWithAllocationSite increments allocation count.
-  // Skip the increment.
-  if (create_memento) {
-    __ jmp(count_incremented);
-  } else {
-    __ jmp(allocated);
-  }
-}
-
-
 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                                            bool is_api_function,
                                            bool create_memento) {
@@ -373,17 +343,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     __ push(r1);
     __ push(r3);
 
-    Label rt_call, allocated, normal_new, count_incremented;
-    __ cmp(r1, r3);
-    __ b(eq, &normal_new);
-
-    // Original constructor and function are different.
-    Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented,
-                               &allocated);
-    __ bind(&normal_new);
-
     // Try to allocate the object without transitioning into C code. If any of
     // the preconditions is not met, the code bails out to the runtime call.
+    Label rt_call, allocated;
     if (FLAG_inline_new) {
       ExternalReference debug_step_in_fp =
           ExternalReference::debug_step_in_fp_address(isolate);
@@ -392,11 +354,15 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       __ tst(r2, r2);
       __ b(ne, &rt_call);
 
+      // Fall back to runtime if the original constructor and function differ.
+      __ cmp(r1, r3);
+      __ b(ne, &rt_call);
+
       // Load the initial map and verify that it is in fact a map.
       // r1: constructor function
       __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
       __ JumpIfSmi(r2, &rt_call);
-      __ CompareObjectType(r2, r3, r4, MAP_TYPE);
+      __ CompareObjectType(r2, r5, r4, MAP_TYPE);
       __ b(ne, &rt_call);
 
       // Check that the constructor is not constructing a JSFunction (see
@@ -404,7 +370,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // initial map's instance type would be JS_FUNCTION_TYPE.
       // r1: constructor function
       // r2: initial map
-      __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
+      __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE);
       __ b(eq, &rt_call);
 
       if (!is_api_function) {
@@ -435,12 +401,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // Now allocate the JSObject on the heap.
       // r1: constructor function
       // r2: initial map
+      Label rt_call_reload_new_target;
       __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
       if (create_memento) {
         __ add(r3, r3, Operand(AllocationMemento::kSize / kPointerSize));
       }
 
-      __ Allocate(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS);
+      __ Allocate(r3, r4, r5, r6, &rt_call_reload_new_target, SIZE_IN_WORDS);
 
       // Allocated the JSObject, now initialize the fields. Map is set to
       // initial map and properties and elements are set to empty fixed array.
@@ -524,13 +491,37 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // Continue with JSObject being successfully allocated
       // r4: JSObject
       __ jmp(&allocated);
+
+      // Reload the original constructor and fall-through.
+      __ bind(&rt_call_reload_new_target);
+      __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
     }
 
     // Allocate the new receiver object using the runtime call.
     // r1: constructor function
+    // r3: original constructor
     __ bind(&rt_call);
-    Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented,
-                               &allocated);
+    if (create_memento) {
+      // Get the cell or allocation site.
+      __ ldr(r2, MemOperand(sp, 3 * kPointerSize));
+      __ push(r2);  // argument 1: allocation site
+    }
+
+    __ push(r1);  // argument 2/1: constructor function
+    __ push(r3);  // argument 3/2: original constructor
+    if (create_memento) {
+      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
+    } else {
+      __ CallRuntime(Runtime::kNewObject, 2);
+    }
+    __ mov(r4, r0);
+
+    // Runtime_NewObjectWithAllocationSite increments allocation count.
+    // Skip the increment.
+    Label count_incremented;
+    if (create_memento) {
+      __ jmp(&count_incremented);
+    }
 
     // Receiver for constructor call allocated.
     // r4: JSObject
@@ -619,9 +610,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
 
     // If the result is a smi, it is *not* an object in the ECMA sense.
     // r0: result
-    // sp[0]: receiver (newly allocated object)
-    // sp[1]: new.target (if used)
-    // sp[1/2]: number of arguments (smi-tagged)
+    // sp[0]: receiver
+    // sp[1]: new.target
+    // sp[2]: number of arguments (smi-tagged)
     __ JumpIfSmi(r0, &use_receiver);
 
     // If the type of the result (stored in its map) is less than
index e3aeca6..174d2a8 100644 (file)
@@ -302,33 +302,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
 }
 
 
-static void Generate_Runtime_NewObject(MacroAssembler* masm,
-                                       bool create_memento,
-                                       Register original_constructor,
-                                       Label* count_incremented,
-                                       Label* allocated) {
-  if (create_memento) {
-    // Get the cell or allocation site.
-    __ Peek(x4, 3 * kXRegSize);
-    __ Push(x4);
-    __ Push(x1);  // Argument for Runtime_NewObject.
-    __ Push(original_constructor);
-    __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
-    __ Mov(x4, x0);
-    // If we ended up using the runtime, and we want a memento, then the
-    // runtime call made it for us, and we shouldn't do create count
-    // increment.
-    __ jmp(count_incremented);
-  } else {
-    __ Push(x1);  // Argument for Runtime_NewObject.
-    __ Push(original_constructor);
-    __ CallRuntime(Runtime::kNewObject, 2);
-    __ Mov(x4, x0);
-    __ jmp(allocated);
-  }
-}
-
-
 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                                            bool is_api_function,
                                            bool create_memento) {
@@ -368,22 +341,20 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     // sp[1]: Constructor function.
     // sp[2]: number of arguments (smi-tagged)
 
-    Label rt_call, count_incremented, allocated, normal_new;
-    __ Cmp(constructor, original_constructor);
-    __ B(eq, &normal_new);
-    Generate_Runtime_NewObject(masm, create_memento, original_constructor,
-                               &count_incremented, &allocated);
-
-    __ Bind(&normal_new);
-
     // Try to allocate the object without transitioning into C code. If any of
     // the preconditions is not met, the code bails out to the runtime call.
+    Label rt_call, allocated;
     if (FLAG_inline_new) {
       ExternalReference debug_step_in_fp =
           ExternalReference::debug_step_in_fp_address(isolate);
       __ Mov(x2, Operand(debug_step_in_fp));
       __ Ldr(x2, MemOperand(x2));
       __ Cbnz(x2, &rt_call);
+
+      // Fall back to runtime if the original constructor and function differ.
+      __ Cmp(constructor, original_constructor);
+      __ B(ne, &rt_call);
+
       // Load the initial map and verify that it is in fact a map.
       Register init_map = x2;
       __ Ldr(init_map,
@@ -424,15 +395,18 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       }
 
       // Now allocate the JSObject on the heap.
+      Label rt_call_reload_new_target;
       Register obj_size = x3;
       Register new_obj = x4;
       __ Ldrb(obj_size, FieldMemOperand(init_map, Map::kInstanceSizeOffset));
       if (create_memento) {
         __ Add(x7, obj_size,
                Operand(AllocationMemento::kSize / kPointerSize));
-        __ Allocate(x7, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS);
+        __ Allocate(x7, new_obj, x10, x11, &rt_call_reload_new_target,
+                    SIZE_IN_WORDS);
       } else {
-        __ Allocate(obj_size, new_obj, x10, x11, &rt_call, SIZE_IN_WORDS);
+        __ Allocate(obj_size, new_obj, x10, x11, &rt_call_reload_new_target,
+                    SIZE_IN_WORDS);
       }
 
       // Allocated the JSObject, now initialize the fields. Map is set to
@@ -526,12 +500,32 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
 
       // Continue with JSObject being successfully allocated.
       __ B(&allocated);
+
+      // Reload the original constructor and fall-through.
+      __ Bind(&rt_call_reload_new_target);
+      __ Peek(x3, 0 * kXRegSize);
     }
 
     // Allocate the new receiver object using the runtime call.
+    // x1: constructor function
+    // x3: original constructor
     __ Bind(&rt_call);
-    Generate_Runtime_NewObject(masm, create_memento, constructor,
-                               &count_incremented, &allocated);
+    Label count_incremented;
+    if (create_memento) {
+      // Get the cell or allocation site.
+      __ Peek(x4, 3 * kXRegSize);
+      __ Push(x4, constructor, original_constructor);  // arguments 1-3
+      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
+      __ Mov(x4, x0);
+      // If we ended up using the runtime, and we want a memento, then the
+      // runtime call made it for us, and we shouldn't do create count
+      // increment.
+      __ B(&count_incremented);
+    } else {
+      __ Push(constructor, original_constructor);  // arguments 1-2
+      __ CallRuntime(Runtime::kNewObject, 2);
+      __ Mov(x4, x0);
+    }
 
     // Receiver for constructor call allocated.
     // x4: JSObject
index a8f26ef..5cbecc2 100644 (file)
@@ -100,42 +100,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
 }
 
 
-static void Generate_Runtime_NewObject(MacroAssembler* masm,
-                                       bool create_memento,
-                                       Register original_constructor,
-                                       Label* count_incremented,
-                                       Label* allocated) {
-  int offset = kPointerSize;
-  if (create_memento) {
-    // Get the cell or allocation site.
-    __ mov(edi, Operand(esp, kPointerSize * 3));
-    __ push(edi);
-    offset += kPointerSize;
-  }
-
-  // Must restore esi (context) and edi (constructor) before calling
-  // runtime.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ mov(edi, Operand(esp, offset));
-  __ push(edi);
-  __ push(original_constructor);
-  if (create_memento) {
-    __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
-  } else {
-    __ CallRuntime(Runtime::kNewObject, 2);
-  }
-  __ mov(ebx, eax);  // store result in ebx
-
-  // Runtime_NewObjectWithAllocationSite increments allocation count.
-  // Skip the increment.
-  if (create_memento) {
-    __ jmp(count_incremented);
-  } else {
-    __ jmp(allocated);
-  }
-}
-
-
 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                                            bool is_api_function,
                                            bool create_memento) {
@@ -164,26 +128,19 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     __ push(edi);
     __ push(edx);
 
-    __ cmp(edx, edi);
-    Label normal_new;
-    Label count_incremented;
-    Label allocated;
-    __ j(equal, &normal_new);
-
-    // Original constructor and function are different.
-    Generate_Runtime_NewObject(masm, create_memento, edx, &count_incremented,
-                               &allocated);
-    __ bind(&normal_new);
-
     // Try to allocate the object without transitioning into C code. If any of
     // the preconditions is not met, the code bails out to the runtime call.
-    Label rt_call;
+    Label rt_call, allocated;
     if (FLAG_inline_new) {
       ExternalReference debug_step_in_fp =
           ExternalReference::debug_step_in_fp_address(masm->isolate());
       __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
       __ j(not_equal, &rt_call);
 
+      // Fall back to runtime if the original constructor and function differ.
+      __ cmp(edx, edi);
+      __ j(not_equal, &rt_call);
+
       // Verified that the constructor is a JSFunction.
       // Load the initial map and verify that it is in fact a map.
       // edi: constructor
@@ -220,12 +177,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         __ j(not_equal, &allocate);
 
         __ push(eax);
+        __ push(edx);
         __ push(edi);
 
         __ push(edi);  // constructor
         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
 
         __ pop(edi);
+        __ pop(edx);
         __ pop(eax);
         __ mov(esi, Map::kSlackTrackingCounterEnd - 1);
 
@@ -313,9 +272,36 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     }
 
     // Allocate the new receiver object using the runtime call.
+    // edx: original constructor
     __ bind(&rt_call);
-    Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented,
-                               &allocated);
+    int offset = kPointerSize;
+    if (create_memento) {
+      // Get the cell or allocation site.
+      __ mov(edi, Operand(esp, kPointerSize * 3));
+      __ push(edi);  // argument 1: allocation site
+      offset += kPointerSize;
+    }
+
+    // Must restore esi (context) and edi (constructor) before calling
+    // runtime.
+    __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+    __ mov(edi, Operand(esp, offset));
+    __ push(edi);  // argument 2/1: constructor function
+    __ push(edx);  // argument 3/2: original constructor
+    if (create_memento) {
+      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
+    } else {
+      __ CallRuntime(Runtime::kNewObject, 2);
+    }
+    __ mov(ebx, eax);  // store result in ebx
+
+    // Runtime_NewObjectWithAllocationSite increments allocation count.
+    // Skip the increment.
+    Label count_incremented;
+    if (create_memento) {
+      __ jmp(&count_incremented);
+    }
+
     // New object allocated.
     // ebx: newly allocated object
     __ bind(&allocated);
index 7a22004..0af1ce0 100644 (file)
@@ -316,36 +316,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
 }
 
 
-static void Generate_Runtime_NewObject(MacroAssembler* masm,
-                                       bool create_memento,
-                                       Register original_constructor,
-                                       Label* count_incremented,
-                                       Label* allocated) {
-  if (create_memento) {
-    // Get the cell or allocation site.
-    __ lw(a2, MemOperand(sp, 3 * kPointerSize));
-    __ push(a2);
-  }
-
-  __ push(a1);                    // argument for Runtime_NewObject
-  __ push(original_constructor);  // original constructor
-  if (create_memento) {
-    __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
-  } else {
-    __ CallRuntime(Runtime::kNewObject, 2);
-  }
-  __ mov(t4, v0);
-
-  // Runtime_NewObjectWithAllocationSite increments allocation count.
-  // Skip the increment.
-  if (create_memento) {
-    __ jmp(count_incremented);
-  } else {
-    __ jmp(allocated);
-  }
-}
-
-
 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                                            bool is_api_function,
                                            bool create_memento) {
@@ -363,13 +333,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
 
   Isolate* isolate = masm->isolate();
 
-  // ----------- S t a t e -------------
-  //  -- a0     : number of arguments
-  //  -- a1     : constructor function
-  //  -- ra     : return address
-  //  -- sp[...]: constructor arguments
-  // -----------------------------------
-
   // Enter a construct frame.
   {
     FrameScope scope(masm, StackFrame::CONSTRUCT);
@@ -383,16 +346,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     __ SmiTag(a0);
     __ Push(a0, a1, a3);
 
-    Label rt_call, allocated, normal_new, count_incremented;
-    __ Branch(&normal_new, eq, a1, Operand(a3));
-
-    // Original constructor and function are different.
-    Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented,
-                               &allocated);
-    __ bind(&normal_new);
-
     // Try to allocate the object without transitioning into C code. If any of
     // the preconditions is not met, the code bails out to the runtime call.
+    Label rt_call, allocated;
     if (FLAG_inline_new) {
       ExternalReference debug_step_in_fp =
           ExternalReference::debug_step_in_fp_address(isolate);
@@ -400,11 +356,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       __ lw(a2, MemOperand(a2));
       __ Branch(&rt_call, ne, a2, Operand(zero_reg));
 
+      // Fall back to runtime if the original constructor and function differ.
+      __ Branch(&rt_call, ne, a1, Operand(a3));
+
       // Load the initial map and verify that it is in fact a map.
       // a1: constructor function
       __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
       __ JumpIfSmi(a2, &rt_call);
-      __ GetObjectType(a2, a3, t4);
+      __ GetObjectType(a2, t5, t4);
       __ Branch(&rt_call, ne, t4, Operand(MAP_TYPE));
 
       // Check that the constructor is not constructing a JSFunction (see
@@ -412,8 +371,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // initial map's instance type would be JS_FUNCTION_TYPE.
       // a1: constructor function
       // a2: initial map
-      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
-      __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
+      __ lbu(t5, FieldMemOperand(a2, Map::kInstanceTypeOffset));
+      __ Branch(&rt_call, eq, t5, Operand(JS_FUNCTION_TYPE));
 
       if (!is_api_function) {
         Label allocate;
@@ -440,12 +399,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // Now allocate the JSObject on the heap.
       // a1: constructor function
       // a2: initial map
+      Label rt_call_reload_new_target;
       __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
       if (create_memento) {
         __ Addu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize));
       }
 
-      __ Allocate(a3, t4, t5, t6, &rt_call, SIZE_IN_WORDS);
+      __ Allocate(a3, t4, t5, t6, &rt_call_reload_new_target, SIZE_IN_WORDS);
 
       // Allocated the JSObject, now initialize the fields. Map is set to
       // initial map and properties and elements are set to empty fixed array.
@@ -533,13 +493,36 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // Continue with JSObject being successfully allocated.
       // t4: JSObject
       __ jmp(&allocated);
+
+      // Reload the original constructor and fall-through.
+      __ bind(&rt_call_reload_new_target);
+      __ lw(a3, MemOperand(sp, 0 * kPointerSize));
     }
 
     // Allocate the new receiver object using the runtime call.
     // a1: constructor function
+    // a3: original constructor
     __ bind(&rt_call);
-    Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented,
-                               &allocated);
+    if (create_memento) {
+      // Get the cell or allocation site.
+      __ lw(a2, MemOperand(sp, 3 * kPointerSize));
+      __ push(a2);  // argument 1: allocation site
+    }
+
+    __ Push(a1, a3);  // arguments 2-3 / 1-2
+    if (create_memento) {
+      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
+    } else {
+      __ CallRuntime(Runtime::kNewObject, 2);
+    }
+    __ mov(t4, v0);
+
+    // Runtime_NewObjectWithAllocationSite increments allocation count.
+    // Skip the increment.
+    Label count_incremented;
+    if (create_memento) {
+      __ jmp(&count_incremented);
+    }
 
     // Receiver for constructor call allocated.
     // t4: JSObject
index 0300dc8..efecc29 100644 (file)
@@ -315,36 +315,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
 }
 
 
-static void Generate_Runtime_NewObject(MacroAssembler* masm,
-                                       bool create_memento,
-                                       Register original_constructor,
-                                       Label* count_incremented,
-                                       Label* allocated) {
-  if (create_memento) {
-    // Get the cell or allocation site.
-    __ ld(a2, MemOperand(sp, 3 * kPointerSize));
-    __ push(a2);
-  }
-
-  __ push(a1);                    // argument for Runtime_NewObject
-  __ push(original_constructor);  // original constructor
-  if (create_memento) {
-    __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
-  } else {
-    __ CallRuntime(Runtime::kNewObject, 2);
-  }
-  __ mov(t0, v0);
-
-  // Runtime_NewObjectWithAllocationSite increments allocation count.
-  // Skip the increment.
-  if (create_memento) {
-    __ jmp(count_incremented);
-  } else {
-    __ jmp(allocated);
-  }
-}
-
-
 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                                            bool is_api_function,
                                            bool create_memento) {
@@ -362,13 +332,6 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
 
   Isolate* isolate = masm->isolate();
 
-  // ----------- S t a t e -------------
-  //  -- a0     : number of arguments
-  //  -- a1     : constructor function
-  //  -- ra     : return address
-  //  -- sp[...]: constructor arguments
-  // -----------------------------------
-
   // Enter a construct frame.
   {
     FrameScope scope(masm, StackFrame::CONSTRUCT);
@@ -382,16 +345,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     __ SmiTag(a0);
     __ Push(a0, a1, a3);
 
-    Label rt_call, allocated, normal_new, count_incremented;
-    __ Branch(&normal_new, eq, a1, Operand(a3));
-
-    // Original constructor and function are different.
-    Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented,
-                               &allocated);
-    __ bind(&normal_new);
-
     // Try to allocate the object without transitioning into C code. If any of
     // the preconditions is not met, the code bails out to the runtime call.
+    Label rt_call, allocated;
     if (FLAG_inline_new) {
       ExternalReference debug_step_in_fp =
           ExternalReference::debug_step_in_fp_address(isolate);
@@ -399,11 +355,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       __ ld(a2, MemOperand(a2));
       __ Branch(&rt_call, ne, a2, Operand(zero_reg));
 
+      // Fall back to runtime if the original constructor and function differ.
+      __ Branch(&rt_call, ne, a1, Operand(a3));
+
       // Load the initial map and verify that it is in fact a map.
       // a1: constructor function
       __ ld(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
       __ JumpIfSmi(a2, &rt_call);
-      __ GetObjectType(a2, a3, t0);
+      __ GetObjectType(a2, t1, t0);
       __ Branch(&rt_call, ne, t0, Operand(MAP_TYPE));
 
       // Check that the constructor is not constructing a JSFunction (see
@@ -411,8 +370,8 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // initial map's instance type would be JS_FUNCTION_TYPE.
       // a1: constructor function
       // a2: initial map
-      __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset));
-      __ Branch(&rt_call, eq, a3, Operand(JS_FUNCTION_TYPE));
+      __ lbu(t1, FieldMemOperand(a2, Map::kInstanceTypeOffset));
+      __ Branch(&rt_call, eq, t1, Operand(JS_FUNCTION_TYPE));
 
       if (!is_api_function) {
         Label allocate;
@@ -440,12 +399,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // Now allocate the JSObject on the heap.
       // a1: constructor function
       // a2: initial map
+      Label rt_call_reload_new_target;
       __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset));
       if (create_memento) {
         __ Daddu(a3, a3, Operand(AllocationMemento::kSize / kPointerSize));
       }
 
-      __ Allocate(a3, t0, t1, t2, &rt_call, SIZE_IN_WORDS);
+      __ Allocate(a3, t0, t1, t2, &rt_call_reload_new_target, SIZE_IN_WORDS);
 
       // Allocated the JSObject, now initialize the fields. Map is set to
       // initial map and properties and elements are set to empty fixed array.
@@ -533,14 +493,36 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       // Continue with JSObject being successfully allocated.
       // a4: JSObject
       __ jmp(&allocated);
+
+      // Reload the original constructor and fall-through.
+      __ bind(&rt_call_reload_new_target);
+      __ ld(a3, MemOperand(sp, 0 * kPointerSize));
     }
 
     // Allocate the new receiver object using the runtime call.
     // a1: constructor function
+    // a3: original constructor
     __ bind(&rt_call);
-    Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented,
-                               &allocated);
+    if (create_memento) {
+      // Get the cell or allocation site.
+      __ ld(a2, MemOperand(sp, 3 * kPointerSize));
+      __ push(a2);  // argument 1: allocation site
+    }
 
+    __ Push(a1, a3);  // arguments 2-3 / 1-2
+    if (create_memento) {
+      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
+    } else {
+      __ CallRuntime(Runtime::kNewObject, 2);
+    }
+    __ mov(t0, v0);
+
+    // Runtime_NewObjectWithAllocationSite increments allocation count.
+    // Skip the increment.
+    Label count_incremented;
+    if (create_memento) {
+      __ jmp(&count_incremented);
+    }
 
     // Receiver for constructor call allocated.
     // t0: JSObject
index 012b153..c59d3ba 100644 (file)
@@ -99,41 +99,6 @@ void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
 }
 
 
-static void Generate_Runtime_NewObject(MacroAssembler* masm,
-                                       bool create_memento,
-                                       Register original_constructor,
-                                       Label* count_incremented,
-                                       Label* allocated) {
-  int offset = kPointerSize;
-  if (create_memento) {
-    // Get the cell or allocation site.
-    __ movp(rdi, Operand(rsp, kPointerSize * 3));
-    __ Push(rdi);
-    offset += kPointerSize;
-  }
-
-  // Must restore rsi (context) and rdi (constructor) before calling runtime.
-  __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
-  __ movp(rdi, Operand(rsp, offset));
-  __ Push(rdi);
-  __ Push(original_constructor);
-  if (create_memento) {
-    __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
-  } else {
-    __ CallRuntime(Runtime::kNewObject, 2);
-  }
-  __ movp(rbx, rax);  // store result in rbx
-
-  // Runtime_NewObjectWithAllocationSite increments allocation count.
-  // Skip the increment.
-  if (create_memento) {
-    __ jmp(count_incremented);
-  } else {
-    __ jmp(allocated);
-  }
-}
-
-
 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
                                            bool is_api_function,
                                            bool create_memento) {
@@ -162,16 +127,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     __ Push(rdi);
     __ Push(rdx);
 
-    Label rt_call, normal_new, allocated, count_incremented;
-    __ cmpp(rdx, rdi);
-    __ j(equal, &normal_new);
-
-    Generate_Runtime_NewObject(masm, create_memento, rdx, &count_incremented,
-                               &allocated);
-
-    __ bind(&normal_new);
     // Try to allocate the object without transitioning into C code. If any of
     // the preconditions is not met, the code bails out to the runtime call.
+    Label rt_call, allocated;
     if (FLAG_inline_new) {
       ExternalReference debug_step_in_fp =
           ExternalReference::debug_step_in_fp_address(masm->isolate());
@@ -179,6 +137,10 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
       __ cmpp(Operand(kScratchRegister, 0), Immediate(0));
       __ j(not_equal, &rt_call);
 
+      // Fall back to runtime if the original constructor and function differ.
+      __ cmpp(rdx, rdi);
+      __ j(not_equal, &rt_call);
+
       // Verified that the constructor is a JSFunction.
       // Load the initial map and verify that it is in fact a map.
       // rdi: constructor
@@ -215,12 +177,14 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
         __ j(not_equal, &allocate);
 
         __ Push(rax);
+        __ Push(rdx);
         __ Push(rdi);
 
         __ Push(rdi);  // constructor
         __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
 
         __ Pop(rdi);
+        __ Pop(rdx);
         __ Pop(rax);
         __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1));
 
@@ -307,10 +271,34 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
     }
 
     // Allocate the new receiver object using the runtime call.
-    // rdi: function (constructor)
+    // rdx: original constructor
     __ bind(&rt_call);
-    Generate_Runtime_NewObject(masm, create_memento, rdi, &count_incremented,
-                               &allocated);
+    int offset = kPointerSize;
+    if (create_memento) {
+      // Get the cell or allocation site.
+      __ movp(rdi, Operand(rsp, kPointerSize * 3));
+      __ Push(rdi);  // argument 1: allocation site
+      offset += kPointerSize;
+    }
+
+    // Must restore rsi (context) and rdi (constructor) before calling runtime.
+    __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+    __ movp(rdi, Operand(rsp, offset));
+    __ Push(rdi);  // argument 2/1: constructor function
+    __ Push(rdx);  // argument 3/2: original constructor
+    if (create_memento) {
+      __ CallRuntime(Runtime::kNewObjectWithAllocationSite, 3);
+    } else {
+      __ CallRuntime(Runtime::kNewObject, 2);
+    }
+    __ movp(rbx, rax);  // store result in rbx
+
+    // Runtime_NewObjectWithAllocationSite increments allocation count.
+    // Skip the increment.
+    Label count_incremented;
+    if (create_memento) {
+      __ jmp(&count_incremented);
+    }
 
     // New object allocated.
     // rbx: newly allocated object