| 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 8814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8825 | 8825 |
| 8826 call->set_position(expr->position()); | 8826 call->set_position(expr->position()); |
| 8827 return ast_context()->ReturnInstruction(call, expr->id()); | 8827 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8828 } | 8828 } |
| 8829 | 8829 |
| 8830 | 8830 |
| 8831 // Checks whether allocation using the given constructor can be inlined. | 8831 // Checks whether allocation using the given constructor can be inlined. |
| 8832 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 8832 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| 8833 return constructor->has_initial_map() && | 8833 return constructor->has_initial_map() && |
| 8834 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 8834 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
| 8835 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 8835 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
| 8836 constructor->initial_map()->InitialPropertiesLength() == 0; | |
| 8837 } | 8836 } |
| 8838 | 8837 |
| 8839 | 8838 |
| 8840 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 8839 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 8841 ASSERT(!HasStackOverflow()); | 8840 ASSERT(!HasStackOverflow()); |
| 8842 ASSERT(current_block() != NULL); | 8841 ASSERT(current_block() != NULL); |
| 8843 ASSERT(current_block()->HasPredecessor()); | 8842 ASSERT(current_block()->HasPredecessor()); |
| 8844 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 8843 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 8845 HValue* context = environment()->LookupContext(); | 8844 HValue* context = environment()->LookupContext(); |
| 8846 Factory* factory = isolate()->factory(); | |
| 8847 | 8845 |
| 8848 if (FLAG_inline_construct && | 8846 if (FLAG_inline_construct && |
| 8849 expr->IsMonomorphic() && | 8847 expr->IsMonomorphic() && |
| 8850 IsAllocationInlineable(expr->target())) { | 8848 IsAllocationInlineable(expr->target())) { |
| 8851 // The constructor function is on the stack in the unoptimized code | 8849 // The constructor function is on the stack in the unoptimized code |
| 8852 // during evaluation of the arguments. | 8850 // during evaluation of the arguments. |
| 8853 CHECK_ALIVE(VisitForValue(expr->expression())); | 8851 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8854 HValue* function = Top(); | 8852 HValue* function = Top(); |
| 8855 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8853 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8856 Handle<JSFunction> constructor = expr->target(); | 8854 Handle<JSFunction> constructor = expr->target(); |
| 8857 HValue* check = AddInstruction( | 8855 HValue* check = AddInstruction( |
| 8858 new(zone()) HCheckFunction(function, constructor)); | 8856 new(zone()) HCheckFunction(function, constructor)); |
| 8859 | 8857 |
| 8860 // Force completion of inobject slack tracking before generating | 8858 // Force completion of inobject slack tracking before generating |
| 8861 // allocation code to finalize instance size. | 8859 // allocation code to finalize instance size. |
| 8862 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { | 8860 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { |
| 8863 constructor->shared()->CompleteInobjectSlackTracking(); | 8861 constructor->shared()->CompleteInobjectSlackTracking(); |
| 8864 } | 8862 } |
| 8865 | 8863 |
| 8866 // Calculate instance size from initial map of constructor. | 8864 // Replace the constructor function with a newly allocated receiver. |
| 8867 ASSERT(constructor->has_initial_map()); | 8865 HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); |
| 8868 Handle<Map> initial_map(constructor->initial_map()); | 8866 // Index of the receiver from the top of the expression stack. |
| 8869 int instance_size = initial_map->instance_size(); | |
| 8870 ASSERT(initial_map->InitialPropertiesLength() == 0); | |
| 8871 | |
| 8872 // Allocate an instance of the implicit receiver object. | |
| 8873 HValue* size_in_bytes = | |
| 8874 AddInstruction(new(zone()) HConstant(instance_size)); | |
| 8875 | |
| 8876 HAllocate::Flags flags = HAllocate::DefaultFlags(); | |
| 8877 if (FLAG_pretenuring_call_new && | |
| 8878 isolate()->heap()->ShouldGloballyPretenure()) { | |
| 8879 flags = static_cast<HAllocate::Flags>( | |
| 8880 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | |
| 8881 } | |
| 8882 | |
| 8883 HInstruction* receiver = | |
| 8884 AddInstruction(new(zone()) HAllocate(context, | |
| 8885 size_in_bytes, | |
| 8886 HType::JSObject(), | |
| 8887 flags)); | |
| 8888 HAllocate::cast(receiver)->set_known_initial_map(initial_map); | |
| 8889 | |
| 8890 // Load the initial map from the constructor. | |
| 8891 HValue* constructor_value = | |
| 8892 AddInstruction(new(zone()) HConstant(constructor)); | |
| 8893 HValue* initial_map_value = | |
| 8894 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( | |
| 8895 JSFunction::kPrototypeOrInitialMapOffset)); | |
| 8896 | |
| 8897 // Initialize map and fields of the newly allocated object. | |
| 8898 { NoObservableSideEffectsScope no_effects(this); | |
| 8899 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | |
| 8900 AddStore(receiver, | |
| 8901 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | |
| 8902 initial_map_value); | |
| 8903 HValue* empty_fixed_array = | |
| 8904 AddInstruction(new(zone()) HConstant(factory->empty_fixed_array())); | |
| 8905 AddStore(receiver, | |
| 8906 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | |
| 8907 empty_fixed_array); | |
| 8908 AddStore(receiver, | |
| 8909 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | |
| 8910 empty_fixed_array); | |
| 8911 if (initial_map->inobject_properties() != 0) { | |
| 8912 HConstant* undefined = graph()->GetConstantUndefined(); | |
| 8913 for (int i = 0; i < initial_map->inobject_properties(); i++) { | |
| 8914 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | |
| 8915 AddStore(receiver, | |
| 8916 HObjectAccess::ForJSObjectOffset(property_offset), | |
| 8917 undefined); | |
| 8918 } | |
| 8919 } | |
| 8920 } | |
| 8921 | |
| 8922 // Replace the constructor function with a newly allocated receiver using | |
| 8923 // the index of the receiver from the top of the expression stack. | |
| 8924 const int receiver_index = argument_count - 1; | 8867 const int receiver_index = argument_count - 1; |
| 8868 AddInstruction(receiver); |
| 8925 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 8869 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
| 8926 environment()->SetExpressionStackAt(receiver_index, receiver); | 8870 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8927 | 8871 |
| 8928 if (TryInlineConstruct(expr, receiver)) return; | 8872 if (TryInlineConstruct(expr, receiver)) return; |
| 8929 | 8873 |
| 8930 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 8874 // TODO(mstarzinger): For now we remove the previous HAllocateObject and |
| 8931 // corresponding instructions and instead add HPushArgument for the | 8875 // add HPushArgument for the arguments in case inlining failed. What we |
| 8932 // arguments in case inlining failed. What we actually should do is for | 8876 // actually should do is emit HInvokeFunction on the constructor instead |
| 8933 // inlining to try to build a subgraph without mutating the parent graph. | 8877 // of using HCallNew as a fallback. |
| 8934 HInstruction* instr = current_block()->last(); | |
| 8935 while (instr != initial_map_value) { | |
| 8936 HInstruction* prev_instr = instr->previous(); | |
| 8937 instr->DeleteAndReplaceWith(NULL); | |
| 8938 instr = prev_instr; | |
| 8939 } | |
| 8940 initial_map_value->DeleteAndReplaceWith(NULL); | |
| 8941 receiver->DeleteAndReplaceWith(NULL); | 8878 receiver->DeleteAndReplaceWith(NULL); |
| 8942 check->DeleteAndReplaceWith(NULL); | 8879 check->DeleteAndReplaceWith(NULL); |
| 8943 environment()->SetExpressionStackAt(receiver_index, function); | 8880 environment()->SetExpressionStackAt(receiver_index, function); |
| 8944 HInstruction* call = PreProcessCall( | 8881 HInstruction* call = PreProcessCall( |
| 8945 new(zone()) HCallNew(context, function, argument_count)); | 8882 new(zone()) HCallNew(context, function, argument_count)); |
| 8946 call->set_position(expr->position()); | 8883 call->set_position(expr->position()); |
| 8947 return ast_context()->ReturnInstruction(call, expr->id()); | 8884 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8948 } else { | 8885 } else { |
| 8949 // The constructor function is both an operand to the instruction and an | 8886 // The constructor function is both an operand to the instruction and an |
| 8950 // argument to the construct call. | 8887 // argument to the construct call. |
| (...skipping 2701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11652 } | 11589 } |
| 11653 } | 11590 } |
| 11654 | 11591 |
| 11655 #ifdef DEBUG | 11592 #ifdef DEBUG |
| 11656 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11593 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11657 if (allocator_ != NULL) allocator_->Verify(); | 11594 if (allocator_ != NULL) allocator_->Verify(); |
| 11658 #endif | 11595 #endif |
| 11659 } | 11596 } |
| 11660 | 11597 |
| 11661 } } // namespace v8::internal | 11598 } } // namespace v8::internal |
| OLD | NEW |