Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: src/hydrogen.cc

Issue 6815029: Merge (7180:7265] from bleeding_edge to the experimental/gc branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 if (first_ == NULL) { 106 if (first_ == NULL) {
107 HBlockEntry* entry = new HBlockEntry(); 107 HBlockEntry* entry = new HBlockEntry();
108 entry->InitializeAsFirst(this); 108 entry->InitializeAsFirst(this);
109 first_ = last_ = entry; 109 first_ = last_ = entry;
110 } 110 }
111 instr->InsertAfter(last_); 111 instr->InsertAfter(last_);
112 last_ = instr; 112 last_ = instr;
113 } 113 }
114 114
115 115
116 HDeoptimize* HBasicBlock::CreateDeoptimize() {
117 ASSERT(HasEnvironment());
118 HEnvironment* environment = last_environment();
119
120 HDeoptimize* instr = new HDeoptimize(environment->length());
121
122 for (int i = 0; i < environment->length(); i++) {
123 HValue* val = environment->values()->at(i);
124 instr->AddEnvironmentValue(val);
125 }
126
127 return instr;
128 }
129
130
116 HSimulate* HBasicBlock::CreateSimulate(int id) { 131 HSimulate* HBasicBlock::CreateSimulate(int id) {
117 ASSERT(HasEnvironment()); 132 ASSERT(HasEnvironment());
118 HEnvironment* environment = last_environment(); 133 HEnvironment* environment = last_environment();
119 ASSERT(id == AstNode::kNoNumber || 134 ASSERT(id == AstNode::kNoNumber ||
120 environment->closure()->shared()->VerifyBailoutId(id)); 135 environment->closure()->shared()->VerifyBailoutId(id));
121 136
122 int push_count = environment->push_count(); 137 int push_count = environment->push_count();
123 int pop_count = environment->pop_count(); 138 int pop_count = environment->pop_count();
124 139
125 int length = environment->length(); 140 int length = environment->length();
(...skipping 2339 matching lines...) Expand 10 before | Expand all | Expand 10 after
2465 // We only optimize switch statements with smi-literal smi comparisons, 2480 // We only optimize switch statements with smi-literal smi comparisons,
2466 // with a bounded number of clauses. 2481 // with a bounded number of clauses.
2467 const int kCaseClauseLimit = 128; 2482 const int kCaseClauseLimit = 128;
2468 ZoneList<CaseClause*>* clauses = stmt->cases(); 2483 ZoneList<CaseClause*>* clauses = stmt->cases();
2469 int clause_count = clauses->length(); 2484 int clause_count = clauses->length();
2470 if (clause_count > kCaseClauseLimit) { 2485 if (clause_count > kCaseClauseLimit) {
2471 BAILOUT("SwitchStatement: too many clauses"); 2486 BAILOUT("SwitchStatement: too many clauses");
2472 } 2487 }
2473 2488
2474 VISIT_FOR_VALUE(stmt->tag()); 2489 VISIT_FOR_VALUE(stmt->tag());
2490 AddSimulate(stmt->EntryId());
2475 HValue* tag_value = Pop(); 2491 HValue* tag_value = Pop();
2476 HBasicBlock* first_test_block = current_block(); 2492 HBasicBlock* first_test_block = current_block();
2477 2493
2478 // 1. Build all the tests, with dangling true branches. Unconditionally 2494 // 1. Build all the tests, with dangling true branches. Unconditionally
2479 // deoptimize if we encounter a non-smi comparison. 2495 // deoptimize if we encounter a non-smi comparison.
2480 for (int i = 0; i < clause_count; ++i) { 2496 for (int i = 0; i < clause_count; ++i) {
2481 CaseClause* clause = clauses->at(i); 2497 CaseClause* clause = clauses->at(i);
2482 if (clause->is_default()) continue; 2498 if (clause->is_default()) continue;
2483 if (!clause->label()->IsSmiLiteral()) { 2499 if (!clause->label()->IsSmiLiteral()) {
2484 BAILOUT("SwitchStatement: non-literal switch label"); 2500 BAILOUT("SwitchStatement: non-literal switch label");
2485 } 2501 }
2486 2502
2487 // Unconditionally deoptimize on the first non-smi compare. 2503 // Unconditionally deoptimize on the first non-smi compare.
2488 clause->RecordTypeFeedback(oracle()); 2504 clause->RecordTypeFeedback(oracle());
2489 if (!clause->IsSmiCompare()) { 2505 if (!clause->IsSmiCompare()) {
2490 if (current_block() == first_test_block) { 2506 current_block()->FinishExitWithDeoptimization();
2491 // If the first test is the one that deopts and if the tag value is
2492 // a phi, we need to have some use of that phi to prevent phi
2493 // elimination from removing it. This HSimulate is such a use.
2494 Push(tag_value);
2495 AddSimulate(stmt->EntryId());
2496 Drop(1);
2497 }
2498 current_block()->Finish(new HDeoptimize());
2499 set_current_block(NULL); 2507 set_current_block(NULL);
2500 break; 2508 break;
2501 } 2509 }
2502 2510
2503 // Otherwise generate a compare and branch. 2511 // Otherwise generate a compare and branch.
2504 VISIT_FOR_VALUE(clause->label()); 2512 VISIT_FOR_VALUE(clause->label());
2505 HValue* label_value = Pop(); 2513 HValue* label_value = Pop();
2506 HCompare* compare = new HCompare(tag_value, label_value, Token::EQ_STRICT); 2514 HCompare* compare = new HCompare(tag_value, label_value, Token::EQ_STRICT);
2507 compare->SetInputRepresentation(Representation::Integer32()); 2515 compare->SetInputRepresentation(Representation::Integer32());
2508 ASSERT(!compare->HasSideEffects()); 2516 ASSERT(!compare->HasSideEffects());
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after
3108 current_block()->Goto(join); 3116 current_block()->Goto(join);
3109 3117
3110 set_current_block(if_false); 3118 set_current_block(if_false);
3111 } 3119 }
3112 } 3120 }
3113 3121
3114 // Finish up. Unconditionally deoptimize if we've handled all the maps we 3122 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3115 // know about and do not want to handle ones we've never seen. Otherwise 3123 // know about and do not want to handle ones we've never seen. Otherwise
3116 // use a generic IC. 3124 // use a generic IC.
3117 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 3125 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3118 current_block()->FinishExit(new HDeoptimize); 3126 current_block()->FinishExitWithDeoptimization();
3119 } else { 3127 } else {
3120 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 3128 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3121 instr->set_position(expr->position()); 3129 instr->set_position(expr->position());
3122 AddInstruction(instr); 3130 AddInstruction(instr);
3123 3131
3124 if (join != NULL) { 3132 if (join != NULL) {
3125 if (!ast_context()->IsEffect()) Push(value); 3133 if (!ast_context()->IsEffect()) Push(value);
3126 current_block()->Goto(join); 3134 current_block()->Goto(join);
3127 } else { 3135 } else {
3128 // The HSimulate for the store should not see the stored value in 3136 // The HSimulate for the store should not see the stored value in
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
3456 current_block()->Goto(join); 3464 current_block()->Goto(join);
3457 3465
3458 set_current_block(if_false); 3466 set_current_block(if_false);
3459 } 3467 }
3460 } 3468 }
3461 3469
3462 // Finish up. Unconditionally deoptimize if we've handled all the maps we 3470 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3463 // know about and do not want to handle ones we've never seen. Otherwise 3471 // know about and do not want to handle ones we've never seen. Otherwise
3464 // use a generic IC. 3472 // use a generic IC.
3465 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 3473 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3466 current_block()->FinishExit(new HDeoptimize); 3474 current_block()->FinishExitWithDeoptimization();
3467 } else { 3475 } else {
3468 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3476 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3469 instr->set_position(expr->position()); 3477 instr->set_position(expr->position());
3470 3478
3471 if (join != NULL) { 3479 if (join != NULL) {
3472 AddInstruction(instr); 3480 AddInstruction(instr);
3473 if (!ast_context()->IsEffect()) Push(instr); 3481 if (!ast_context()->IsEffect()) Push(instr);
3474 current_block()->Goto(join); 3482 current_block()->Goto(join);
3475 } else { 3483 } else {
3476 ast_context()->ReturnInstruction(instr, expr->id()); 3484 ast_context()->ReturnInstruction(instr, expr->id());
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after
3821 3829
3822 if (current_block() != NULL) current_block()->Goto(join); 3830 if (current_block() != NULL) current_block()->Goto(join);
3823 set_current_block(if_false); 3831 set_current_block(if_false);
3824 } 3832 }
3825 } 3833 }
3826 3834
3827 // Finish up. Unconditionally deoptimize if we've handled all the maps we 3835 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3828 // know about and do not want to handle ones we've never seen. Otherwise 3836 // know about and do not want to handle ones we've never seen. Otherwise
3829 // use a generic IC. 3837 // use a generic IC.
3830 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 3838 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3831 current_block()->FinishExit(new HDeoptimize); 3839 current_block()->FinishExitWithDeoptimization();
3832 } else { 3840 } else {
3833 HContext* context = new HContext; 3841 HContext* context = new HContext;
3834 AddInstruction(context); 3842 AddInstruction(context);
3835 HCallNamed* call = new HCallNamed(context, name, argument_count); 3843 HCallNamed* call = new HCallNamed(context, name, argument_count);
3836 call->set_position(expr->position()); 3844 call->set_position(expr->position());
3837 PreProcessCall(call); 3845 PreProcessCall(call);
3838 3846
3839 if (join != NULL) { 3847 if (join != NULL) {
3840 AddInstruction(call); 3848 AddInstruction(call);
3841 if (!ast_context()->IsEffect()) Push(call); 3849 if (!ast_context()->IsEffect()) Push(call);
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
4209 expr->GetReceiverTypes()->first(), 4217 expr->GetReceiverTypes()->first(),
4210 true); 4218 true);
4211 HInstruction* result = 4219 HInstruction* result =
4212 new HApplyArguments(function, receiver, length, elements); 4220 new HApplyArguments(function, receiver, length, elements);
4213 result->set_position(expr->position()); 4221 result->set_position(expr->position());
4214 ast_context()->ReturnInstruction(result, expr->id()); 4222 ast_context()->ReturnInstruction(result, expr->id());
4215 return true; 4223 return true;
4216 } 4224 }
4217 4225
4218 4226
4219 static bool HasCustomCallGenerator(Handle<JSFunction> function) {
4220 SharedFunctionInfo* info = function->shared();
4221 return info->HasBuiltinFunctionId() &&
4222 CallStubCompiler::HasCustomCallGenerator(info->builtin_function_id());
4223 }
4224
4225
4226 void HGraphBuilder::VisitCall(Call* expr) { 4227 void HGraphBuilder::VisitCall(Call* expr) {
4227 Expression* callee = expr->expression(); 4228 Expression* callee = expr->expression();
4228 int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4229 int argument_count = expr->arguments()->length() + 1; // Plus receiver.
4229 HInstruction* call = NULL; 4230 HInstruction* call = NULL;
4230 4231
4231 Property* prop = callee->AsProperty(); 4232 Property* prop = callee->AsProperty();
4232 if (prop != NULL) { 4233 if (prop != NULL) {
4233 if (!prop->key()->IsPropertyName()) { 4234 if (!prop->key()->IsPropertyName()) {
4234 // Keyed function call. 4235 // Keyed function call.
4235 VISIT_FOR_VALUE(prop->obj()); 4236 VISIT_FOR_VALUE(prop->obj());
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
4273 if (expr->IsMonomorphic()) { 4274 if (expr->IsMonomorphic()) {
4274 Handle<Map> receiver_map = 4275 Handle<Map> receiver_map =
4275 (types == NULL) ? Handle<Map>::null() : types->first(); 4276 (types == NULL) ? Handle<Map>::null() : types->first();
4276 if (TryInlineBuiltinFunction(expr, 4277 if (TryInlineBuiltinFunction(expr,
4277 receiver, 4278 receiver,
4278 receiver_map, 4279 receiver_map,
4279 expr->check_type())) { 4280 expr->check_type())) {
4280 return; 4281 return;
4281 } 4282 }
4282 4283
4283 if (HasCustomCallGenerator(expr->target()) || 4284 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) ||
4284 CallOptimization(*expr->target()).is_simple_api_call() ||
4285 expr->check_type() != RECEIVER_MAP_CHECK) { 4285 expr->check_type() != RECEIVER_MAP_CHECK) {
4286 // When the target has a custom call IC generator, use the IC, 4286 // When the target has a custom call IC generator, use the IC,
4287 // because it is likely to generate better code. Similarly, we 4287 // because it is likely to generate better code. Also use the IC
4288 // generate better call stubs for some API functions. 4288 // when a primitive receiver check is required.
4289 // Also use the IC when a primitive receiver check is required.
4290 HContext* context = new HContext; 4289 HContext* context = new HContext;
4291 AddInstruction(context); 4290 AddInstruction(context);
4292 call = PreProcessCall(new HCallNamed(context, name, argument_count)); 4291 call = PreProcessCall(new HCallNamed(context, name, argument_count));
4293 } else { 4292 } else {
4294 AddCheckConstantFunction(expr, receiver, receiver_map, true); 4293 AddCheckConstantFunction(expr, receiver, receiver_map, true);
4295 4294
4296 if (TryInline(expr)) { 4295 if (TryInline(expr)) {
4297 return; 4296 return;
4298 } else { 4297 } else {
4299 // Check for bailout, as the TryInline call in the if condition above 4298 // Check for bailout, as the TryInline call in the if condition above
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
4526 4525
4527 HBasicBlock* join = 4526 HBasicBlock* join =
4528 CreateJoin(materialize_false, materialize_true, expr->id()); 4527 CreateJoin(materialize_false, materialize_true, expr->id());
4529 set_current_block(join); 4528 set_current_block(join);
4530 ast_context()->ReturnValue(Pop()); 4529 ast_context()->ReturnValue(Pop());
4531 } else { 4530 } else {
4532 ASSERT(ast_context()->IsEffect()); 4531 ASSERT(ast_context()->IsEffect());
4533 VisitForEffect(expr->expression()); 4532 VisitForEffect(expr->expression());
4534 } 4533 }
4535 4534
4536 } else if (op == Token::BIT_NOT || op == Token::SUB) { 4535 } else if (op == Token::TYPEOF) {
4536 VISIT_FOR_VALUE(expr->expression());
4537 HValue* value = Pop();
4538 ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4539
4540 } else {
4537 VISIT_FOR_VALUE(expr->expression()); 4541 VISIT_FOR_VALUE(expr->expression());
4538 HValue* value = Pop(); 4542 HValue* value = Pop();
4539 HInstruction* instr = NULL; 4543 HInstruction* instr = NULL;
4540 switch (op) { 4544 switch (op) {
4541 case Token::BIT_NOT: 4545 case Token::BIT_NOT:
4542 instr = new HBitNot(value); 4546 instr = new HBitNot(value);
4543 break; 4547 break;
4544 case Token::SUB: 4548 case Token::SUB:
4545 instr = new HMul(graph_->GetConstantMinus1(), value); 4549 instr = new HMul(value, graph_->GetConstantMinus1());
4550 break;
4551 case Token::ADD:
4552 instr = new HMul(value, graph_->GetConstant1());
4546 break; 4553 break;
4547 default: 4554 default:
4548 UNREACHABLE(); 4555 BAILOUT("Value: unsupported unary operation");
4549 break; 4556 break;
4550 } 4557 }
4551 ast_context()->ReturnInstruction(instr, expr->id()); 4558 ast_context()->ReturnInstruction(instr, expr->id());
4552 } else if (op == Token::TYPEOF) {
4553 VISIT_FOR_VALUE(expr->expression());
4554 HValue* value = Pop();
4555 ast_context()->ReturnInstruction(new HTypeof(value), expr->id());
4556 } else {
4557 BAILOUT("Value: unsupported unary operation");
4558 } 4559 }
4559 } 4560 }
4560 4561
4561 4562
4562 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { 4563 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) {
4563 // IncrementOperation is never visited by the visitor. It only 4564 // IncrementOperation is never visited by the visitor. It only
4564 // occurs as a subexpression of CountOperation. 4565 // occurs as a subexpression of CountOperation.
4565 UNREACHABLE(); 4566 UNREACHABLE();
4566 } 4567 }
4567 4568
(...skipping 1357 matching lines...) Expand 10 before | Expand all | Expand 10 after
5925 } 5926 }
5926 } 5927 }
5927 5928
5928 #ifdef DEBUG 5929 #ifdef DEBUG
5929 if (graph_ != NULL) graph_->Verify(); 5930 if (graph_ != NULL) graph_->Verify();
5930 if (allocator_ != NULL) allocator_->Verify(); 5931 if (allocator_ != NULL) allocator_->Verify();
5931 #endif 5932 #endif
5932 } 5933 }
5933 5934
5934 } } // namespace v8::internal 5935 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698