OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 7239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7250 | 7250 |
7251 call->set_position(expr->position()); | 7251 call->set_position(expr->position()); |
7252 return ast_context()->ReturnInstruction(call, expr->id()); | 7252 return ast_context()->ReturnInstruction(call, expr->id()); |
7253 } | 7253 } |
7254 | 7254 |
7255 | 7255 |
7256 // Checks whether allocation using the given constructor can be inlined. | 7256 // Checks whether allocation using the given constructor can be inlined. |
7257 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 7257 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
7258 return constructor->has_initial_map() && | 7258 return constructor->has_initial_map() && |
7259 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 7259 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
7260 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; | 7260 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && |
| 7261 constructor->initial_map()->InitialPropertiesLength() == 0; |
7261 } | 7262 } |
7262 | 7263 |
7263 | 7264 |
7264 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 7265 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
7265 ASSERT(!HasStackOverflow()); | 7266 ASSERT(!HasStackOverflow()); |
7266 ASSERT(current_block() != NULL); | 7267 ASSERT(current_block() != NULL); |
7267 ASSERT(current_block()->HasPredecessor()); | 7268 ASSERT(current_block()->HasPredecessor()); |
7268 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 7269 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
7269 HValue* context = environment()->LookupContext(); | 7270 HValue* context = environment()->LookupContext(); |
| 7271 Factory* factory = isolate()->factory(); |
7270 | 7272 |
7271 if (FLAG_inline_construct && | 7273 if (FLAG_inline_construct && |
7272 expr->IsMonomorphic() && | 7274 expr->IsMonomorphic() && |
7273 IsAllocationInlineable(expr->target())) { | 7275 IsAllocationInlineable(expr->target())) { |
7274 // The constructor function is on the stack in the unoptimized code | 7276 // The constructor function is on the stack in the unoptimized code |
7275 // during evaluation of the arguments. | 7277 // during evaluation of the arguments. |
7276 CHECK_ALIVE(VisitForValue(expr->expression())); | 7278 CHECK_ALIVE(VisitForValue(expr->expression())); |
7277 HValue* function = Top(); | 7279 HValue* function = Top(); |
7278 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7280 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7279 Handle<JSFunction> constructor = expr->target(); | 7281 Handle<JSFunction> constructor = expr->target(); |
7280 HValue* check = Add<HCheckFunction>(function, constructor); | 7282 HValue* check = Add<HCheckFunction>(function, constructor); |
7281 | 7283 |
7282 // Force completion of inobject slack tracking before generating | 7284 // Force completion of inobject slack tracking before generating |
7283 // allocation code to finalize instance size. | 7285 // allocation code to finalize instance size. |
7284 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { | 7286 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { |
7285 constructor->shared()->CompleteInobjectSlackTracking(); | 7287 constructor->shared()->CompleteInobjectSlackTracking(); |
7286 } | 7288 } |
7287 | 7289 |
7288 // Replace the constructor function with a newly allocated receiver. | 7290 // Calculate instance size from initial map of constructor. |
7289 HInstruction* receiver = Add<HAllocateObject>(context, constructor); | 7291 ASSERT(constructor->has_initial_map()); |
7290 // Index of the receiver from the top of the expression stack. | 7292 Handle<Map> initial_map(constructor->initial_map()); |
| 7293 int instance_size = initial_map->instance_size(); |
| 7294 ASSERT(initial_map->InitialPropertiesLength() == 0); |
| 7295 |
| 7296 // Allocate an instance of the implicit receiver object. |
| 7297 HValue* size_in_bytes = Add<HConstant>(instance_size); |
| 7298 HAllocate::Flags flags = HAllocate::DefaultFlags(); |
| 7299 if (FLAG_pretenuring_call_new && |
| 7300 isolate()->heap()->ShouldGloballyPretenure()) { |
| 7301 flags = static_cast<HAllocate::Flags>( |
| 7302 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 7303 } |
| 7304 HAllocate* receiver = |
| 7305 Add<HAllocate>(context, size_in_bytes, HType::JSObject(), flags); |
| 7306 receiver->set_known_initial_map(initial_map); |
| 7307 |
| 7308 // Load the initial map from the constructor. |
| 7309 HValue* constructor_value = Add<HConstant>(constructor); |
| 7310 HValue* initial_map_value = |
| 7311 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( |
| 7312 JSFunction::kPrototypeOrInitialMapOffset)); |
| 7313 |
| 7314 // Initialize map and fields of the newly allocated object. |
| 7315 { NoObservableSideEffectsScope no_effects(this); |
| 7316 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); |
| 7317 AddStore(receiver, |
| 7318 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), |
| 7319 initial_map_value); |
| 7320 HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array()); |
| 7321 AddStore(receiver, |
| 7322 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), |
| 7323 empty_fixed_array); |
| 7324 AddStore(receiver, |
| 7325 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), |
| 7326 empty_fixed_array); |
| 7327 if (initial_map->inobject_properties() != 0) { |
| 7328 HConstant* undefined = graph()->GetConstantUndefined(); |
| 7329 for (int i = 0; i < initial_map->inobject_properties(); i++) { |
| 7330 int property_offset = JSObject::kHeaderSize + i * kPointerSize; |
| 7331 AddStore(receiver, |
| 7332 HObjectAccess::ForJSObjectOffset(property_offset), |
| 7333 undefined); |
| 7334 } |
| 7335 } |
| 7336 } |
| 7337 |
| 7338 // Replace the constructor function with a newly allocated receiver using |
| 7339 // the index of the receiver from the top of the expression stack. |
7291 const int receiver_index = argument_count - 1; | 7340 const int receiver_index = argument_count - 1; |
7292 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 7341 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
7293 environment()->SetExpressionStackAt(receiver_index, receiver); | 7342 environment()->SetExpressionStackAt(receiver_index, receiver); |
7294 | 7343 |
7295 if (TryInlineConstruct(expr, receiver)) return; | 7344 if (TryInlineConstruct(expr, receiver)) return; |
7296 | 7345 |
7297 // TODO(mstarzinger): For now we remove the previous HAllocateObject and | 7346 // TODO(mstarzinger): For now we remove the previous HAllocate and all |
7298 // add HPushArgument for the arguments in case inlining failed. What we | 7347 // corresponding instructions and instead add HPushArgument for the |
7299 // actually should do is emit HInvokeFunction on the constructor instead | 7348 // arguments in case inlining failed. What we actually should do is for |
7300 // of using HCallNew as a fallback. | 7349 // inlining to try to build a subgraph without mutating the parent graph. |
| 7350 HInstruction* instr = current_block()->last(); |
| 7351 while (instr != initial_map_value) { |
| 7352 HInstruction* prev_instr = instr->previous(); |
| 7353 instr->DeleteAndReplaceWith(NULL); |
| 7354 instr = prev_instr; |
| 7355 } |
| 7356 initial_map_value->DeleteAndReplaceWith(NULL); |
7301 receiver->DeleteAndReplaceWith(NULL); | 7357 receiver->DeleteAndReplaceWith(NULL); |
7302 check->DeleteAndReplaceWith(NULL); | 7358 check->DeleteAndReplaceWith(NULL); |
7303 environment()->SetExpressionStackAt(receiver_index, function); | 7359 environment()->SetExpressionStackAt(receiver_index, function); |
7304 HInstruction* call = PreProcessCall( | 7360 HInstruction* call = PreProcessCall( |
7305 new(zone()) HCallNew(context, function, argument_count)); | 7361 new(zone()) HCallNew(context, function, argument_count)); |
7306 call->set_position(expr->position()); | 7362 call->set_position(expr->position()); |
7307 return ast_context()->ReturnInstruction(call, expr->id()); | 7363 return ast_context()->ReturnInstruction(call, expr->id()); |
7308 } else { | 7364 } else { |
7309 // The constructor function is both an operand to the instruction and an | 7365 // The constructor function is both an operand to the instruction and an |
7310 // argument to the construct call. | 7366 // argument to the construct call. |
(...skipping 2640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9951 if (ShouldProduceTraceOutput()) { | 10007 if (ShouldProduceTraceOutput()) { |
9952 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10008 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9953 } | 10009 } |
9954 | 10010 |
9955 #ifdef DEBUG | 10011 #ifdef DEBUG |
9956 graph_->Verify(false); // No full verify. | 10012 graph_->Verify(false); // No full verify. |
9957 #endif | 10013 #endif |
9958 } | 10014 } |
9959 | 10015 |
9960 } } // namespace v8::internal | 10016 } } // namespace v8::internal |
OLD | NEW |