Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(378)

Unified Diff: src/ia32/builtins-ia32.cc

Issue 1221803004: Unify all four JSConstructStub generators into one. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@local_graph-builder-super-1
Patch Set: Rebased. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/builtins-ia32.cc
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index ef9f30d715106dea2224cab66c426bbc8842d75e..48e9a96722822c7f2db94ca93011abc88644899f 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -139,6 +139,7 @@ static void Generate_Runtime_NewObject(MacroAssembler* masm,
static void Generate_JSConstructStubHelper(MacroAssembler* masm,
bool is_api_function,
bool use_new_target,
+ bool is_derived_class,
bool create_memento) {
// ----------- S t a t e -------------
// -- eax: number of arguments
@@ -150,6 +151,9 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Should never create mementos for api functions.
DCHECK(!is_api_function || !create_memento);
+ // Should never create mementos for subclass constructors.
+ DCHECK(!is_derived_class || !create_memento);
+
// Enter a construct frame.
{
FrameScope scope(masm, StackFrame::CONSTRUCT);
@@ -162,256 +166,252 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Preserve the incoming parameters on the stack.
__ SmiTag(eax);
__ push(eax);
- __ push(edi);
- if (use_new_target) {
- __ 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;
- if (FLAG_inline_new) {
- Label undo_allocation;
- 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);
-
- // Verified that the constructor is a JSFunction.
- // Load the initial map and verify that it is in fact a map.
- // edi: constructor
- __ mov(eax, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
- // Will both indicate a NULL and a Smi
- __ JumpIfSmi(eax, &rt_call);
- // edi: constructor
- // eax: initial map (if proven valid below)
- __ CmpObjectType(eax, MAP_TYPE, ebx);
- __ j(not_equal, &rt_call);
-
- // Check that the constructor is not constructing a JSFunction (see
- // comments in Runtime_NewObject in runtime.cc). In which case the
- // initial map's instance type would be JS_FUNCTION_TYPE.
- // edi: constructor
- // eax: initial map
- __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
- __ j(equal, &rt_call);
-
- if (!is_api_function) {
- Label allocate;
- // The code below relies on these assumptions.
- STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
- // Check if slack tracking is enabled.
- __ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
- __ shr(esi, Map::Counter::kShift);
- __ cmp(esi, Map::kSlackTrackingCounterEnd);
- __ j(less, &allocate);
- // Decrease generous allocation count.
- __ sub(FieldOperand(eax, Map::kBitField3Offset),
- Immediate(1 << Map::Counter::kShift));
-
- __ cmp(esi, Map::kSlackTrackingCounterEnd);
- __ j(not_equal, &allocate);
-
- __ push(eax);
- __ push(edi);
-
- __ push(edi); // constructor
- __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
-
- __ pop(edi);
- __ pop(eax);
- __ mov(esi, Map::kSlackTrackingCounterEnd - 1);
-
- __ bind(&allocate);
+ if (!is_derived_class) {
+ __ push(edi);
+ if (use_new_target) {
+ __ push(edx);
}
- // Now allocate the JSObject on the heap.
- // edi: constructor
- // eax: initial map
- __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
- __ shl(edi, kPointerSizeLog2);
- if (create_memento) {
- __ add(edi, Immediate(AllocationMemento::kSize));
- }
+ __ 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;
+ if (FLAG_inline_new) {
+ Label undo_allocation;
+ 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);
+
+ // Verified that the constructor is a JSFunction.
+ // Load the initial map and verify that it is in fact a map.
+ // edi: constructor
+ __ mov(eax,
+ FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
+ // Will both indicate a NULL and a Smi
+ __ JumpIfSmi(eax, &rt_call);
+ // edi: constructor
+ // eax: initial map (if proven valid below)
+ __ CmpObjectType(eax, MAP_TYPE, ebx);
+ __ j(not_equal, &rt_call);
+
+ // Check that the constructor is not constructing a JSFunction (see
+ // comments in Runtime_NewObject in runtime.cc). In which case the
+ // initial map's instance type would be JS_FUNCTION_TYPE.
+ // edi: constructor
+ // eax: initial map
+ __ CmpInstanceType(eax, JS_FUNCTION_TYPE);
+ __ j(equal, &rt_call);
+
+ if (!is_api_function) {
+ Label allocate;
+ // The code below relies on these assumptions.
+ STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
+ // Check if slack tracking is enabled.
+ __ mov(esi, FieldOperand(eax, Map::kBitField3Offset));
+ __ shr(esi, Map::Counter::kShift);
+ __ cmp(esi, Map::kSlackTrackingCounterEnd);
+ __ j(less, &allocate);
+ // Decrease generous allocation count.
+ __ sub(FieldOperand(eax, Map::kBitField3Offset),
+ Immediate(1 << Map::Counter::kShift));
+
+ __ cmp(esi, Map::kSlackTrackingCounterEnd);
+ __ j(not_equal, &allocate);
+
+ __ push(eax);
+ __ push(edi);
+
+ __ push(edi); // constructor
+ __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
+
+ __ pop(edi);
+ __ pop(eax);
+ __ mov(esi, Map::kSlackTrackingCounterEnd - 1);
+
+ __ bind(&allocate);
+ }
- __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
-
- Factory* factory = masm->isolate()->factory();
-
- // Allocated the JSObject, now initialize the fields.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object (including memento if create_memento)
- __ mov(Operand(ebx, JSObject::kMapOffset), eax);
- __ mov(ecx, factory->empty_fixed_array());
- __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
- __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
- // Set extra fields in the newly allocated object.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object (including memento if create_memento)
- // esi: slack tracking counter (non-API function case)
- __ mov(edx, factory->undefined_value());
- __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
- if (!is_api_function) {
- Label no_inobject_slack_tracking;
-
- // Check if slack tracking is enabled.
- __ cmp(esi, Map::kSlackTrackingCounterEnd);
- __ j(less, &no_inobject_slack_tracking);
-
- // Allocate object with a slack.
- __ movzx_b(esi,
- FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
- __ lea(esi,
- Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
- // esi: offset of first field after pre-allocated fields
- if (FLAG_debug_code) {
- __ cmp(esi, edi);
- __ Assert(less_equal,
- kUnexpectedNumberOfPreAllocatedPropertyFields);
+ // Now allocate the JSObject on the heap.
+ // edi: constructor
+ // eax: initial map
+ __ movzx_b(edi, FieldOperand(eax, Map::kInstanceSizeOffset));
+ __ shl(edi, kPointerSizeLog2);
+ if (create_memento) {
+ __ add(edi, Immediate(AllocationMemento::kSize));
}
- __ InitializeFieldsWithFiller(ecx, esi, edx);
- __ mov(edx, factory->one_pointer_filler_map());
- // Fill the remaining fields with one pointer filler map.
- __ bind(&no_inobject_slack_tracking);
- }
+ __ Allocate(edi, ebx, edi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
+
+ Factory* factory = masm->isolate()->factory();
+
+ // Allocated the JSObject, now initialize the fields.
+ // eax: initial map
+ // ebx: JSObject
+ // edi: start of next object (including memento if create_memento)
+ __ mov(Operand(ebx, JSObject::kMapOffset), eax);
+ __ mov(ecx, factory->empty_fixed_array());
+ __ mov(Operand(ebx, JSObject::kPropertiesOffset), ecx);
+ __ mov(Operand(ebx, JSObject::kElementsOffset), ecx);
+ // Set extra fields in the newly allocated object.
+ // eax: initial map
+ // ebx: JSObject
+ // edi: start of next object (including memento if create_memento)
+ // esi: slack tracking counter (non-API function case)
+ __ mov(edx, factory->undefined_value());
+ __ lea(ecx, Operand(ebx, JSObject::kHeaderSize));
+ if (!is_api_function) {
+ Label no_inobject_slack_tracking;
+
+ // Check if slack tracking is enabled.
+ __ cmp(esi, Map::kSlackTrackingCounterEnd);
+ __ j(less, &no_inobject_slack_tracking);
+
+ // Allocate object with a slack.
+ __ movzx_b(esi,
+ FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
+ __ lea(esi,
+ Operand(ebx, esi, times_pointer_size, JSObject::kHeaderSize));
+ // esi: offset of first field after pre-allocated fields
+ if (FLAG_debug_code) {
+ __ cmp(esi, edi);
+ __ Assert(less_equal,
+ kUnexpectedNumberOfPreAllocatedPropertyFields);
+ }
+ __ InitializeFieldsWithFiller(ecx, esi, edx);
+ __ mov(edx, factory->one_pointer_filler_map());
+ // Fill the remaining fields with one pointer filler map.
+
+ __ bind(&no_inobject_slack_tracking);
+ }
- if (create_memento) {
- __ lea(esi, Operand(edi, -AllocationMemento::kSize));
- __ InitializeFieldsWithFiller(ecx, esi, edx);
-
- // Fill in memento fields if necessary.
- // esi: points to the allocated but uninitialized memento.
- __ mov(Operand(esi, AllocationMemento::kMapOffset),
- factory->allocation_memento_map());
- // Get the cell or undefined.
- __ mov(edx, Operand(esp, kPointerSize*2));
- __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset),
- edx);
- } else {
- __ InitializeFieldsWithFiller(ecx, edi, edx);
+ if (create_memento) {
+ __ lea(esi, Operand(edi, -AllocationMemento::kSize));
+ __ InitializeFieldsWithFiller(ecx, esi, edx);
+
+ // Fill in memento fields if necessary.
+ // esi: points to the allocated but uninitialized memento.
+ __ mov(Operand(esi, AllocationMemento::kMapOffset),
+ factory->allocation_memento_map());
+ // Get the cell or undefined.
+ __ mov(edx, Operand(esp, kPointerSize * 2));
+ __ mov(Operand(esi, AllocationMemento::kAllocationSiteOffset), edx);
+ } else {
+ __ InitializeFieldsWithFiller(ecx, edi, edx);
+ }
+
+ // Add the object tag to make the JSObject real, so that we can continue
+ // and jump into the continuation code at any time from now on. Any
+ // failures need to undo the allocation, so that the heap is in a
+ // consistent state and verifiable.
+ // eax: initial map
+ // ebx: JSObject
+ // edi: start of next object
+ __ or_(ebx, Immediate(kHeapObjectTag));
+
+ // Check if a non-empty properties array is needed.
+ // Allocate and initialize a FixedArray if it is.
+ // eax: initial map
+ // ebx: JSObject
+ // edi: start of next object
+ // Calculate the total number of properties described by the map.
+ __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
+ __ movzx_b(ecx,
+ FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
+ __ add(edx, ecx);
+ // Calculate unused properties past the end of the in-object properties.
+ __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
+ __ sub(edx, ecx);
+ // Done if no extra properties are to be allocated.
+ __ j(zero, &allocated);
+ __ Assert(positive, kPropertyAllocationCountFailed);
+
+ // Scale the number of elements by pointer size and add the header for
+ // FixedArrays to the start of the next object calculation from above.
+ // ebx: JSObject
+ // edi: start of next object (will be start of FixedArray)
+ // edx: number of elements in properties array
+ __ Allocate(FixedArray::kHeaderSize, times_pointer_size, edx,
+ REGISTER_VALUE_IS_INT32, edi, ecx, no_reg, &undo_allocation,
+ RESULT_CONTAINS_TOP);
+
+ // Initialize the FixedArray.
+ // ebx: JSObject
+ // edi: FixedArray
+ // edx: number of elements
+ // ecx: start of next object
+ __ mov(eax, factory->fixed_array_map());
+ __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
+ __ SmiTag(edx);
+ __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
+
+ // Initialize the fields to undefined.
+ // ebx: JSObject
+ // edi: FixedArray
+ // ecx: start of next object
+ __ mov(edx, factory->undefined_value());
+ __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
+ __ InitializeFieldsWithFiller(eax, ecx, edx);
+
+ // Store the initialized FixedArray into the properties field of
+ // the JSObject
+ // ebx: JSObject
+ // edi: FixedArray
+ __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag
+ __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
+
+
+ // Continue with JSObject being successfully allocated
+ // ebx: JSObject
+ __ jmp(&allocated);
+
+ // Undo the setting of the new top so that the heap is verifiable. For
+ // example, the map's unused properties potentially do not match the
+ // allocated objects unused properties.
+ // ebx: JSObject (previous new top)
+ __ bind(&undo_allocation);
+ __ UndoAllocationInNewSpace(ebx);
}
- // Add the object tag to make the JSObject real, so that we can continue
- // and jump into the continuation code at any time from now on. Any
- // failures need to undo the allocation, so that the heap is in a
- // consistent state and verifiable.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object
- __ or_(ebx, Immediate(kHeapObjectTag));
-
- // Check if a non-empty properties array is needed.
- // Allocate and initialize a FixedArray if it is.
- // eax: initial map
- // ebx: JSObject
- // edi: start of next object
- // Calculate the total number of properties described by the map.
- __ movzx_b(edx, FieldOperand(eax, Map::kUnusedPropertyFieldsOffset));
- __ movzx_b(ecx,
- FieldOperand(eax, Map::kPreAllocatedPropertyFieldsOffset));
- __ add(edx, ecx);
- // Calculate unused properties past the end of the in-object properties.
- __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
- __ sub(edx, ecx);
- // Done if no extra properties are to be allocated.
- __ j(zero, &allocated);
- __ Assert(positive, kPropertyAllocationCountFailed);
-
- // Scale the number of elements by pointer size and add the header for
- // FixedArrays to the start of the next object calculation from above.
- // ebx: JSObject
- // edi: start of next object (will be start of FixedArray)
- // edx: number of elements in properties array
- __ Allocate(FixedArray::kHeaderSize,
- times_pointer_size,
- edx,
- REGISTER_VALUE_IS_INT32,
- edi,
- ecx,
- no_reg,
- &undo_allocation,
- RESULT_CONTAINS_TOP);
-
- // Initialize the FixedArray.
- // ebx: JSObject
- // edi: FixedArray
- // edx: number of elements
- // ecx: start of next object
- __ mov(eax, factory->fixed_array_map());
- __ mov(Operand(edi, FixedArray::kMapOffset), eax); // setup the map
- __ SmiTag(edx);
- __ mov(Operand(edi, FixedArray::kLengthOffset), edx); // and length
-
- // Initialize the fields to undefined.
- // ebx: JSObject
- // edi: FixedArray
- // ecx: start of next object
- __ mov(edx, factory->undefined_value());
- __ lea(eax, Operand(edi, FixedArray::kHeaderSize));
- __ InitializeFieldsWithFiller(eax, ecx, edx);
-
- // Store the initialized FixedArray into the properties field of
- // the JSObject
- // ebx: JSObject
- // edi: FixedArray
- __ or_(edi, Immediate(kHeapObjectTag)); // add the heap tag
- __ mov(FieldOperand(ebx, JSObject::kPropertiesOffset), edi);
-
-
- // Continue with JSObject being successfully allocated
- // ebx: JSObject
- __ jmp(&allocated);
-
- // Undo the setting of the new top so that the heap is verifiable. For
- // example, the map's unused properties potentially do not match the
- // allocated objects unused properties.
- // ebx: JSObject (previous new top)
- __ bind(&undo_allocation);
- __ UndoAllocationInNewSpace(ebx);
- }
+ // Allocate the new receiver object using the runtime call.
+ __ bind(&rt_call);
+ Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented,
+ &allocated);
+ // New object allocated.
+ // ebx: newly allocated object
+ __ bind(&allocated);
- // Allocate the new receiver object using the runtime call.
- __ bind(&rt_call);
- Generate_Runtime_NewObject(masm, create_memento, edi, &count_incremented,
- &allocated);
- // New object allocated.
- // ebx: newly allocated object
- __ bind(&allocated);
+ if (create_memento) {
+ int offset = (use_new_target ? 3 : 2) * kPointerSize;
+ __ mov(ecx, Operand(esp, offset));
+ __ cmp(ecx, masm->isolate()->factory()->undefined_value());
+ __ j(equal, &count_incremented);
+ // ecx is an AllocationSite. We are creating a memento from it, so we
+ // need to increment the memento create count.
+ __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset),
+ Immediate(Smi::FromInt(1)));
+ __ bind(&count_incremented);
+ }
- if (create_memento) {
- int offset = (use_new_target ? 3 : 2) * kPointerSize;
- __ mov(ecx, Operand(esp, offset));
- __ cmp(ecx, masm->isolate()->factory()->undefined_value());
- __ j(equal, &count_incremented);
- // ecx is an AllocationSite. We are creating a memento from it, so we
- // need to increment the memento create count.
- __ add(FieldOperand(ecx, AllocationSite::kPretenureCreateCountOffset),
- Immediate(Smi::FromInt(1)));
- __ bind(&count_incremented);
- }
+ // Restore the parameters.
+ if (use_new_target) {
+ __ pop(edx); // new.target
+ }
+ __ pop(edi); // Constructor function.
- // Restore the parameters.
- if (use_new_target) {
- __ pop(edx); // new.target
+ // Retrieve smi-tagged arguments count from the stack.
+ __ mov(eax, Operand(esp, 0));
}
- __ pop(edi); // Constructor function.
-
- // Retrieve smi-tagged arguments count from the stack.
- __ mov(eax, Operand(esp, 0));
__ SmiUntag(eax);
// Push new.target onto the construct frame. This is stored just below the
@@ -423,8 +423,13 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Push the allocated receiver to the stack. We need two copies
// because we may have to return the original one and the calling
// conventions dictate that the called function pops the receiver.
- __ push(ebx);
- __ push(ebx);
+ if (!is_derived_class) {
+ __ push(ebx);
+ __ push(ebx);
+ } else {
+ // receiver is the hole.
+ __ push(Immediate(masm->isolate()->factory()->the_hole_value()));
+ }
// Set up pointer to last argument.
__ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
@@ -439,6 +444,24 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
__ dec(ecx);
__ j(greater_equal, &loop);
+ // Handle step in.
+ if (is_derived_class) {
+ Label skip_step_in;
+ ExternalReference debug_step_in_fp =
+ ExternalReference::debug_step_in_fp_address(masm->isolate());
+ __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
+ __ j(equal, &skip_step_in);
+
+ __ push(eax);
+ __ push(edi);
+ __ push(edi);
+ __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
+ __ pop(edi);
+ __ pop(eax);
+
+ __ bind(&skip_step_in);
+ }
+
// Call the function.
if (is_api_function) {
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
@@ -454,7 +477,7 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// Store offset of return address for deoptimizer.
// TODO(arv): Remove the "!use_new_target" before supporting optimization
// of functions that reference new.target
- if (!is_api_function && !use_new_target) {
+ if (!is_api_function && !use_new_target && !is_derived_class) {
masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
}
@@ -464,25 +487,28 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
// If the result is an object (in the ECMA sense), we should get rid
// of the receiver and use the result; see ECMA-262 section 13.2.2-7
// on page 74.
- Label use_receiver, exit;
+ if (!is_derived_class) {
+ Label use_receiver, exit;
+
+ // If the result is a smi, it is *not* an object in the ECMA sense.
+ __ JumpIfSmi(eax, &use_receiver);
- // If the result is a smi, it is *not* an object in the ECMA sense.
- __ JumpIfSmi(eax, &use_receiver);
+ // If the type of the result (stored in its map) is less than
+ // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
+ __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
+ __ j(above_equal, &exit);
- // If the type of the result (stored in its map) is less than
- // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
- __ CmpObjectType(eax, FIRST_SPEC_OBJECT_TYPE, ecx);
- __ j(above_equal, &exit);
+ // Throw away the result of the constructor invocation and use the
+ // on-stack receiver as the result.
+ __ bind(&use_receiver);
+ __ mov(eax, Operand(esp, 0));
- // Throw away the result of the constructor invocation and use the
- // on-stack receiver as the result.
- __ bind(&use_receiver);
- __ mov(eax, Operand(esp, 0));
+ __ bind(&exit);
+ }
// Restore the arguments count and leave the construct frame. The arguments
// count is stored below the reciever and the new.target.
- __ bind(&exit);
- int offset = (use_new_target ? 2 : 1) * kPointerSize;
+ int offset = ((use_new_target && !is_derived_class) ? 2 : 1) * kPointerSize;
__ mov(ebx, Operand(esp, offset));
// Leave construct frame.
@@ -499,89 +525,24 @@ static void Generate_JSConstructStubHelper(MacroAssembler* masm,
void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new);
+ bool create_memento = FLAG_pretenuring_call_new;
+ Generate_JSConstructStubHelper(masm, false, false, false, create_memento);
}
void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
- Generate_JSConstructStubHelper(masm, true, false, false);
+ Generate_JSConstructStubHelper(masm, true, false, false, false);
}
void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) {
arv (Not doing code reviews) 2015/07/07 16:32:26 I think we should get rid of this stub and have JS
Michael Starzinger 2015/07/07 16:46:59 Yes, oh god please yes, from the bottom of my hear
Michael Starzinger 2015/07/07 16:50:59 To rephrase this in a more professional way: Agree
- Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new);
+ bool create_memento = FLAG_pretenuring_call_new;
+ Generate_JSConstructStubHelper(masm, false, true, false, create_memento);
}
void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- eax: number of arguments
- // -- edi: constructor function
- // -- ebx: allocation site or undefined
- // -- edx: original constructor
- // -----------------------------------
-
- // TODO(dslomov): support pretenuring
- CHECK(!FLAG_pretenuring_call_new);
-
- {
- FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
-
- // Preserve actual arguments count.
- __ SmiTag(eax);
- __ push(eax);
- __ SmiUntag(eax);
-
- // Push new.target.
- __ push(edx);
-
- // receiver is the hole.
- __ push(Immediate(masm->isolate()->factory()->the_hole_value()));
-
- // Set up pointer to last argument.
- __ lea(ebx, Operand(ebp, StandardFrameConstants::kCallerSPOffset));
-
- // Copy arguments and receiver to the expression stack.
- Label loop, entry;
- __ mov(ecx, eax);
- __ jmp(&entry);
- __ bind(&loop);
- __ push(Operand(ebx, ecx, times_4, 0));
- __ bind(&entry);
- __ dec(ecx);
- __ j(greater_equal, &loop);
-
- // Handle step in.
- Label skip_step_in;
- ExternalReference debug_step_in_fp =
- ExternalReference::debug_step_in_fp_address(masm->isolate());
- __ cmp(Operand::StaticVariable(debug_step_in_fp), Immediate(0));
- __ j(equal, &skip_step_in);
-
- __ push(eax);
- __ push(edi);
- __ push(edi);
- __ CallRuntime(Runtime::kHandleStepInForDerivedConstructors, 1);
- __ pop(edi);
- __ pop(eax);
-
- __ bind(&skip_step_in);
-
- // Invoke function.
- ParameterCount actual(eax);
- __ InvokeFunction(edi, actual, CALL_FUNCTION, NullCallWrapper());
-
- // Restore context from the frame.
- __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-
- // Get arguments count, skipping over new.target.
- __ mov(ebx, Operand(esp, kPointerSize));
- }
-
- __ pop(ecx); // Return address.
- __ lea(esp, Operand(esp, ebx, times_2, 1 * kPointerSize));
- __ push(ecx);
- __ ret(0);
+ Generate_JSConstructStubHelper(masm, false, true, true, false);
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698