Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 8740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8751 | 8751 |
| 8752 call->set_position(expr->position()); | 8752 call->set_position(expr->position()); |
| 8753 return ast_context()->ReturnInstruction(call, expr->id()); | 8753 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8754 } | 8754 } |
| 8755 | 8755 |
| 8756 | 8756 |
| 8757 // Checks whether allocation using the given constructor can be inlined. | 8757 // Checks whether allocation using the given constructor can be inlined. |
| 8758 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 8758 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| 8759 return constructor->has_initial_map() && | 8759 return constructor->has_initial_map() && |
| 8760 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 8760 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
| 8761 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 8761 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
| 8762 constructor->initial_map()->InitialPropertiesLength() == 0; | |
| 8762 } | 8763 } |
| 8763 | 8764 |
| 8764 | 8765 |
| 8765 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 8766 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 8766 ASSERT(!HasStackOverflow()); | 8767 ASSERT(!HasStackOverflow()); |
| 8767 ASSERT(current_block() != NULL); | 8768 ASSERT(current_block() != NULL); |
| 8768 ASSERT(current_block()->HasPredecessor()); | 8769 ASSERT(current_block()->HasPredecessor()); |
| 8769 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 8770 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 8770 HValue* context = environment()->LookupContext(); | 8771 HValue* context = environment()->LookupContext(); |
| 8772 Factory* factory = isolate()->factory(); | |
| 8771 | 8773 |
| 8772 if (FLAG_inline_construct && | 8774 if (FLAG_inline_construct && |
| 8773 expr->IsMonomorphic() && | 8775 expr->IsMonomorphic() && |
| 8774 IsAllocationInlineable(expr->target())) { | 8776 IsAllocationInlineable(expr->target())) { |
| 8775 // The constructor function is on the stack in the unoptimized code | 8777 // The constructor function is on the stack in the unoptimized code |
| 8776 // during evaluation of the arguments. | 8778 // during evaluation of the arguments. |
| 8777 CHECK_ALIVE(VisitForValue(expr->expression())); | 8779 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8778 HValue* function = Top(); | 8780 HValue* function = Top(); |
| 8779 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8781 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8780 Handle<JSFunction> constructor = expr->target(); | 8782 Handle<JSFunction> constructor = expr->target(); |
| 8781 HValue* check = AddInstruction( | 8783 HValue* check = AddInstruction( |
| 8782 new(zone()) HCheckFunction(function, constructor)); | 8784 new(zone()) HCheckFunction(function, constructor)); |
| 8783 | 8785 |
| 8784 // Force completion of inobject slack tracking before generating | 8786 // Force completion of inobject slack tracking before generating |
| 8785 // allocation code to finalize instance size. | 8787 // allocation code to finalize instance size. |
| 8786 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { | 8788 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { |
| 8787 constructor->shared()->CompleteInobjectSlackTracking(); | 8789 constructor->shared()->CompleteInobjectSlackTracking(); |
| 8788 } | 8790 } |
| 8789 | 8791 |
| 8790 // Replace the constructor function with a newly allocated receiver. | 8792 // Calculate instance size from initial map of constructor. |
| 8791 HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); | 8793 ASSERT(constructor->has_initial_map()); |
| 8792 // Index of the receiver from the top of the expression stack. | 8794 Handle<Map> initial_map(constructor->initial_map()); |
| 8795 int instance_size = initial_map->instance_size(); | |
| 8796 ASSERT(initial_map->InitialPropertiesLength() == 0); | |
| 8797 | |
| 8798 // Allocate an instance of the implicit receiver object. | |
| 8799 HValue* size_in_bytes = | |
| 8800 AddInstruction(new(zone()) HConstant(instance_size, | |
| 8801 Representation::Integer32())); | |
| 8802 HInstruction* receiver = | |
| 8803 AddInstruction(new(zone()) HAllocate(context, | |
| 8804 size_in_bytes, | |
| 8805 HType::JSObject(), | |
| 8806 HAllocate::DefaultFlags())); | |
| 8807 HAllocate::cast(receiver)->set_known_initial_map(initial_map); | |
| 8808 | |
| 8809 // Load the initial map from the constructor. | |
| 8810 HValue* constructor_value = | |
| 8811 AddInstruction(new(zone()) HConstant(constructor, | |
| 8812 Representation::Tagged())); | |
| 8813 HValue* initial_map_value = | |
| 8814 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( | |
| 8815 JSFunction::kPrototypeOrInitialMapOffset)); | |
| 8816 | |
| 8817 // Initialize map and fields of the newly allocated object. | |
| 8818 { NoObservableSideEffectsScope no_effects(this); | |
| 8819 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | |
| 8820 AddStore(receiver, | |
| 8821 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | |
| 8822 initial_map_value); | |
| 8823 HValue* empty_fixed_array = | |
| 8824 AddInstruction(new(zone()) HConstant(factory->empty_fixed_array(), | |
| 8825 Representation::Tagged())); | |
| 8826 AddStore(receiver, | |
| 8827 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | |
| 8828 empty_fixed_array); | |
| 8829 AddStore(receiver, | |
| 8830 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | |
| 8831 empty_fixed_array); | |
| 8832 if (initial_map->inobject_properties() != 0) { | |
| 8833 HConstant* undefined = graph()->GetConstantUndefined(); | |
| 8834 for (int i = 0; i < initial_map->inobject_properties(); i++) { | |
| 8835 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | |
| 8836 AddStore(receiver, | |
| 8837 HObjectAccess::ForJSObjectOffset(property_offset), | |
| 8838 undefined); | |
| 8839 } | |
| 8840 } | |
| 8841 } | |
| 8842 | |
| 8843 // Replace the constructor function with a newly allocated receiver using | |
| 8844 // the index of the receiver from the top of the expression stack. | |
| 8793 const int receiver_index = argument_count - 1; | 8845 const int receiver_index = argument_count - 1; |
| 8794 AddInstruction(receiver); | |
| 8795 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 8846 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
| 8796 environment()->SetExpressionStackAt(receiver_index, receiver); | 8847 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8797 | 8848 |
| 8798 if (TryInlineConstruct(expr, receiver)) return; | 8849 if (TryInlineConstruct(expr, receiver)) return; |
| 8799 | 8850 |
| 8800 // TODO(mstarzinger): For now we remove the previous HAllocateObject and | 8851 // TODO(mstarzinger): For now we remove the previous HAllocate and instead |
| 8801 // add HPushArgument for the arguments in case inlining failed. What we | 8852 // add HPushArgument for the arguments in case inlining failed. What we |
| 8802 // actually should do is emit HInvokeFunction on the constructor instead | 8853 // actually should do is emit HInvokeFunction on the constructor instead |
| 8803 // of using HCallNew as a fallback. | 8854 // of using HCallNew as a fallback. |
| 8855 HInstruction* instr = current_block()->last(); | |
| 8856 while (instr != initial_map_value) { | |
| 8857 HInstruction* prev_instr = instr->previous(); | |
| 8858 instr->DeleteAndReplaceWith(NULL); | |
| 8859 instr = prev_instr; | |
| 8860 } | |
| 8861 initial_map_value->DeleteAndReplaceWith(NULL); | |
|
Hannes Payer (out of office)
2013/06/04 07:44:19
Should we create a separate function for that piec
Michael Starzinger
2013/06/04 08:17:33
As discussed offline: We decided not to provide a
| |
| 8804 receiver->DeleteAndReplaceWith(NULL); | 8862 receiver->DeleteAndReplaceWith(NULL); |
| 8805 check->DeleteAndReplaceWith(NULL); | 8863 check->DeleteAndReplaceWith(NULL); |
| 8806 environment()->SetExpressionStackAt(receiver_index, function); | 8864 environment()->SetExpressionStackAt(receiver_index, function); |
| 8807 HInstruction* call = PreProcessCall( | 8865 HInstruction* call = PreProcessCall( |
| 8808 new(zone()) HCallNew(context, function, argument_count)); | 8866 new(zone()) HCallNew(context, function, argument_count)); |
| 8809 call->set_position(expr->position()); | 8867 call->set_position(expr->position()); |
| 8810 return ast_context()->ReturnInstruction(call, expr->id()); | 8868 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8811 } else { | 8869 } else { |
| 8812 // The constructor function is both an operand to the instruction and an | 8870 // The constructor function is both an operand to the instruction and an |
| 8813 // argument to the construct call. | 8871 // argument to the construct call. |
| (...skipping 2684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11498 } | 11556 } |
| 11499 } | 11557 } |
| 11500 | 11558 |
| 11501 #ifdef DEBUG | 11559 #ifdef DEBUG |
| 11502 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11560 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11503 if (allocator_ != NULL) allocator_->Verify(); | 11561 if (allocator_ != NULL) allocator_->Verify(); |
| 11504 #endif | 11562 #endif |
| 11505 } | 11563 } |
| 11506 | 11564 |
| 11507 } } // namespace v8::internal | 11565 } } // namespace v8::internal |
| OLD | NEW |