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 |