| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
| (...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1746 | 1746 |
| 1747 | 1747 |
| 1748 HAllocate* HGraphBuilder::BuildAllocate( | 1748 HAllocate* HGraphBuilder::BuildAllocate( |
| 1749 HValue* object_size, | 1749 HValue* object_size, |
| 1750 HType type, | 1750 HType type, |
| 1751 InstanceType instance_type, | 1751 InstanceType instance_type, |
| 1752 HAllocationMode allocation_mode) { | 1752 HAllocationMode allocation_mode) { |
| 1753 // Compute the effective allocation size. | 1753 // Compute the effective allocation size. |
| 1754 HValue* size = object_size; | 1754 HValue* size = object_size; |
| 1755 if (allocation_mode.CreateAllocationMementos()) { | 1755 if (allocation_mode.CreateAllocationMementos()) { |
| 1756 size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize)); | 1756 NoObservableSideEffectsScope no_effects(this); |
| 1757 size = AddInstruction( |
| 1758 HAdd::New(zone(), context(), object_size, |
| 1759 Add<HConstant>(AllocationMemento::kSize))); |
| 1757 size->ClearFlag(HValue::kCanOverflow); | 1760 size->ClearFlag(HValue::kCanOverflow); |
| 1758 } | 1761 } |
| 1759 | 1762 |
| 1760 // Perform the actual allocation. | 1763 // Perform the actual allocation. |
| 1761 HAllocate* object = Add<HAllocate>( | 1764 HAllocate* object = Add<HAllocate>( |
| 1762 size, type, allocation_mode.GetPretenureMode(), | 1765 size, type, allocation_mode.GetPretenureMode(), |
| 1763 instance_type, allocation_mode.feedback_site()); | 1766 instance_type, allocation_mode.feedback_site()); |
| 1764 | 1767 |
| 1765 // Setup the allocation memento. | 1768 // Setup the allocation memento. |
| 1766 if (allocation_mode.CreateAllocationMementos()) { | 1769 if (allocation_mode.CreateAllocationMementos()) { |
| (...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2791 } | 2794 } |
| 2792 | 2795 |
| 2793 if_nil.CaptureContinuation(continuation); | 2796 if_nil.CaptureContinuation(continuation); |
| 2794 } | 2797 } |
| 2795 | 2798 |
| 2796 | 2799 |
| 2797 void HGraphBuilder::BuildCreateAllocationMemento( | 2800 void HGraphBuilder::BuildCreateAllocationMemento( |
| 2798 HValue* previous_object, | 2801 HValue* previous_object, |
| 2799 HValue* previous_object_size, | 2802 HValue* previous_object_size, |
| 2800 HValue* allocation_site) { | 2803 HValue* allocation_site) { |
| 2804 NoObservableSideEffectsScope no_effects(this); |
| 2801 ASSERT(allocation_site != NULL); | 2805 ASSERT(allocation_site != NULL); |
| 2802 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( | 2806 HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>( |
| 2803 previous_object, previous_object_size, HType::HeapObject()); | 2807 previous_object, previous_object_size, HType::HeapObject()); |
| 2804 AddStoreMapConstant( | 2808 AddStoreMapConstant( |
| 2805 allocation_memento, isolate()->factory()->allocation_memento_map()); | 2809 allocation_memento, isolate()->factory()->allocation_memento_map()); |
| 2806 Add<HStoreNamedField>( | 2810 Add<HStoreNamedField>( |
| 2807 allocation_memento, | 2811 allocation_memento, |
| 2808 HObjectAccess::ForAllocationMementoSite(), | 2812 HObjectAccess::ForAllocationMementoSite(), |
| 2809 allocation_site); | 2813 allocation_site); |
| 2810 if (FLAG_allocation_site_pretenuring) { | 2814 if (FLAG_allocation_site_pretenuring) { |
| (...skipping 2346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5157 Handle<JSObject> boilerplate; | 5161 Handle<JSObject> boilerplate; |
| 5158 if (!literals_cell->IsUndefined()) { | 5162 if (!literals_cell->IsUndefined()) { |
| 5159 // Retrieve the boilerplate | 5163 // Retrieve the boilerplate |
| 5160 site = Handle<AllocationSite>::cast(literals_cell); | 5164 site = Handle<AllocationSite>::cast(literals_cell); |
| 5161 boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()), | 5165 boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()), |
| 5162 isolate()); | 5166 isolate()); |
| 5163 } | 5167 } |
| 5164 | 5168 |
| 5165 if (!boilerplate.is_null() && | 5169 if (!boilerplate.is_null() && |
| 5166 IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) { | 5170 IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) { |
| 5167 AllocationSiteUsageContext usage_context(isolate(), site, false); | 5171 bool emit_mementos = FLAG_allocation_site_pretenuring && |
| 5172 site->emit_mementos(); |
| 5173 AllocationSiteUsageContext usage_context(isolate(), site, emit_mementos); |
| 5168 usage_context.EnterNewScope(); | 5174 usage_context.EnterNewScope(); |
| 5169 literal = BuildFastLiteral(boilerplate, &usage_context); | 5175 literal = BuildFastLiteral(boilerplate, &usage_context); |
| 5170 usage_context.ExitScope(site, boilerplate); | 5176 usage_context.ExitScope(site, boilerplate); |
| 5171 } else { | 5177 } else { |
| 5172 NoObservableSideEffectsScope no_effects(this); | 5178 NoObservableSideEffectsScope no_effects(this); |
| 5173 Handle<FixedArray> closure_literals(closure->literals(), isolate()); | 5179 Handle<FixedArray> closure_literals(closure->literals(), isolate()); |
| 5174 Handle<FixedArray> constant_properties = expr->constant_properties(); | 5180 Handle<FixedArray> constant_properties = expr->constant_properties(); |
| 5175 int literal_index = expr->literal_index(); | 5181 int literal_index = expr->literal_index(); |
| 5176 int flags = expr->fast_elements() | 5182 int flags = expr->fast_elements() |
| 5177 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; | 5183 ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5314 ASSERT(site->SitePointsToLiteral()); | 5320 ASSERT(site->SitePointsToLiteral()); |
| 5315 | 5321 |
| 5316 ElementsKind boilerplate_elements_kind = | 5322 ElementsKind boilerplate_elements_kind = |
| 5317 boilerplate_object->GetElementsKind(); | 5323 boilerplate_object->GetElementsKind(); |
| 5318 | 5324 |
| 5319 // Check whether to use fast or slow deep-copying for boilerplate. | 5325 // Check whether to use fast or slow deep-copying for boilerplate. |
| 5320 int max_properties = kMaxFastLiteralProperties; | 5326 int max_properties = kMaxFastLiteralProperties; |
| 5321 if (IsFastLiteral(boilerplate_object, | 5327 if (IsFastLiteral(boilerplate_object, |
| 5322 kMaxFastLiteralDepth, | 5328 kMaxFastLiteralDepth, |
| 5323 &max_properties)) { | 5329 &max_properties)) { |
| 5324 AllocationSiteUsageContext usage_context(isolate(), site, false); | 5330 bool emit_mementos = FLAG_allocation_site_pretenuring && |
| 5331 site->emit_mementos(); |
| 5332 AllocationSiteUsageContext usage_context(isolate(), site, emit_mementos); |
| 5325 usage_context.EnterNewScope(); | 5333 usage_context.EnterNewScope(); |
| 5326 literal = BuildFastLiteral(boilerplate_object, &usage_context); | 5334 literal = BuildFastLiteral(boilerplate_object, &usage_context); |
| 5327 usage_context.ExitScope(site, boilerplate_object); | 5335 usage_context.ExitScope(site, boilerplate_object); |
| 5328 } else { | 5336 } else { |
| 5329 NoObservableSideEffectsScope no_effects(this); | 5337 NoObservableSideEffectsScope no_effects(this); |
| 5330 // Boilerplate already exists and constant elements are never accessed, | 5338 // Boilerplate already exists and constant elements are never accessed, |
| 5331 // pass an empty fixed array to the runtime function instead. | 5339 // pass an empty fixed array to the runtime function instead. |
| 5332 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); | 5340 Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array(); |
| 5333 int literal_index = expr->literal_index(); | 5341 int literal_index = expr->literal_index(); |
| 5334 int flags = expr->depth() == 1 | 5342 int flags = expr->depth() == 1 |
| (...skipping 2985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8320 target->context()->global_object()->global_receiver()); | 8328 target->context()->global_object()->global_receiver()); |
| 8321 return Add<HConstant>(global_receiver); | 8329 return Add<HConstant>(global_receiver); |
| 8322 } | 8330 } |
| 8323 return graph()->GetConstantUndefined(); | 8331 return graph()->GetConstantUndefined(); |
| 8324 } | 8332 } |
| 8325 | 8333 |
| 8326 | 8334 |
| 8327 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression, | 8335 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression, |
| 8328 int arguments_count, | 8336 int arguments_count, |
| 8329 HValue* function, | 8337 HValue* function, |
| 8330 Handle<AllocationSite> site) { | 8338 Handle<AllocationSite> site, |
| 8339 HAllocationMode mode) { |
| 8331 Add<HCheckValue>(function, array_function()); | 8340 Add<HCheckValue>(function, array_function()); |
| 8332 | 8341 |
| 8333 if (IsCallArrayInlineable(arguments_count, site)) { | 8342 if (IsCallArrayInlineable(arguments_count, site)) { |
| 8334 BuildInlinedCallArray(expression, arguments_count, site); | 8343 BuildInlinedCallArray(expression, arguments_count, mode, site); |
| 8335 return; | 8344 return; |
| 8336 } | 8345 } |
| 8337 | 8346 |
| 8338 HInstruction* call = PreProcessCall(New<HCallNewArray>( | 8347 HInstruction* call = PreProcessCall(New<HCallNewArray>( |
| 8339 function, arguments_count + 1, site->GetElementsKind())); | 8348 function, arguments_count + 1, site->GetElementsKind(), mode)); |
| 8340 if (expression->IsCall()) { | 8349 if (expression->IsCall()) { |
| 8341 Drop(1); | 8350 Drop(1); |
| 8342 } | 8351 } |
| 8343 ast_context()->ReturnInstruction(call, expression->id()); | 8352 ast_context()->ReturnInstruction(call, expression->id()); |
| 8344 } | 8353 } |
| 8345 | 8354 |
| 8346 | 8355 |
| 8347 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver, | 8356 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver, |
| 8348 HValue* search_element, | 8357 HValue* search_element, |
| 8349 ElementsKind kind, | 8358 ElementsKind kind, |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8490 if (!array_function().is_identical_to(expr->target())) { | 8499 if (!array_function().is_identical_to(expr->target())) { |
| 8491 return false; | 8500 return false; |
| 8492 } | 8501 } |
| 8493 | 8502 |
| 8494 Handle<AllocationSite> site = expr->allocation_site(); | 8503 Handle<AllocationSite> site = expr->allocation_site(); |
| 8495 if (site.is_null()) return false; | 8504 if (site.is_null()) return false; |
| 8496 | 8505 |
| 8497 BuildArrayCall(expr, | 8506 BuildArrayCall(expr, |
| 8498 expr->arguments()->length(), | 8507 expr->arguments()->length(), |
| 8499 function, | 8508 function, |
| 8500 site); | 8509 site, |
| 8510 HAllocationMode()); |
| 8501 return true; | 8511 return true; |
| 8502 } | 8512 } |
| 8503 | 8513 |
| 8504 | 8514 |
| 8505 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr, | 8515 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr, |
| 8506 HValue* function) { | 8516 HValue* function, |
| 8517 HAllocationMode mode) { |
| 8507 if (!array_function().is_identical_to(expr->target())) { | 8518 if (!array_function().is_identical_to(expr->target())) { |
| 8508 return false; | 8519 return false; |
| 8509 } | 8520 } |
| 8510 | 8521 |
| 8511 BuildArrayCall(expr, | 8522 BuildArrayCall(expr, |
| 8512 expr->arguments()->length(), | 8523 expr->arguments()->length(), |
| 8513 function, | 8524 function, |
| 8514 expr->allocation_site()); | 8525 expr->allocation_site(), |
| 8526 mode); |
| 8515 return true; | 8527 return true; |
| 8516 } | 8528 } |
| 8517 | 8529 |
| 8518 | 8530 |
| 8519 void HOptimizedGraphBuilder::VisitCall(Call* expr) { | 8531 void HOptimizedGraphBuilder::VisitCall(Call* expr) { |
| 8520 ASSERT(!HasStackOverflow()); | 8532 ASSERT(!HasStackOverflow()); |
| 8521 ASSERT(current_block() != NULL); | 8533 ASSERT(current_block() != NULL); |
| 8522 ASSERT(current_block()->HasPredecessor()); | 8534 ASSERT(current_block()->HasPredecessor()); |
| 8523 Expression* callee = expr->expression(); | 8535 Expression* callee = expr->expression(); |
| 8524 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 8536 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8690 } | 8702 } |
| 8691 | 8703 |
| 8692 Drop(1); // Drop the function. | 8704 Drop(1); // Drop the function. |
| 8693 return ast_context()->ReturnInstruction(call, expr->id()); | 8705 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8694 } | 8706 } |
| 8695 | 8707 |
| 8696 | 8708 |
| 8697 void HOptimizedGraphBuilder::BuildInlinedCallArray( | 8709 void HOptimizedGraphBuilder::BuildInlinedCallArray( |
| 8698 Expression* expression, | 8710 Expression* expression, |
| 8699 int argument_count, | 8711 int argument_count, |
| 8712 HAllocationMode mode, |
| 8700 Handle<AllocationSite> site) { | 8713 Handle<AllocationSite> site) { |
| 8701 ASSERT(!site.is_null()); | 8714 ASSERT(!site.is_null()); |
| 8702 ASSERT(argument_count >= 0 && argument_count <= 1); | 8715 ASSERT(argument_count >= 0 && argument_count <= 1); |
| 8703 NoObservableSideEffectsScope no_effects(this); | 8716 NoObservableSideEffectsScope no_effects(this); |
| 8704 | 8717 |
| 8705 // We should at least have the constructor on the expression stack. | 8718 // We should at least have the constructor on the expression stack. |
| 8706 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 8719 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 8707 | 8720 |
| 8708 // Register on the site for deoptimization if the transition feedback changes. | 8721 // Register on the site for deoptimization if the transition feedback changes. |
| 8709 AllocationSite::AddDependentCompilationInfo( | 8722 AllocationSite::AddDependentCompilationInfo( |
| 8710 site, AllocationSite::TRANSITIONS, top_info()); | 8723 site, AllocationSite::TRANSITIONS, top_info()); |
| 8711 ElementsKind kind = site->GetElementsKind(); | 8724 ElementsKind kind = site->GetElementsKind(); |
| 8712 HInstruction* site_instruction = Add<HConstant>(site); | 8725 HInstruction* site_instruction = Add<HConstant>(site); |
| 8713 | 8726 |
| 8714 // In the single constant argument case, we may have to adjust elements kind | 8727 // In the single constant argument case, we may have to adjust elements kind |
| 8715 // to avoid creating a packed non-empty array. | 8728 // to avoid creating a packed non-empty array. |
| 8716 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 8729 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 8717 HValue* argument = environment()->Top(); | 8730 HValue* argument = environment()->Top(); |
| 8718 if (argument->IsConstant()) { | 8731 if (argument->IsConstant()) { |
| 8719 HConstant* constant_argument = HConstant::cast(argument); | 8732 HConstant* constant_argument = HConstant::cast(argument); |
| 8720 ASSERT(constant_argument->HasSmiValue()); | 8733 ASSERT(constant_argument->HasSmiValue()); |
| 8721 int constant_array_size = constant_argument->Integer32Value(); | 8734 int constant_array_size = constant_argument->Integer32Value(); |
| 8722 if (constant_array_size != 0) { | 8735 if (constant_array_size != 0) { |
| 8723 kind = GetHoleyElementsKind(kind); | 8736 kind = GetHoleyElementsKind(kind); |
| 8724 } | 8737 } |
| 8725 } | 8738 } |
| 8726 } | 8739 } |
| 8727 | 8740 |
| 8728 // Build the array. | 8741 // Build the array. Should we emit mementos? |
| 8742 AllocationSiteOverrideMode site_mode = mode.CreateAllocationMementos() |
| 8743 ? DONT_OVERRIDE |
| 8744 : DISABLE_ALLOCATION_SITES; |
| 8745 |
| 8729 JSArrayBuilder array_builder(this, | 8746 JSArrayBuilder array_builder(this, |
| 8730 kind, | 8747 kind, |
| 8731 site_instruction, | 8748 site_instruction, |
| 8732 constructor, | 8749 constructor, |
| 8733 DISABLE_ALLOCATION_SITES); | 8750 site_mode); |
| 8751 |
| 8734 HValue* new_object = argument_count == 0 | 8752 HValue* new_object = argument_count == 0 |
| 8735 ? array_builder.AllocateEmptyArray() | 8753 ? array_builder.AllocateEmptyArray() |
| 8736 : BuildAllocateArrayFromLength(&array_builder, Top()); | 8754 : BuildAllocateArrayFromLength(&array_builder, Top()); |
| 8737 | 8755 |
| 8738 int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1); | 8756 int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1); |
| 8739 Drop(args_to_drop); | 8757 Drop(args_to_drop); |
| 8740 ast_context()->ReturnValue(new_object); | 8758 ast_context()->ReturnValue(new_object); |
| 8741 } | 8759 } |
| 8742 | 8760 |
| 8743 | 8761 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8789 TraceInline(target, caller, "AllocationSite requested no inlining."); | 8807 TraceInline(target, caller, "AllocationSite requested no inlining."); |
| 8790 } | 8808 } |
| 8791 | 8809 |
| 8792 if (inline_ok) { | 8810 if (inline_ok) { |
| 8793 TraceInline(target, caller, NULL); | 8811 TraceInline(target, caller, NULL); |
| 8794 } | 8812 } |
| 8795 return inline_ok; | 8813 return inline_ok; |
| 8796 } | 8814 } |
| 8797 | 8815 |
| 8798 | 8816 |
| 8817 void HOptimizedGraphBuilder::InitializeAllocationModeForCallNew( |
| 8818 CallNew* expr, |
| 8819 HAllocationMode* mode) { |
| 8820 if (FLAG_pretenuring_call_new) { |
| 8821 if (FLAG_allocation_site_pretenuring) { |
| 8822 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 8823 HConstant* site_constant = NULL; |
| 8824 // By passing a non-null HConstant AllocationSite to HAllocationMode, |
| 8825 // we ensure that a memento will be emitted. |
| 8826 if (allocation_site->emit_mementos()) { |
| 8827 site_constant = Add<HConstant>(allocation_site); |
| 8828 } |
| 8829 // Try to use pretenuring feedback. |
| 8830 *mode = HAllocationMode(allocation_site, site_constant); |
| 8831 // Take a dependency on allocation site. |
| 8832 AllocationSite::AddDependentCompilationInfo(allocation_site, |
| 8833 AllocationSite::TENURING, |
| 8834 top_info()); |
| 8835 } |
| 8836 } |
| 8837 // No else case, the mode will be left at it's default. |
| 8838 } |
| 8839 |
| 8840 |
| 8799 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 8841 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 8800 ASSERT(!HasStackOverflow()); | 8842 ASSERT(!HasStackOverflow()); |
| 8801 ASSERT(current_block() != NULL); | 8843 ASSERT(current_block() != NULL); |
| 8802 ASSERT(current_block()->HasPredecessor()); | 8844 ASSERT(current_block()->HasPredecessor()); |
| 8803 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); | 8845 if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position()); |
| 8804 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 8846 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 8805 Factory* factory = isolate()->factory(); | 8847 Factory* factory = isolate()->factory(); |
| 8806 | 8848 |
| 8807 // The constructor function is on the stack in the unoptimized code | 8849 // The constructor function is on the stack in the unoptimized code |
| 8808 // during evaluation of the arguments. | 8850 // during evaluation of the arguments. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 8824 | 8866 |
| 8825 // Calculate instance size from initial map of constructor. | 8867 // Calculate instance size from initial map of constructor. |
| 8826 ASSERT(constructor->has_initial_map()); | 8868 ASSERT(constructor->has_initial_map()); |
| 8827 Handle<Map> initial_map(constructor->initial_map()); | 8869 Handle<Map> initial_map(constructor->initial_map()); |
| 8828 int instance_size = initial_map->instance_size(); | 8870 int instance_size = initial_map->instance_size(); |
| 8829 ASSERT(initial_map->InitialPropertiesLength() == 0); | 8871 ASSERT(initial_map->InitialPropertiesLength() == 0); |
| 8830 | 8872 |
| 8831 // Allocate an instance of the implicit receiver object. | 8873 // Allocate an instance of the implicit receiver object. |
| 8832 HValue* size_in_bytes = Add<HConstant>(instance_size); | 8874 HValue* size_in_bytes = Add<HConstant>(instance_size); |
| 8833 HAllocationMode allocation_mode; | 8875 HAllocationMode allocation_mode; |
| 8834 if (FLAG_pretenuring_call_new) { | 8876 InitializeAllocationModeForCallNew(expr, &allocation_mode); |
| 8835 if (FLAG_allocation_site_pretenuring) { | |
| 8836 // Try to use pretenuring feedback. | |
| 8837 Handle<AllocationSite> allocation_site = expr->allocation_site(); | |
| 8838 allocation_mode = HAllocationMode(allocation_site); | |
| 8839 // Take a dependency on allocation site. | |
| 8840 AllocationSite::AddDependentCompilationInfo(allocation_site, | |
| 8841 AllocationSite::TENURING, | |
| 8842 top_info()); | |
| 8843 } | |
| 8844 } | |
| 8845 | 8877 |
| 8846 HAllocate* receiver = BuildAllocate( | 8878 HAllocate* receiver = BuildAllocate( |
| 8847 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); | 8879 size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode); |
| 8848 receiver->set_known_initial_map(initial_map); | 8880 receiver->set_known_initial_map(initial_map); |
| 8849 | 8881 |
| 8850 // Initialize map and fields of the newly allocated object. | 8882 // Initialize map and fields of the newly allocated object. |
| 8851 { NoObservableSideEffectsScope no_effects(this); | 8883 { NoObservableSideEffectsScope no_effects(this); |
| 8852 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | 8884 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
| 8853 Add<HStoreNamedField>(receiver, | 8885 Add<HStoreNamedField>(receiver, |
| 8854 HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset), | 8886 HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8886 Map::AddDependentCompilationInfo( | 8918 Map::AddDependentCompilationInfo( |
| 8887 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); | 8919 initial_map, DependentCode::kInitialMapChangedGroup, top_info()); |
| 8888 return; | 8920 return; |
| 8889 } | 8921 } |
| 8890 | 8922 |
| 8891 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 8923 // TODO(mstarzinger): For now we remove the previous HAllocate and all |
| 8892 // corresponding instructions and instead add HPushArguments for the | 8924 // corresponding instructions and instead add HPushArguments for the |
| 8893 // arguments in case inlining failed. What we actually should do is for | 8925 // arguments in case inlining failed. What we actually should do is for |
| 8894 // inlining to try to build a subgraph without mutating the parent graph. | 8926 // inlining to try to build a subgraph without mutating the parent graph. |
| 8895 HInstruction* instr = current_block()->last(); | 8927 HInstruction* instr = current_block()->last(); |
| 8896 do { | 8928 |
| 8929 // If we decided to emit a memento for this allocation, we need to |
| 8930 // remember the instruction of the HConstant for the site added |
| 8931 // in InitializeAllocationModeForCallNew(). |
| 8932 HValue* delete_to_this_instruction = |
| 8933 allocation_mode.CreateAllocationMementos() |
| 8934 ? allocation_mode.current_site() |
| 8935 : receiver; |
| 8936 ASSERT(delete_to_this_instruction != NULL); |
| 8937 while (instr != delete_to_this_instruction) { |
| 8897 HInstruction* prev_instr = instr->previous(); | 8938 HInstruction* prev_instr = instr->previous(); |
| 8898 instr->DeleteAndReplaceWith(NULL); | 8939 instr->DeleteAndReplaceWith(NULL); |
| 8899 instr = prev_instr; | 8940 instr = prev_instr; |
| 8900 } while (instr != check); | 8941 } |
| 8942 // initial_map_value->DeleteAndReplaceWith(NULL); |
| 8943 if (delete_to_this_instruction == receiver) { |
| 8944 receiver->DeleteAndReplaceWith(NULL); |
| 8945 } |
| 8946 check->DeleteAndReplaceWith(NULL); |
| 8901 environment()->SetExpressionStackAt(receiver_index, function); | 8947 environment()->SetExpressionStackAt(receiver_index, function); |
| 8902 HInstruction* call = | 8948 HInstruction* call = PreProcessCall( |
| 8903 PreProcessCall(New<HCallNew>(function, argument_count)); | 8949 New<HCallNew>(function, argument_count, allocation_mode)); |
| 8904 return ast_context()->ReturnInstruction(call, expr->id()); | 8950 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8905 } else { | 8951 } else { |
| 8952 HAllocationMode allocation_mode; |
| 8953 InitializeAllocationModeForCallNew(expr, &allocation_mode); |
| 8954 |
| 8906 // The constructor function is both an operand to the instruction and an | 8955 // The constructor function is both an operand to the instruction and an |
| 8907 // argument to the construct call. | 8956 // argument to the construct call. |
| 8908 if (TryHandleArrayCallNew(expr, function)) return; | 8957 if (TryHandleArrayCallNew(expr, function, allocation_mode)) return; |
| 8909 | 8958 |
| 8910 HInstruction* call = | 8959 HInstruction* call = |
| 8911 PreProcessCall(New<HCallNew>(function, argument_count)); | 8960 PreProcessCall(New<HCallNew>(function, argument_count, |
| 8961 allocation_mode)); |
| 8912 return ast_context()->ReturnInstruction(call, expr->id()); | 8962 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8913 } | 8963 } |
| 8914 } | 8964 } |
| 8915 | 8965 |
| 8916 | 8966 |
| 8917 // Support for generating inlined runtime functions. | 8967 // Support for generating inlined runtime functions. |
| 8918 | 8968 |
| 8919 // Lookup table for generators for runtime calls that are generated inline. | 8969 // Lookup table for generators for runtime calls that are generated inline. |
| 8920 // Elements of the table are member pointers to functions of | 8970 // Elements of the table are member pointers to functions of |
| 8921 // HOptimizedGraphBuilder. | 8971 // HOptimizedGraphBuilder. |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9767 Type* right_type = expr->right()->bounds().lower; | 9817 Type* right_type = expr->right()->bounds().lower; |
| 9768 Type* result_type = expr->bounds().lower; | 9818 Type* result_type = expr->bounds().lower; |
| 9769 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 9819 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 9770 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 9820 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 9771 | 9821 |
| 9772 HAllocationMode allocation_mode; | 9822 HAllocationMode allocation_mode; |
| 9773 if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) { | 9823 if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) { |
| 9774 allocation_mode = HAllocationMode(allocation_site); | 9824 allocation_mode = HAllocationMode(allocation_site); |
| 9775 } | 9825 } |
| 9776 | 9826 |
| 9827 if (FLAG_allocation_site_pretenuring && |
| 9828 !allocation_site.is_null() && |
| 9829 allocation_site->emit_mementos()) { |
| 9830 // This allows crankshaft to continue emitting mementos if a pretenuring |
| 9831 // decision wasn't made yet. A dependency is registered on the site in |
| 9832 // the BuildBinaryOperation call below. |
| 9833 HConstant* site_constant = Add<HConstant>(allocation_site); |
| 9834 allocation_mode = HAllocationMode(allocation_site, site_constant); |
| 9835 } |
| 9836 |
| 9777 HValue* result = HGraphBuilder::BuildBinaryOperation( | 9837 HValue* result = HGraphBuilder::BuildBinaryOperation( |
| 9778 expr->op(), left, right, left_type, right_type, result_type, | 9838 expr->op(), left, right, left_type, right_type, result_type, |
| 9779 fixed_right_arg, allocation_mode); | 9839 fixed_right_arg, allocation_mode); |
| 9780 // Add a simulate after instructions with observable side effects, and | 9840 // Add a simulate after instructions with observable side effects, and |
| 9781 // after phis, which are the result of BuildBinaryOperation when we | 9841 // after phis, which are the result of BuildBinaryOperation when we |
| 9782 // inlined some complex subgraph. | 9842 // inlined some complex subgraph. |
| 9783 if (result->HasObservableSideEffects() || result->IsPhi()) { | 9843 if (result->HasObservableSideEffects() || result->IsPhi()) { |
| 9784 if (push_sim_result == PUSH_BEFORE_SIMULATE) { | 9844 if (push_sim_result == PUSH_BEFORE_SIMULATE) { |
| 9785 Push(result); | 9845 Push(result); |
| 9786 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 9846 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| (...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10469 | 10529 |
| 10470 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 10530 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 10471 Handle<JSObject> boilerplate_object, | 10531 Handle<JSObject> boilerplate_object, |
| 10472 AllocationSiteUsageContext* site_context) { | 10532 AllocationSiteUsageContext* site_context) { |
| 10473 NoObservableSideEffectsScope no_effects(this); | 10533 NoObservableSideEffectsScope no_effects(this); |
| 10474 InstanceType instance_type = boilerplate_object->map()->instance_type(); | 10534 InstanceType instance_type = boilerplate_object->map()->instance_type(); |
| 10475 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); | 10535 ASSERT(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE); |
| 10476 | 10536 |
| 10477 HType type = instance_type == JS_ARRAY_TYPE | 10537 HType type = instance_type == JS_ARRAY_TYPE |
| 10478 ? HType::JSArray() : HType::JSObject(); | 10538 ? HType::JSArray() : HType::JSObject(); |
| 10479 HValue* object_size_constant = Add<HConstant>( | 10539 int instance_size = boilerplate_object->map()->instance_size(); |
| 10480 boilerplate_object->map()->instance_size()); | 10540 bool emit_memento = site_context->ShouldCreateMemento(boilerplate_object); |
| 10541 // Should the object allocation include a manually folded memento? |
| 10542 int alloc_size = emit_memento |
| 10543 ? instance_size + AllocationMemento::kSize |
| 10544 : instance_size; |
| 10545 HValue* alloc_size_constant = Add<HConstant>(alloc_size); |
| 10546 HValue* allocation_site_constant = Add<HConstant>(site_context->current()); |
| 10481 | 10547 |
| 10482 PretenureFlag pretenure_flag = NOT_TENURED; | 10548 PretenureFlag pretenure_flag = NOT_TENURED; |
| 10483 if (FLAG_allocation_site_pretenuring) { | 10549 if (FLAG_allocation_site_pretenuring) { |
| 10484 pretenure_flag = site_context->current()->GetPretenureMode(); | 10550 pretenure_flag = site_context->current()->GetPretenureMode(); |
| 10485 Handle<AllocationSite> site(site_context->current()); | 10551 Handle<AllocationSite> site(site_context->current()); |
| 10486 AllocationSite::AddDependentCompilationInfo( | 10552 AllocationSite::AddDependentCompilationInfo( |
| 10487 site, AllocationSite::TENURING, top_info()); | 10553 site, AllocationSite::TENURING, top_info()); |
| 10488 } | 10554 } |
| 10489 | 10555 |
| 10490 HInstruction* object = Add<HAllocate>(object_size_constant, type, | 10556 HInstruction* object = Add<HAllocate>(alloc_size_constant, type, |
| 10491 pretenure_flag, instance_type, site_context->current()); | 10557 pretenure_flag, instance_type, site_context->current()); |
| 10492 | 10558 |
| 10493 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the | 10559 // If allocation folding reaches Page::kMaxRegularHeapObjectSize the |
| 10494 // elements array may not get folded into the object. Hence, we set the | 10560 // elements array may not get folded into the object. Hence, we set the |
| 10495 // elements pointer to empty fixed array and let store elimination remove | 10561 // elements pointer to empty fixed array and let store elimination remove |
| 10496 // this store in the folding case. | 10562 // this store in the folding case. |
| 10497 HConstant* empty_fixed_array = Add<HConstant>( | 10563 HConstant* empty_fixed_array = Add<HConstant>( |
| 10498 isolate()->factory()->empty_fixed_array()); | 10564 isolate()->factory()->empty_fixed_array()); |
| 10499 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), | 10565 Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(), |
| 10500 empty_fixed_array); | 10566 empty_fixed_array); |
| 10501 | 10567 |
| 10502 BuildEmitObjectHeader(boilerplate_object, object); | 10568 BuildEmitObjectHeader(boilerplate_object, object); |
| 10569 if (emit_memento) { |
| 10570 BuildCreateAllocationMemento(object, |
| 10571 Add<HConstant>(instance_size), |
| 10572 allocation_site_constant); |
| 10573 } |
| 10503 | 10574 |
| 10504 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 10575 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 10505 int elements_size = (elements->length() > 0 && | 10576 int elements_size = (elements->length() > 0 && |
| 10506 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 10577 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 10507 elements->Size() : 0; | 10578 elements->Size() : 0; |
| 10508 | 10579 |
| 10509 if (pretenure_flag == TENURED && | 10580 if (pretenure_flag == TENURED && |
| 10510 elements->map() == isolate()->heap()->fixed_cow_array_map() && | 10581 elements->map() == isolate()->heap()->fixed_cow_array_map() && |
| 10511 isolate()->heap()->InNewSpace(*elements)) { | 10582 isolate()->heap()->InNewSpace(*elements)) { |
| 10512 // If we would like to pretenure a fixed cow array, we must ensure that the | 10583 // If we would like to pretenure a fixed cow array, we must ensure that the |
| (...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12038 if (ShouldProduceTraceOutput()) { | 12109 if (ShouldProduceTraceOutput()) { |
| 12039 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12110 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 12040 } | 12111 } |
| 12041 | 12112 |
| 12042 #ifdef DEBUG | 12113 #ifdef DEBUG |
| 12043 graph_->Verify(false); // No full verify. | 12114 graph_->Verify(false); // No full verify. |
| 12044 #endif | 12115 #endif |
| 12045 } | 12116 } |
| 12046 | 12117 |
| 12047 } } // namespace v8::internal | 12118 } } // namespace v8::internal |
| OLD | NEW |