OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 2240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2251 current_block()->AddPhi(instr); | 2251 current_block()->AddPhi(instr); |
2252 } | 2252 } |
2253 | 2253 |
2254 | 2254 |
2255 void HGraphBuilder::PushAndAdd(HInstruction* instr) { | 2255 void HGraphBuilder::PushAndAdd(HInstruction* instr) { |
2256 Push(instr); | 2256 Push(instr); |
2257 AddInstruction(instr); | 2257 AddInstruction(instr); |
2258 } | 2258 } |
2259 | 2259 |
2260 | 2260 |
2261 void HGraphBuilder::PreProcessCall(HCall* call) { | 2261 template <int V> |
| 2262 HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { |
2262 int count = call->argument_count(); | 2263 int count = call->argument_count(); |
2263 ZoneList<HValue*> arguments(count); | 2264 ZoneList<HValue*> arguments(count); |
2264 for (int i = 0; i < count; ++i) { | 2265 for (int i = 0; i < count; ++i) { |
2265 arguments.Add(Pop()); | 2266 arguments.Add(Pop()); |
2266 } | 2267 } |
2267 | 2268 |
2268 while (!arguments.is_empty()) { | 2269 while (!arguments.is_empty()) { |
2269 AddInstruction(new HPushArgument(arguments.RemoveLast())); | 2270 AddInstruction(new HPushArgument(arguments.RemoveLast())); |
2270 } | 2271 } |
| 2272 return call; |
2271 } | 2273 } |
2272 | 2274 |
2273 | 2275 |
2274 void HGraphBuilder::SetupScope(Scope* scope) { | 2276 void HGraphBuilder::SetupScope(Scope* scope) { |
2275 // We don't yet handle the function name for named function expressions. | 2277 // We don't yet handle the function name for named function expressions. |
2276 if (scope->function() != NULL) BAILOUT("named function expression"); | 2278 if (scope->function() != NULL) BAILOUT("named function expression"); |
2277 | 2279 |
2278 // We can't handle heap-allocated locals. | 2280 // We can't handle heap-allocated locals. |
2279 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); | 2281 if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); |
2280 | 2282 |
(...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3943 SubgraphScope scope(this, subgraph); | 3945 SubgraphScope scope(this, subgraph); |
3944 AddCheckConstantFunction(expr, receiver, map, false); | 3946 AddCheckConstantFunction(expr, receiver, map, false); |
3945 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 3947 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
3946 PrintF("Trying to inline the polymorphic call to %s\n", | 3948 PrintF("Trying to inline the polymorphic call to %s\n", |
3947 *name->ToCString()); | 3949 *name->ToCString()); |
3948 } | 3950 } |
3949 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { | 3951 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { |
3950 // Check for bailout, as trying to inline might fail due to bailout | 3952 // Check for bailout, as trying to inline might fail due to bailout |
3951 // during hydrogen processing. | 3953 // during hydrogen processing. |
3952 CHECK_BAILOUT; | 3954 CHECK_BAILOUT; |
3953 HCall* call = new HCallConstantFunction(expr->target(), argument_count); | 3955 HCallConstantFunction* call = |
| 3956 new HCallConstantFunction(expr->target(), argument_count); |
3954 call->set_position(expr->position()); | 3957 call->set_position(expr->position()); |
3955 PreProcessCall(call); | 3958 PreProcessCall(call); |
3956 PushAndAdd(call); | 3959 PushAndAdd(call); |
3957 } | 3960 } |
3958 maps.Add(map); | 3961 maps.Add(map); |
3959 subgraphs.Add(subgraph); | 3962 subgraphs.Add(subgraph); |
3960 } else { | 3963 } else { |
3961 needs_generic = true; | 3964 needs_generic = true; |
3962 } | 3965 } |
3963 } | 3966 } |
3964 | 3967 |
3965 // If we couldn't compute the target for any of the maps just perform an | 3968 // If we couldn't compute the target for any of the maps just perform an |
3966 // IC call. | 3969 // IC call. |
3967 if (maps.length() == 0) { | 3970 if (maps.length() == 0) { |
3968 HContext* context = new HContext; | 3971 HContext* context = new HContext; |
3969 AddInstruction(context); | 3972 AddInstruction(context); |
3970 HCall* call = new HCallNamed(context, name, argument_count); | 3973 HCallNamed* call = new HCallNamed(context, name, argument_count); |
3971 call->set_position(expr->position()); | 3974 call->set_position(expr->position()); |
3972 PreProcessCall(call); | 3975 PreProcessCall(call); |
3973 ast_context()->ReturnInstruction(call, expr->id()); | 3976 ast_context()->ReturnInstruction(call, expr->id()); |
3974 } else { | 3977 } else { |
3975 // Build subgraph for generic call through IC. | 3978 // Build subgraph for generic call through IC. |
3976 HSubgraph* default_graph = CreateBranchSubgraph(environment()); | 3979 HSubgraph* default_graph = CreateBranchSubgraph(environment()); |
3977 { SubgraphScope scope(this, default_graph); | 3980 { SubgraphScope scope(this, default_graph); |
3978 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { | 3981 if (!needs_generic && FLAG_deoptimize_uncommon_cases) { |
3979 default_graph->FinishExit(new HDeoptimize()); | 3982 default_graph->FinishExit(new HDeoptimize()); |
3980 } else { | 3983 } else { |
3981 HContext* context = new HContext; | 3984 HContext* context = new HContext; |
3982 AddInstruction(context); | 3985 AddInstruction(context); |
3983 HCall* call = new HCallNamed(context, name, argument_count); | 3986 HCallNamed* call = new HCallNamed(context, name, argument_count); |
3984 call->set_position(expr->position()); | 3987 call->set_position(expr->position()); |
3985 PreProcessCall(call); | 3988 PreProcessCall(call); |
3986 PushAndAdd(call); | 3989 PushAndAdd(call); |
3987 } | 3990 } |
3988 } | 3991 } |
3989 | 3992 |
3990 HBasicBlock* new_exit_block = | 3993 HBasicBlock* new_exit_block = |
3991 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); | 3994 BuildTypeSwitch(receiver, &maps, &subgraphs, default_graph, expr->id()); |
3992 set_current_block(new_exit_block); | 3995 set_current_block(new_exit_block); |
3993 // In an effect context, we did not materialized the value in the | 3996 // In an effect context, we did not materialized the value in the |
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4376 static bool HasCustomCallGenerator(Handle<JSFunction> function) { | 4379 static bool HasCustomCallGenerator(Handle<JSFunction> function) { |
4377 SharedFunctionInfo* info = function->shared(); | 4380 SharedFunctionInfo* info = function->shared(); |
4378 return info->HasBuiltinFunctionId() && | 4381 return info->HasBuiltinFunctionId() && |
4379 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id()); | 4382 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id()); |
4380 } | 4383 } |
4381 | 4384 |
4382 | 4385 |
4383 void HGraphBuilder::VisitCall(Call* expr) { | 4386 void HGraphBuilder::VisitCall(Call* expr) { |
4384 Expression* callee = expr->expression(); | 4387 Expression* callee = expr->expression(); |
4385 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4388 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
4386 HCall* call = NULL; | 4389 HInstruction* call = NULL; |
4387 | 4390 |
4388 Property* prop = callee->AsProperty(); | 4391 Property* prop = callee->AsProperty(); |
4389 if (prop != NULL) { | 4392 if (prop != NULL) { |
4390 if (!prop->key()->IsPropertyName()) { | 4393 if (!prop->key()->IsPropertyName()) { |
4391 // Keyed function call. | 4394 // Keyed function call. |
4392 VISIT_FOR_VALUE(prop->obj()); | 4395 VISIT_FOR_VALUE(prop->obj()); |
4393 | 4396 |
4394 VISIT_FOR_VALUE(prop->key()); | 4397 VISIT_FOR_VALUE(prop->key()); |
4395 // Push receiver and key like the non-optimized code generator expects it. | 4398 // Push receiver and key like the non-optimized code generator expects it. |
4396 HValue* key = Pop(); | 4399 HValue* key = Pop(); |
4397 HValue* receiver = Pop(); | 4400 HValue* receiver = Pop(); |
4398 Push(key); | 4401 Push(key); |
4399 Push(receiver); | 4402 Push(receiver); |
4400 | 4403 |
4401 VisitExpressions(expr->arguments()); | 4404 VisitExpressions(expr->arguments()); |
4402 CHECK_BAILOUT; | 4405 CHECK_BAILOUT; |
4403 | 4406 |
4404 HContext* context = new HContext; | 4407 HContext* context = new HContext; |
4405 AddInstruction(context); | 4408 AddInstruction(context); |
4406 call = new HCallKeyed(context, key, argument_count); | 4409 call = PreProcessCall(new HCallKeyed(context, key, argument_count)); |
4407 call->set_position(expr->position()); | 4410 call->set_position(expr->position()); |
4408 PreProcessCall(call); | |
4409 Drop(1); // Key. | 4411 Drop(1); // Key. |
4410 ast_context()->ReturnInstruction(call, expr->id()); | 4412 ast_context()->ReturnInstruction(call, expr->id()); |
4411 return; | 4413 return; |
4412 } | 4414 } |
4413 | 4415 |
4414 // Named function call. | 4416 // Named function call. |
4415 expr->RecordTypeFeedback(oracle()); | 4417 expr->RecordTypeFeedback(oracle()); |
4416 | 4418 |
4417 if (TryCallApply(expr)) return; | 4419 if (TryCallApply(expr)) return; |
4418 CHECK_BAILOUT; | 4420 CHECK_BAILOUT; |
(...skipping 19 matching lines...) Expand all Loading... |
4438 return; | 4440 return; |
4439 } | 4441 } |
4440 | 4442 |
4441 if (HasCustomCallGenerator(expr->target()) || | 4443 if (HasCustomCallGenerator(expr->target()) || |
4442 expr->check_type() != RECEIVER_MAP_CHECK) { | 4444 expr->check_type() != RECEIVER_MAP_CHECK) { |
4443 // When the target has a custom call IC generator, use the IC, | 4445 // When the target has a custom call IC generator, use the IC, |
4444 // because it is likely to generate better code. Also use the | 4446 // because it is likely to generate better code. Also use the |
4445 // IC when a primitive receiver check is required. | 4447 // IC when a primitive receiver check is required. |
4446 HContext* context = new HContext; | 4448 HContext* context = new HContext; |
4447 AddInstruction(context); | 4449 AddInstruction(context); |
4448 call = new HCallNamed(context, name, argument_count); | 4450 call = PreProcessCall(new HCallNamed(context, name, argument_count)); |
4449 } else { | 4451 } else { |
4450 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4452 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
4451 | 4453 |
4452 if (TryInline(expr)) { | 4454 if (TryInline(expr)) { |
4453 if (current_block() != NULL) { | 4455 if (current_block() != NULL) { |
4454 HValue* return_value = Pop(); | 4456 HValue* return_value = Pop(); |
4455 // If we inlined a function in a test context then we need to emit | 4457 // If we inlined a function in a test context then we need to emit |
4456 // a simulate here to shadow the ones at the end of the | 4458 // a simulate here to shadow the ones at the end of the |
4457 // predecessor blocks. Those environments contain the return | 4459 // predecessor blocks. Those environments contain the return |
4458 // value on top and do not correspond to any actual state of the | 4460 // value on top and do not correspond to any actual state of the |
4459 // unoptimized code. | 4461 // unoptimized code. |
4460 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | 4462 if (ast_context()->IsEffect()) AddSimulate(expr->id()); |
4461 ast_context()->ReturnValue(return_value); | 4463 ast_context()->ReturnValue(return_value); |
4462 } | 4464 } |
4463 return; | 4465 return; |
4464 } else { | 4466 } else { |
4465 // Check for bailout, as the TryInline call in the if condition above | 4467 // Check for bailout, as the TryInline call in the if condition above |
4466 // might return false due to bailout during hydrogen processing. | 4468 // might return false due to bailout during hydrogen processing. |
4467 CHECK_BAILOUT; | 4469 CHECK_BAILOUT; |
4468 call = new HCallConstantFunction(expr->target(), argument_count); | 4470 call = PreProcessCall(new HCallConstantFunction(expr->target(), |
| 4471 argument_count)); |
4469 } | 4472 } |
4470 } | 4473 } |
4471 } else if (types != NULL && types->length() > 1) { | 4474 } else if (types != NULL && types->length() > 1) { |
4472 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 4475 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
4473 HandlePolymorphicCallNamed(expr, receiver, types, name); | 4476 HandlePolymorphicCallNamed(expr, receiver, types, name); |
4474 return; | 4477 return; |
4475 | 4478 |
4476 } else { | 4479 } else { |
4477 HContext* context = new HContext; | 4480 HContext* context = new HContext; |
4478 AddInstruction(context); | 4481 AddInstruction(context); |
4479 call = new HCallNamed(context, name, argument_count); | 4482 call = PreProcessCall(new HCallNamed(context, name, argument_count)); |
4480 } | 4483 } |
4481 | 4484 |
4482 } else { | 4485 } else { |
4483 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4486 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
4484 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); | 4487 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); |
4485 | 4488 |
4486 if (!global_call) { | 4489 if (!global_call) { |
4487 ++argument_count; | 4490 ++argument_count; |
4488 VISIT_FOR_VALUE(expr->expression()); | 4491 VISIT_FOR_VALUE(expr->expression()); |
4489 } | 4492 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4530 // unoptimized code. | 4533 // unoptimized code. |
4531 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | 4534 if (ast_context()->IsEffect()) AddSimulate(expr->id()); |
4532 ast_context()->ReturnValue(return_value); | 4535 ast_context()->ReturnValue(return_value); |
4533 } | 4536 } |
4534 return; | 4537 return; |
4535 } | 4538 } |
4536 // Check for bailout, as trying to inline might fail due to bailout | 4539 // Check for bailout, as trying to inline might fail due to bailout |
4537 // during hydrogen processing. | 4540 // during hydrogen processing. |
4538 CHECK_BAILOUT; | 4541 CHECK_BAILOUT; |
4539 | 4542 |
4540 call = new HCallKnownGlobal(expr->target(), argument_count); | 4543 call = PreProcessCall(new HCallKnownGlobal(expr->target(), |
| 4544 argument_count)); |
4541 } else { | 4545 } else { |
4542 HContext* context = new HContext; | 4546 HContext* context = new HContext; |
4543 AddInstruction(context); | 4547 AddInstruction(context); |
4544 PushAndAdd(new HGlobalObject(context)); | 4548 PushAndAdd(new HGlobalObject(context)); |
4545 VisitExpressions(expr->arguments()); | 4549 VisitExpressions(expr->arguments()); |
4546 CHECK_BAILOUT; | 4550 CHECK_BAILOUT; |
4547 | 4551 |
4548 call = new HCallGlobal(context, var->name(), argument_count); | 4552 call = PreProcessCall(new HCallGlobal(context, |
| 4553 var->name(), |
| 4554 argument_count)); |
4549 } | 4555 } |
4550 | 4556 |
4551 } else { | 4557 } else { |
4552 HContext* context = new HContext; | 4558 HContext* context = new HContext; |
4553 HGlobalObject* global_object = new HGlobalObject(context); | 4559 HGlobalObject* global_object = new HGlobalObject(context); |
4554 AddInstruction(context); | 4560 AddInstruction(context); |
4555 AddInstruction(global_object); | 4561 AddInstruction(global_object); |
4556 PushAndAdd(new HGlobalReceiver(global_object)); | 4562 PushAndAdd(new HGlobalReceiver(global_object)); |
4557 VisitExpressions(expr->arguments()); | 4563 VisitExpressions(expr->arguments()); |
4558 CHECK_BAILOUT; | 4564 CHECK_BAILOUT; |
4559 | 4565 |
4560 call = new HCallFunction(context, argument_count); | 4566 call = PreProcessCall(new HCallFunction(context, argument_count)); |
4561 } | 4567 } |
4562 } | 4568 } |
4563 | 4569 |
4564 call->set_position(expr->position()); | 4570 call->set_position(expr->position()); |
4565 PreProcessCall(call); | |
4566 ast_context()->ReturnInstruction(call, expr->id()); | 4571 ast_context()->ReturnInstruction(call, expr->id()); |
4567 } | 4572 } |
4568 | 4573 |
4569 | 4574 |
4570 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 4575 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
4571 // The constructor function is also used as the receiver argument to the | 4576 // The constructor function is also used as the receiver argument to the |
4572 // JS construct call builtin. | 4577 // JS construct call builtin. |
4573 VISIT_FOR_VALUE(expr->expression()); | 4578 VISIT_FOR_VALUE(expr->expression()); |
4574 VisitExpressions(expr->arguments()); | 4579 VisitExpressions(expr->arguments()); |
4575 CHECK_BAILOUT; | 4580 CHECK_BAILOUT; |
4576 | 4581 |
4577 HContext* context = new HContext; | 4582 HContext* context = new HContext; |
4578 AddInstruction(context); | 4583 AddInstruction(context); |
4579 | 4584 |
4580 // The constructor is both an operand to the instruction and an argument | 4585 // The constructor is both an operand to the instruction and an argument |
4581 // to the construct call. | 4586 // to the construct call. |
4582 int arg_count = expr->arguments()->length() + 1; // Plus constructor. | 4587 int arg_count = expr->arguments()->length() + 1; // Plus constructor. |
4583 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); | 4588 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); |
4584 HCall* call = new HCallNew(context, constructor, arg_count); | 4589 HCallNew* call = new HCallNew(context, constructor, arg_count); |
4585 call->set_position(expr->position()); | 4590 call->set_position(expr->position()); |
4586 PreProcessCall(call); | 4591 PreProcessCall(call); |
4587 ast_context()->ReturnInstruction(call, expr->id()); | 4592 ast_context()->ReturnInstruction(call, expr->id()); |
4588 } | 4593 } |
4589 | 4594 |
4590 | 4595 |
4591 // Support for generating inlined runtime functions. | 4596 // Support for generating inlined runtime functions. |
4592 | 4597 |
4593 // Lookup table for generators for runtime calls that are generated inline. | 4598 // Lookup table for generators for runtime calls that are generated inline. |
4594 // Elements of the table are member pointers to functions of HGraphBuilder. | 4599 // Elements of the table are member pointers to functions of HGraphBuilder. |
(...skipping 28 matching lines...) Expand all Loading... |
4623 | 4628 |
4624 // Call the inline code generator using the pointer-to-member. | 4629 // Call the inline code generator using the pointer-to-member. |
4625 (this->*generator)(expr); | 4630 (this->*generator)(expr); |
4626 } else { | 4631 } else { |
4627 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 4632 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
4628 VisitArgumentList(expr->arguments()); | 4633 VisitArgumentList(expr->arguments()); |
4629 CHECK_BAILOUT; | 4634 CHECK_BAILOUT; |
4630 | 4635 |
4631 Handle<String> name = expr->name(); | 4636 Handle<String> name = expr->name(); |
4632 int argument_count = expr->arguments()->length(); | 4637 int argument_count = expr->arguments()->length(); |
4633 HCall* call = new HCallRuntime(name, function, argument_count); | 4638 HCallRuntime* call = new HCallRuntime(name, function, argument_count); |
4634 call->set_position(RelocInfo::kNoPosition); | 4639 call->set_position(RelocInfo::kNoPosition); |
4635 Drop(argument_count); | 4640 Drop(argument_count); |
4636 ast_context()->ReturnInstruction(call, expr->id()); | 4641 ast_context()->ReturnInstruction(call, expr->id()); |
4637 } | 4642 } |
4638 } | 4643 } |
4639 | 4644 |
4640 | 4645 |
4641 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 4646 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
4642 Token::Value op = expr->op(); | 4647 Token::Value op = expr->op(); |
4643 if (op == Token::VOID) { | 4648 if (op == Token::VOID) { |
(...skipping 1446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6090 } | 6095 } |
6091 } | 6096 } |
6092 | 6097 |
6093 #ifdef DEBUG | 6098 #ifdef DEBUG |
6094 if (graph_ != NULL) graph_->Verify(); | 6099 if (graph_ != NULL) graph_->Verify(); |
6095 if (allocator_ != NULL) allocator_->Verify(); | 6100 if (allocator_ != NULL) allocator_->Verify(); |
6096 #endif | 6101 #endif |
6097 } | 6102 } |
6098 | 6103 |
6099 } } // namespace v8::internal | 6104 } } // namespace v8::internal |
OLD | NEW |