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

Side by Side Diff: src/hydrogen.cc

Issue 8404030: Version 3.7.1 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: Created 9 years, 1 month 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 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 void HBasicBlock::Finish(HControlInstruction* end) { 157 void HBasicBlock::Finish(HControlInstruction* end) {
158 ASSERT(!IsFinished()); 158 ASSERT(!IsFinished());
159 AddInstruction(end); 159 AddInstruction(end);
160 end_ = end; 160 end_ = end;
161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 161 for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
162 it.Current()->RegisterPredecessor(this); 162 it.Current()->RegisterPredecessor(this);
163 } 163 }
164 } 164 }
165 165
166 166
167 void HBasicBlock::Goto(HBasicBlock* block) { 167 void HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) {
168 if (block->IsInlineReturnTarget()) { 168 if (block->IsInlineReturnTarget()) {
169 AddInstruction(new(zone()) HLeaveInlined); 169 AddInstruction(new(zone()) HLeaveInlined);
170 last_environment_ = last_environment()->outer(); 170 last_environment_ = last_environment()->outer();
171 if (drop_extra) last_environment_->Drop(1);
171 } 172 }
172 AddSimulate(AstNode::kNoNumber); 173 AddSimulate(AstNode::kNoNumber);
173 HGoto* instr = new(zone()) HGoto(block); 174 HGoto* instr = new(zone()) HGoto(block);
174 Finish(instr); 175 Finish(instr);
175 } 176 }
176 177
177 178
178 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 179 void HBasicBlock::AddLeaveInlined(HValue* return_value,
180 HBasicBlock* target,
181 bool drop_extra) {
179 ASSERT(target->IsInlineReturnTarget()); 182 ASSERT(target->IsInlineReturnTarget());
180 ASSERT(return_value != NULL); 183 ASSERT(return_value != NULL);
181 AddInstruction(new(zone()) HLeaveInlined); 184 AddInstruction(new(zone()) HLeaveInlined);
182 last_environment_ = last_environment()->outer(); 185 last_environment_ = last_environment()->outer();
186 if (drop_extra) last_environment_->Drop(1);
183 last_environment()->Push(return_value); 187 last_environment()->Push(return_value);
184 AddSimulate(AstNode::kNoNumber); 188 AddSimulate(AstNode::kNoNumber);
185 HGoto* instr = new(zone()) HGoto(target); 189 HGoto* instr = new(zone()) HGoto(target);
186 Finish(instr); 190 Finish(instr);
187 } 191 }
188 192
189 193
190 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 194 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
191 ASSERT(!HasEnvironment()); 195 ASSERT(!HasEnvironment());
192 ASSERT(first() == NULL); 196 ASSERT(first() == NULL);
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 538
535 539
536 HConstant* HGraph::GetConstantHole() { 540 HConstant* HGraph::GetConstantHole() {
537 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value()); 541 return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value());
538 } 542 }
539 543
540 544
541 HGraphBuilder::HGraphBuilder(CompilationInfo* info, 545 HGraphBuilder::HGraphBuilder(CompilationInfo* info,
542 TypeFeedbackOracle* oracle) 546 TypeFeedbackOracle* oracle)
543 : function_state_(NULL), 547 : function_state_(NULL),
544 initial_function_state_(this, info, oracle), 548 initial_function_state_(this, info, oracle, false),
545 ast_context_(NULL), 549 ast_context_(NULL),
546 break_scope_(NULL), 550 break_scope_(NULL),
547 graph_(NULL), 551 graph_(NULL),
548 current_block_(NULL), 552 current_block_(NULL),
549 inlined_count_(0), 553 inlined_count_(0),
550 zone_(info->isolate()->zone()), 554 zone_(info->isolate()->zone()),
551 inline_bailout_(false) { 555 inline_bailout_(false) {
552 // This is not initialized in the initializer list because the 556 // This is not initialized in the initializer list because the
553 // constructor for the initial state relies on function_state_ == NULL 557 // constructor for the initial state relies on function_state_ == NULL
554 // to know it's the initial state. 558 // to know it's the initial state.
(...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 1496
1493 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( 1497 int HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
1494 HBasicBlock* dominator, HBasicBlock* dominated) { 1498 HBasicBlock* dominator, HBasicBlock* dominated) {
1495 int side_effects = 0; 1499 int side_effects = 0;
1496 for (int i = 0; i < dominated->predecessors()->length(); ++i) { 1500 for (int i = 0; i < dominated->predecessors()->length(); ++i) {
1497 HBasicBlock* block = dominated->predecessors()->at(i); 1501 HBasicBlock* block = dominated->predecessors()->at(i);
1498 if (dominator->block_id() < block->block_id() && 1502 if (dominator->block_id() < block->block_id() &&
1499 block->block_id() < dominated->block_id() && 1503 block->block_id() < dominated->block_id() &&
1500 visited_on_paths_.Add(block->block_id())) { 1504 visited_on_paths_.Add(block->block_id())) {
1501 side_effects |= block_side_effects_[block->block_id()]; 1505 side_effects |= block_side_effects_[block->block_id()];
1506 if (block->IsLoopHeader()) {
1507 side_effects |= loop_side_effects_[block->block_id()];
1508 }
1502 side_effects |= CollectSideEffectsOnPathsToDominatedBlock( 1509 side_effects |= CollectSideEffectsOnPathsToDominatedBlock(
1503 dominator, block); 1510 dominator, block);
1504 } 1511 }
1505 } 1512 }
1506 return side_effects; 1513 return side_effects;
1507 } 1514 }
1508 1515
1509 1516
1510 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { 1517 void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
1511 TraceGVN("Analyzing block B%d%s\n", 1518 TraceGVN("Analyzing block B%d%s\n",
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
1998 } 2005 }
1999 } 2006 }
2000 } 2007 }
2001 } 2008 }
2002 2009
2003 2010
2004 // Implementation of utility class to encapsulate the translation state for 2011 // Implementation of utility class to encapsulate the translation state for
2005 // a (possibly inlined) function. 2012 // a (possibly inlined) function.
2006 FunctionState::FunctionState(HGraphBuilder* owner, 2013 FunctionState::FunctionState(HGraphBuilder* owner,
2007 CompilationInfo* info, 2014 CompilationInfo* info,
2008 TypeFeedbackOracle* oracle) 2015 TypeFeedbackOracle* oracle,
2016 bool drop_extra)
2009 : owner_(owner), 2017 : owner_(owner),
2010 compilation_info_(info), 2018 compilation_info_(info),
2011 oracle_(oracle), 2019 oracle_(oracle),
2012 call_context_(NULL), 2020 call_context_(NULL),
2021 drop_extra_(drop_extra),
2013 function_return_(NULL), 2022 function_return_(NULL),
2014 test_context_(NULL), 2023 test_context_(NULL),
2015 outer_(owner->function_state()) { 2024 outer_(owner->function_state()) {
2016 if (outer_ != NULL) { 2025 if (outer_ != NULL) {
2017 // State for an inline function. 2026 // State for an inline function.
2018 if (owner->ast_context()->IsTest()) { 2027 if (owner->ast_context()->IsTest()) {
2019 HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2028 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
2020 HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2029 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
2021 if_true->MarkAsInlineReturnTarget(); 2030 if_true->MarkAsInlineReturnTarget();
2022 if_false->MarkAsInlineReturnTarget(); 2031 if_false->MarkAsInlineReturnTarget();
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2161 } 2170 }
2162 2171
2163 2172
2164 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { 2173 void TestContext::ReturnControl(HControlInstruction* instr, int ast_id) {
2165 ASSERT(!instr->HasSideEffects()); 2174 ASSERT(!instr->HasSideEffects());
2166 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 2175 HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
2167 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 2176 HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
2168 instr->SetSuccessorAt(0, empty_true); 2177 instr->SetSuccessorAt(0, empty_true);
2169 instr->SetSuccessorAt(1, empty_false); 2178 instr->SetSuccessorAt(1, empty_false);
2170 owner()->current_block()->Finish(instr); 2179 owner()->current_block()->Finish(instr);
2171 empty_true->Goto(if_true()); 2180 empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
2172 empty_false->Goto(if_false()); 2181 empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
2173 owner()->set_current_block(NULL); 2182 owner()->set_current_block(NULL);
2174 } 2183 }
2175 2184
2176 2185
2177 void TestContext::BuildBranch(HValue* value) { 2186 void TestContext::BuildBranch(HValue* value) {
2178 // We expect the graph to be in edge-split form: there is no edge that 2187 // We expect the graph to be in edge-split form: there is no edge that
2179 // connects a branch node to a join node. We conservatively ensure that 2188 // connects a branch node to a join node. We conservatively ensure that
2180 // property by always adding an empty block on the outgoing edges of this 2189 // property by always adding an empty block on the outgoing edges of this
2181 // branch. 2190 // branch.
2182 HGraphBuilder* builder = owner(); 2191 HGraphBuilder* builder = owner();
2183 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2192 if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
2184 builder->Bailout("arguments object value in a test context"); 2193 builder->Bailout("arguments object value in a test context");
2185 } 2194 }
2186 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2195 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock();
2187 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2196 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock();
2188 unsigned test_id = condition()->test_id(); 2197 unsigned test_id = condition()->test_id();
2189 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id)); 2198 ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id));
2190 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); 2199 HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected);
2191 builder->current_block()->Finish(test); 2200 builder->current_block()->Finish(test);
2192 2201
2193 empty_true->Goto(if_true()); 2202 empty_true->Goto(if_true(), owner()->function_state()->drop_extra());
2194 empty_false->Goto(if_false()); 2203 empty_false->Goto(if_false(), owner()->function_state()->drop_extra());
2195 builder->set_current_block(NULL); 2204 builder->set_current_block(NULL);
2196 } 2205 }
2197 2206
2198 2207
2199 // HGraphBuilder infrastructure for bailing out and checking bailouts. 2208 // HGraphBuilder infrastructure for bailing out and checking bailouts.
2200 #define CHECK_BAILOUT(call) \ 2209 #define CHECK_BAILOUT(call) \
2201 do { \ 2210 do { \
2202 call; \ 2211 call; \
2203 if (HasStackOverflow()) return; \ 2212 if (HasStackOverflow()) return; \
2204 } while (false) 2213 } while (false)
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2645 } else { 2654 } else {
2646 // Return from an inlined function, visit the subexpression in the 2655 // Return from an inlined function, visit the subexpression in the
2647 // expression context of the call. 2656 // expression context of the call.
2648 if (context->IsTest()) { 2657 if (context->IsTest()) {
2649 TestContext* test = TestContext::cast(context); 2658 TestContext* test = TestContext::cast(context);
2650 VisitForControl(stmt->expression(), 2659 VisitForControl(stmt->expression(),
2651 test->if_true(), 2660 test->if_true(),
2652 test->if_false()); 2661 test->if_false());
2653 } else if (context->IsEffect()) { 2662 } else if (context->IsEffect()) {
2654 CHECK_ALIVE(VisitForEffect(stmt->expression())); 2663 CHECK_ALIVE(VisitForEffect(stmt->expression()));
2655 current_block()->Goto(function_return()); 2664 current_block()->Goto(function_return(), function_state()->drop_extra());
2656 } else { 2665 } else {
2657 ASSERT(context->IsValue()); 2666 ASSERT(context->IsValue());
2658 CHECK_ALIVE(VisitForValue(stmt->expression())); 2667 CHECK_ALIVE(VisitForValue(stmt->expression()));
2659 HValue* return_value = environment()->Pop(); 2668 HValue* return_value = environment()->Pop();
2660 current_block()->AddLeaveInlined(return_value, function_return()); 2669 current_block()->AddLeaveInlined(return_value,
2670 function_return(),
2671 function_state()->drop_extra());
2661 } 2672 }
2662 set_current_block(NULL); 2673 set_current_block(NULL);
2663 } 2674 }
2664 } 2675 }
2665 2676
2666 2677
2667 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2678 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2668 ASSERT(!HasStackOverflow()); 2679 ASSERT(!HasStackOverflow());
2669 ASSERT(current_block() != NULL); 2680 ASSERT(current_block() != NULL);
2670 ASSERT(current_block()->HasPredecessor()); 2681 ASSERT(current_block()->HasPredecessor());
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
3149 // Handle known global constants like 'undefined' specially to avoid a 3160 // Handle known global constants like 'undefined' specially to avoid a
3150 // load from a global cell for them. 3161 // load from a global cell for them.
3151 Handle<Object> constant_value = 3162 Handle<Object> constant_value =
3152 isolate()->factory()->GlobalConstantFor(variable->name()); 3163 isolate()->factory()->GlobalConstantFor(variable->name());
3153 if (!constant_value.is_null()) { 3164 if (!constant_value.is_null()) {
3154 HConstant* instr = 3165 HConstant* instr =
3155 new(zone()) HConstant(constant_value, Representation::Tagged()); 3166 new(zone()) HConstant(constant_value, Representation::Tagged());
3156 return ast_context()->ReturnInstruction(instr, expr->id()); 3167 return ast_context()->ReturnInstruction(instr, expr->id());
3157 } 3168 }
3158 3169
3159 LookupResult lookup; 3170 LookupResult lookup(isolate());
3160 GlobalPropertyAccess type = 3171 GlobalPropertyAccess type =
3161 LookupGlobalProperty(variable, &lookup, false); 3172 LookupGlobalProperty(variable, &lookup, false);
3162 3173
3163 if (type == kUseCell && 3174 if (type == kUseCell &&
3164 info()->global_object()->IsAccessCheckNeeded()) { 3175 info()->global_object()->IsAccessCheckNeeded()) {
3165 type = kUseGeneric; 3176 type = kUseGeneric;
3166 } 3177 }
3167 3178
3168 if (type == kUseCell) { 3179 if (type == kUseCell) {
3169 Handle<GlobalObject> global(info()->global_object()); 3180 Handle<GlobalObject> global(info()->global_object());
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
3269 if (property->emit_store()) { 3280 if (property->emit_store()) {
3270 CHECK_ALIVE(VisitForValue(value)); 3281 CHECK_ALIVE(VisitForValue(value));
3271 HValue* value = Pop(); 3282 HValue* value = Pop();
3272 Handle<String> name = Handle<String>::cast(key->handle()); 3283 Handle<String> name = Handle<String>::cast(key->handle());
3273 HStoreNamedGeneric* store = 3284 HStoreNamedGeneric* store =
3274 new(zone()) HStoreNamedGeneric( 3285 new(zone()) HStoreNamedGeneric(
3275 context, 3286 context,
3276 literal, 3287 literal,
3277 name, 3288 name,
3278 value, 3289 value,
3279 function_strict_mode()); 3290 function_strict_mode_flag());
3280 AddInstruction(store); 3291 AddInstruction(store);
3281 AddSimulate(key->id()); 3292 AddSimulate(key->id());
3282 } else { 3293 } else {
3283 CHECK_ALIVE(VisitForEffect(value)); 3294 CHECK_ALIVE(VisitForEffect(value));
3284 } 3295 }
3285 break; 3296 break;
3286 } 3297 }
3287 // Fall through. 3298 // Fall through.
3288 case ObjectLiteral::Property::PROTOTYPE: 3299 case ObjectLiteral::Property::PROTOTYPE:
3289 case ObjectLiteral::Property::SETTER: 3300 case ObjectLiteral::Property::SETTER:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
3330 for (int i = 0; i < length; i++) { 3341 for (int i = 0; i < length; i++) {
3331 Expression* subexpr = subexprs->at(i); 3342 Expression* subexpr = subexprs->at(i);
3332 // If the subexpression is a literal or a simple materialized literal it 3343 // If the subexpression is a literal or a simple materialized literal it
3333 // is already set in the cloned array. 3344 // is already set in the cloned array.
3334 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3345 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
3335 3346
3336 CHECK_ALIVE(VisitForValue(subexpr)); 3347 CHECK_ALIVE(VisitForValue(subexpr));
3337 HValue* value = Pop(); 3348 HValue* value = Pop();
3338 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 3349 if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal");
3339 3350
3340 // Load the elements array before the first store. 3351 elements = new(zone()) HLoadElements(literal);
3341 if (elements == NULL) { 3352 AddInstruction(elements);
3342 elements = new(zone()) HLoadElements(literal);
3343 AddInstruction(elements);
3344 }
3345 3353
3346 HValue* key = AddInstruction( 3354 HValue* key = AddInstruction(
3347 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 3355 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
3348 Representation::Integer32())); 3356 Representation::Integer32()));
3349 HInstruction* elements_kind = 3357 HInstruction* elements_kind =
3350 AddInstruction(new(zone()) HElementsKind(literal)); 3358 AddInstruction(new(zone()) HElementsKind(literal));
3351 HBasicBlock* store_fast = graph()->CreateBasicBlock(); 3359 HBasicBlock* store_fast = graph()->CreateBasicBlock();
3352 // Two empty blocks to satisfy edge split form. 3360 // Two empty blocks to satisfy edge split form.
3353 HBasicBlock* store_fast_edgesplit1 = graph()->CreateBasicBlock(); 3361 HBasicBlock* store_fast_edgesplit1 = graph()->CreateBasicBlock();
3354 HBasicBlock* store_fast_edgesplit2 = graph()->CreateBasicBlock(); 3362 HBasicBlock* store_fast_edgesplit2 = graph()->CreateBasicBlock();
3355 HBasicBlock* store_generic = graph()->CreateBasicBlock(); 3363 HBasicBlock* store_generic = graph()->CreateBasicBlock();
3356 HBasicBlock* check_smi_only_elements = graph()->CreateBasicBlock(); 3364 HBasicBlock* check_smi_only_elements = graph()->CreateBasicBlock();
3357 HBasicBlock* join = graph()->CreateBasicBlock(); 3365 HBasicBlock* join = graph()->CreateBasicBlock();
3358 3366
3359 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(value); 3367 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(value);
3360 smicheck->SetSuccessorAt(0, store_fast_edgesplit1); 3368 smicheck->SetSuccessorAt(0, store_fast_edgesplit1);
3361 smicheck->SetSuccessorAt(1, check_smi_only_elements); 3369 smicheck->SetSuccessorAt(1, check_smi_only_elements);
3362 current_block()->Finish(smicheck); 3370 current_block()->Finish(smicheck);
3363 store_fast_edgesplit1->Finish(new(zone()) HGoto(store_fast)); 3371 store_fast_edgesplit1->Finish(new(zone()) HGoto(store_fast));
3364 3372
3365 set_current_block(check_smi_only_elements); 3373 set_current_block(check_smi_only_elements);
3366 HCompareConstantEqAndBranch* smi_elements_check = 3374 HCompareConstantEqAndBranch* smi_elements_check =
3367 new(zone()) HCompareConstantEqAndBranch(elements_kind, 3375 new(zone()) HCompareConstantEqAndBranch(elements_kind,
3368 FAST_SMI_ONLY_ELEMENTS, 3376 FAST_ELEMENTS,
3369 Token::EQ_STRICT); 3377 Token::EQ_STRICT);
3370 smi_elements_check->SetSuccessorAt(0, store_generic); 3378 smi_elements_check->SetSuccessorAt(0, store_fast_edgesplit2);
3371 smi_elements_check->SetSuccessorAt(1, store_fast_edgesplit2); 3379 smi_elements_check->SetSuccessorAt(1, store_generic);
3372 current_block()->Finish(smi_elements_check); 3380 current_block()->Finish(smi_elements_check);
3373 store_fast_edgesplit2->Finish(new(zone()) HGoto(store_fast)); 3381 store_fast_edgesplit2->Finish(new(zone()) HGoto(store_fast));
3374 3382
3375 set_current_block(store_fast); 3383 set_current_block(store_fast);
3376 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); 3384 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3377 store_fast->Goto(join); 3385 store_fast->Goto(join);
3378 3386
3379 set_current_block(store_generic); 3387 set_current_block(store_generic);
3380 AddInstruction(BuildStoreKeyedGeneric(literal, key, value)); 3388 AddInstruction(BuildStoreKeyedGeneric(literal, key, value));
3381 store_generic->Goto(join); 3389 store_generic->Goto(join);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
3450 3458
3451 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3459 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object,
3452 Handle<String> name, 3460 Handle<String> name,
3453 HValue* value) { 3461 HValue* value) {
3454 HValue* context = environment()->LookupContext(); 3462 HValue* context = environment()->LookupContext();
3455 return new(zone()) HStoreNamedGeneric( 3463 return new(zone()) HStoreNamedGeneric(
3456 context, 3464 context,
3457 object, 3465 object,
3458 name, 3466 name,
3459 value, 3467 value,
3460 function_strict_mode()); 3468 function_strict_mode_flag());
3461 } 3469 }
3462 3470
3463 3471
3464 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3472 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object,
3465 HValue* value, 3473 HValue* value,
3466 Expression* expr) { 3474 Expression* expr) {
3467 Property* prop = (expr->AsProperty() != NULL) 3475 Property* prop = (expr->AsProperty() != NULL)
3468 ? expr->AsProperty() 3476 ? expr->AsProperty()
3469 : expr->AsAssignment()->target()->AsProperty(); 3477 : expr->AsAssignment()->target()->AsProperty();
3470 Literal* key = prop->key()->AsLiteral(); 3478 Literal* key = prop->key()->AsLiteral();
3471 Handle<String> name = Handle<String>::cast(key->handle()); 3479 Handle<String> name = Handle<String>::cast(key->handle());
3472 ASSERT(!name.is_null()); 3480 ASSERT(!name.is_null());
3473 3481
3474 LookupResult lookup; 3482 LookupResult lookup(isolate());
3475 SmallMapList* types = expr->GetReceiverTypes(); 3483 SmallMapList* types = expr->GetReceiverTypes();
3476 bool is_monomorphic = expr->IsMonomorphic() && 3484 bool is_monomorphic = expr->IsMonomorphic() &&
3477 ComputeStoredField(types->first(), name, &lookup); 3485 ComputeStoredField(types->first(), name, &lookup);
3478 3486
3479 return is_monomorphic 3487 return is_monomorphic
3480 ? BuildStoreNamedField(object, name, value, types->first(), &lookup, 3488 ? BuildStoreNamedField(object, name, value, types->first(), &lookup,
3481 true) // Needs smi and map check. 3489 true) // Needs smi and map check.
3482 : BuildStoreNamedGeneric(object, name, value); 3490 : BuildStoreNamedGeneric(object, name, value);
3483 } 3491 }
3484 3492
3485 3493
3486 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3494 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3487 HValue* object, 3495 HValue* object,
3488 HValue* value, 3496 HValue* value,
3489 SmallMapList* types, 3497 SmallMapList* types,
3490 Handle<String> name) { 3498 Handle<String> name) {
3491 // TODO(ager): We should recognize when the prototype chains for different 3499 // TODO(ager): We should recognize when the prototype chains for different
3492 // maps are identical. In that case we can avoid repeatedly generating the 3500 // maps are identical. In that case we can avoid repeatedly generating the
3493 // same prototype map checks. 3501 // same prototype map checks.
3494 int count = 0; 3502 int count = 0;
3495 HBasicBlock* join = NULL; 3503 HBasicBlock* join = NULL;
3496 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 3504 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
3497 Handle<Map> map = types->at(i); 3505 Handle<Map> map = types->at(i);
3498 LookupResult lookup; 3506 LookupResult lookup(isolate());
3499 if (ComputeStoredField(map, name, &lookup)) { 3507 if (ComputeStoredField(map, name, &lookup)) {
3500 if (count == 0) { 3508 if (count == 0) {
3501 AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. 3509 AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once.
3502 join = graph()->CreateBasicBlock(); 3510 join = graph()->CreateBasicBlock();
3503 } 3511 }
3504 ++count; 3512 ++count;
3505 HBasicBlock* if_true = graph()->CreateBasicBlock(); 3513 HBasicBlock* if_true = graph()->CreateBasicBlock();
3506 HBasicBlock* if_false = graph()->CreateBasicBlock(); 3514 HBasicBlock* if_false = graph()->CreateBasicBlock();
3507 HCompareMap* compare = 3515 HCompareMap* compare =
3508 new(zone()) HCompareMap(object, map, if_true, if_false); 3516 new(zone()) HCompareMap(object, map, if_true, if_false);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
3571 // Named store. 3579 // Named store.
3572 CHECK_ALIVE(VisitForValue(expr->value())); 3580 CHECK_ALIVE(VisitForValue(expr->value()));
3573 value = Pop(); 3581 value = Pop();
3574 HValue* object = Pop(); 3582 HValue* object = Pop();
3575 3583
3576 Literal* key = prop->key()->AsLiteral(); 3584 Literal* key = prop->key()->AsLiteral();
3577 Handle<String> name = Handle<String>::cast(key->handle()); 3585 Handle<String> name = Handle<String>::cast(key->handle());
3578 ASSERT(!name.is_null()); 3586 ASSERT(!name.is_null());
3579 3587
3580 SmallMapList* types = expr->GetReceiverTypes(); 3588 SmallMapList* types = expr->GetReceiverTypes();
3581 LookupResult lookup; 3589 LookupResult lookup(isolate());
3582 3590
3583 if (expr->IsMonomorphic()) { 3591 if (expr->IsMonomorphic()) {
3584 instr = BuildStoreNamed(object, value, expr); 3592 instr = BuildStoreNamed(object, value, expr);
3585 3593
3586 } else if (types != NULL && types->length() > 1) { 3594 } else if (types != NULL && types->length() > 1) {
3587 HandlePolymorphicStoreNamedField(expr, object, value, types, name); 3595 HandlePolymorphicStoreNamedField(expr, object, value, types, name);
3588 return; 3596 return;
3589 3597
3590 } else { 3598 } else {
3591 instr = BuildStoreNamedGeneric(object, name, value); 3599 instr = BuildStoreNamedGeneric(object, name, value);
(...skipping 24 matching lines...) Expand all
3616 } 3624 }
3617 3625
3618 3626
3619 // Because not every expression has a position and there is not common 3627 // Because not every expression has a position and there is not common
3620 // superclass of Assignment and CountOperation, we cannot just pass the 3628 // superclass of Assignment and CountOperation, we cannot just pass the
3621 // owning expression instead of position and ast_id separately. 3629 // owning expression instead of position and ast_id separately.
3622 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3630 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3623 HValue* value, 3631 HValue* value,
3624 int position, 3632 int position,
3625 int ast_id) { 3633 int ast_id) {
3626 LookupResult lookup; 3634 LookupResult lookup(isolate());
3627 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 3635 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
3628 if (type == kUseCell) { 3636 if (type == kUseCell) {
3629 Handle<GlobalObject> global(info()->global_object()); 3637 Handle<GlobalObject> global(info()->global_object());
3630 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3638 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3631 HInstruction* instr = 3639 HInstruction* instr =
3632 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); 3640 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
3633 instr->set_position(position); 3641 instr->set_position(position);
3634 AddInstruction(instr); 3642 AddInstruction(instr);
3635 if (instr->HasSideEffects()) AddSimulate(ast_id); 3643 if (instr->HasSideEffects()) AddSimulate(ast_id);
3636 } else { 3644 } else {
3637 HValue* context = environment()->LookupContext(); 3645 HValue* context = environment()->LookupContext();
3638 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3646 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3639 AddInstruction(global_object); 3647 AddInstruction(global_object);
3640 HStoreGlobalGeneric* instr = 3648 HStoreGlobalGeneric* instr =
3641 new(zone()) HStoreGlobalGeneric(context, 3649 new(zone()) HStoreGlobalGeneric(context,
3642 global_object, 3650 global_object,
3643 var->name(), 3651 var->name(),
3644 value, 3652 value,
3645 function_strict_mode()); 3653 function_strict_mode_flag());
3646 instr->set_position(position); 3654 instr->set_position(position);
3647 AddInstruction(instr); 3655 AddInstruction(instr);
3648 ASSERT(instr->HasSideEffects()); 3656 ASSERT(instr->HasSideEffects());
3649 if (instr->HasSideEffects()) AddSimulate(ast_id); 3657 if (instr->HasSideEffects()) AddSimulate(ast_id);
3650 } 3658 }
3651 } 3659 }
3652 3660
3653 3661
3654 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3662 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3655 Expression* target = expr->target(); 3663 Expression* target = expr->target();
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
3931 Handle<Object> name = expr->key()->AsLiteral()->handle(); 3939 Handle<Object> name = expr->key()->AsLiteral()->handle();
3932 HValue* context = environment()->LookupContext(); 3940 HValue* context = environment()->LookupContext();
3933 return new(zone()) HLoadNamedGeneric(context, obj, name); 3941 return new(zone()) HLoadNamedGeneric(context, obj, name);
3934 } 3942 }
3935 3943
3936 3944
3937 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 3945 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj,
3938 Property* expr, 3946 Property* expr,
3939 Handle<Map> map, 3947 Handle<Map> map,
3940 Handle<String> name) { 3948 Handle<String> name) {
3941 LookupResult lookup; 3949 LookupResult lookup(isolate());
3942 map->LookupInDescriptors(NULL, *name, &lookup); 3950 map->LookupInDescriptors(NULL, *name, &lookup);
3943 if (lookup.IsProperty() && lookup.type() == FIELD) { 3951 if (lookup.IsProperty() && lookup.type() == FIELD) {
3944 return BuildLoadNamedField(obj, 3952 return BuildLoadNamedField(obj,
3945 expr, 3953 expr,
3946 map, 3954 map,
3947 &lookup, 3955 &lookup,
3948 true); 3956 true);
3949 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 3957 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) {
3950 AddInstruction(new(zone()) HCheckNonSmi(obj)); 3958 AddInstruction(new(zone()) HCheckNonSmi(obj));
3951 AddInstruction(new(zone()) HCheckMap(obj, map)); 3959 AddInstruction(new(zone()) HCheckMap(obj, map));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
4030 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); 4038 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
4031 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. 4039 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
4032 return new(zone()) HLoadKeyedFastElement(elements, checked_key); 4040 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
4033 } 4041 }
4034 } 4042 }
4035 4043
4036 4044
4037 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 4045 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
4038 HValue* key, 4046 HValue* key,
4039 HValue* val, 4047 HValue* val,
4040 Expression* expr, 4048 Handle<Map> map,
4041 bool is_store) { 4049 bool is_store) {
4042 ASSERT(expr->IsMonomorphic());
4043 Handle<Map> map = expr->GetMonomorphicReceiverType();
4044 AddInstruction(new(zone()) HCheckNonSmi(object));
4045 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); 4050 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
4046 bool fast_smi_only_elements = map->has_fast_smi_only_elements(); 4051 bool fast_smi_only_elements = map->has_fast_smi_only_elements();
4047 bool fast_elements = map->has_fast_elements(); 4052 bool fast_elements = map->has_fast_elements();
4048 bool fast_double_elements = map->has_fast_double_elements(); 4053 bool fast_double_elements = map->has_fast_double_elements();
4049 if (!fast_smi_only_elements && 4054 if (!fast_smi_only_elements &&
4050 !fast_elements && 4055 !fast_elements &&
4051 !fast_double_elements && 4056 !fast_double_elements &&
4052 !map->has_external_array_elements()) { 4057 !map->has_external_array_elements()) {
4053 return is_store ? BuildStoreKeyedGeneric(object, key, val) 4058 return is_store ? BuildStoreKeyedGeneric(object, key, val)
4054 : BuildLoadKeyedGeneric(object, key); 4059 : BuildLoadKeyedGeneric(object, key);
(...skipping 29 matching lines...) Expand all
4084 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, 4089 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
4085 HValue* key, 4090 HValue* key,
4086 HValue* val, 4091 HValue* val,
4087 Expression* prop, 4092 Expression* prop,
4088 int ast_id, 4093 int ast_id,
4089 int position, 4094 int position,
4090 bool is_store, 4095 bool is_store,
4091 bool* has_side_effects) { 4096 bool* has_side_effects) {
4092 *has_side_effects = false; 4097 *has_side_effects = false;
4093 AddInstruction(new(zone()) HCheckNonSmi(object)); 4098 AddInstruction(new(zone()) HCheckNonSmi(object));
4094 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
4095 SmallMapList* maps = prop->GetReceiverTypes(); 4099 SmallMapList* maps = prop->GetReceiverTypes();
4096 bool todo_external_array = false; 4100 bool todo_external_array = false;
4097 4101
4098 static const int kNumElementTypes = kElementsKindCount; 4102 static const int kNumElementTypes = kElementsKindCount;
4099 bool type_todo[kNumElementTypes]; 4103 bool type_todo[kNumElementTypes];
4100 for (int i = 0; i < kNumElementTypes; ++i) { 4104 for (int i = 0; i < kNumElementTypes; ++i) {
4101 type_todo[i] = false; 4105 type_todo[i] = false;
4102 } 4106 }
4103 4107
4108 // Elements_kind transition support.
4109 MapHandleList transition_target(maps->length());
4110 // Collect possible transition targets.
4111 MapHandleList possible_transitioned_maps(maps->length());
4104 for (int i = 0; i < maps->length(); ++i) { 4112 for (int i = 0; i < maps->length(); ++i) {
4105 ASSERT(maps->at(i)->IsMap()); 4113 Handle<Map> map = maps->at(i);
4106 type_todo[maps->at(i)->elements_kind()] = true; 4114 ElementsKind elements_kind = map->elements_kind();
4107 if (maps->at(i)->elements_kind() 4115 if (elements_kind == FAST_DOUBLE_ELEMENTS ||
4108 >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { 4116 elements_kind == FAST_ELEMENTS) {
4109 todo_external_array = true; 4117 possible_transitioned_maps.Add(map);
4118 }
4119 }
4120 // Get transition target for each map (NULL == no transition).
4121 for (int i = 0; i < maps->length(); ++i) {
4122 Handle<Map> map = maps->at(i);
4123 Handle<Map> transitioned_map =
4124 map->FindTransitionedMap(&possible_transitioned_maps);
4125 transition_target.Add(transitioned_map);
4126 }
4127
4128 int num_untransitionable_maps = 0;
4129 Handle<Map> untransitionable_map;
4130 for (int i = 0; i < maps->length(); ++i) {
4131 Handle<Map> map = maps->at(i);
4132 ASSERT(map->IsMap());
4133 if (!transition_target.at(i).is_null()) {
4134 object = AddInstruction(new(zone()) HTransitionElementsKind(
4135 object, map, transition_target.at(i)));
4136 } else {
4137 type_todo[map->elements_kind()] = true;
4138 if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) {
4139 todo_external_array = true;
4140 }
4141 num_untransitionable_maps++;
4142 untransitionable_map = map;
4110 } 4143 }
4111 } 4144 }
4112 4145
4146 // If only one map is left after transitioning, handle this case
4147 // monomorphically.
4148 if (num_untransitionable_maps == 1) {
4149 HInstruction* instr = AddInstruction(BuildMonomorphicElementAccess(
4150 object, key, val, untransitionable_map, is_store));
4151 *has_side_effects |= instr->HasSideEffects();
4152 instr->set_position(position);
4153 return is_store ? NULL : instr;
4154 }
4155
4156 AddInstruction(HCheckInstanceType::NewIsSpecObject(object));
4113 HBasicBlock* join = graph()->CreateBasicBlock(); 4157 HBasicBlock* join = graph()->CreateBasicBlock();
4114 4158
4115 HInstruction* elements_kind_instr = 4159 HInstruction* elements_kind_instr =
4116 AddInstruction(new(zone()) HElementsKind(object)); 4160 AddInstruction(new(zone()) HElementsKind(object));
4117 HCompareConstantEqAndBranch* elements_kind_branch = NULL; 4161 HCompareConstantEqAndBranch* elements_kind_branch = NULL;
4118 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 4162 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
4119 HLoadExternalArrayPointer* external_elements = NULL; 4163 HLoadExternalArrayPointer* external_elements = NULL;
4120 HInstruction* checked_key = NULL; 4164 HInstruction* checked_key = NULL;
4121 4165
4122 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, 4166 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
4234 HValue* key, 4278 HValue* key,
4235 HValue* val, 4279 HValue* val,
4236 Expression* expr, 4280 Expression* expr,
4237 int ast_id, 4281 int ast_id,
4238 int position, 4282 int position,
4239 bool is_store, 4283 bool is_store,
4240 bool* has_side_effects) { 4284 bool* has_side_effects) {
4241 ASSERT(!expr->IsPropertyName()); 4285 ASSERT(!expr->IsPropertyName());
4242 HInstruction* instr = NULL; 4286 HInstruction* instr = NULL;
4243 if (expr->IsMonomorphic()) { 4287 if (expr->IsMonomorphic()) {
4244 instr = BuildMonomorphicElementAccess(obj, key, val, expr, is_store); 4288 Handle<Map> map = expr->GetMonomorphicReceiverType();
4289 AddInstruction(new(zone()) HCheckNonSmi(obj));
4290 instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store);
4245 } else if (expr->GetReceiverTypes() != NULL && 4291 } else if (expr->GetReceiverTypes() != NULL &&
4246 !expr->GetReceiverTypes()->is_empty()) { 4292 !expr->GetReceiverTypes()->is_empty()) {
4247 return HandlePolymorphicElementAccess( 4293 return HandlePolymorphicElementAccess(
4248 obj, key, val, expr, ast_id, position, is_store, has_side_effects); 4294 obj, key, val, expr, ast_id, position, is_store, has_side_effects);
4249 } else { 4295 } else {
4250 if (is_store) { 4296 if (is_store) {
4251 instr = BuildStoreKeyedGeneric(obj, key, val); 4297 instr = BuildStoreKeyedGeneric(obj, key, val);
4252 } else { 4298 } else {
4253 instr = BuildLoadKeyedGeneric(obj, key); 4299 instr = BuildLoadKeyedGeneric(obj, key);
4254 } 4300 }
4255 } 4301 }
4256 instr->set_position(position); 4302 instr->set_position(position);
4257 AddInstruction(instr); 4303 AddInstruction(instr);
4258 *has_side_effects = instr->HasSideEffects(); 4304 *has_side_effects = instr->HasSideEffects();
4259 return instr; 4305 return instr;
4260 } 4306 }
4261 4307
4262 4308
4263 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 4309 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object,
4264 HValue* key, 4310 HValue* key,
4265 HValue* value) { 4311 HValue* value) {
4266 HValue* context = environment()->LookupContext(); 4312 HValue* context = environment()->LookupContext();
4267 return new(zone()) HStoreKeyedGeneric( 4313 return new(zone()) HStoreKeyedGeneric(
4268 context, 4314 context,
4269 object, 4315 object,
4270 key, 4316 key,
4271 value, 4317 value,
4272 function_strict_mode()); 4318 function_strict_mode_flag());
4273 } 4319 }
4274 4320
4275 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { 4321 bool HGraphBuilder::TryArgumentsAccess(Property* expr) {
4276 VariableProxy* proxy = expr->obj()->AsVariableProxy(); 4322 VariableProxy* proxy = expr->obj()->AsVariableProxy();
4277 if (proxy == NULL) return false; 4323 if (proxy == NULL) return false;
4278 if (!proxy->var()->IsStackAllocated()) return false; 4324 if (!proxy->var()->IsStackAllocated()) return false;
4279 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 4325 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
4280 return false; 4326 return false;
4281 } 4327 }
4282 4328
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
4504 if (reason == NULL) { 4550 if (reason == NULL) {
4505 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 4551 PrintF("Inlined %s called from %s.\n", *target_name, *caller_name);
4506 } else { 4552 } else {
4507 PrintF("Did not inline %s called from %s (%s).\n", 4553 PrintF("Did not inline %s called from %s (%s).\n",
4508 *target_name, *caller_name, reason); 4554 *target_name, *caller_name, reason);
4509 } 4555 }
4510 } 4556 }
4511 } 4557 }
4512 4558
4513 4559
4514 bool HGraphBuilder::TryInline(Call* expr) { 4560 bool HGraphBuilder::TryInline(Call* expr, bool drop_extra) {
4515 if (!FLAG_use_inlining) return false; 4561 if (!FLAG_use_inlining) return false;
4516 4562
4517 // The function call we are inlining is a method call if the call 4563 // The function call we are inlining is a method call if the call
4518 // is a property call. 4564 // is a property call.
4519 CallKind call_kind = (expr->expression()->AsProperty() == NULL) 4565 CallKind call_kind = (expr->expression()->AsProperty() == NULL)
4520 ? CALL_AS_FUNCTION 4566 ? CALL_AS_FUNCTION
4521 : CALL_AS_METHOD; 4567 : CALL_AS_METHOD;
4522 4568
4523 // Precondition: call is monomorphic and we have found a target with the 4569 // Precondition: call is monomorphic and we have found a target with the
4524 // appropriate arity. 4570 // appropriate arity.
4525 Handle<JSFunction> caller = info()->closure(); 4571 Handle<JSFunction> caller = info()->closure();
4526 Handle<JSFunction> target = expr->target(); 4572 Handle<JSFunction> target = expr->target();
4527 Handle<SharedFunctionInfo> target_shared(target->shared()); 4573 Handle<SharedFunctionInfo> target_shared(target->shared());
4528 4574
4529 // Do a quick check on source code length to avoid parsing large 4575 // Do a quick check on source code length to avoid parsing large
4530 // inlining candidates. 4576 // inlining candidates.
4531 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { 4577 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
4532 TraceInline(target, caller, "target text too big"); 4578 TraceInline(target, caller, "target text too big");
4533 return false; 4579 return false;
4534 } 4580 }
4535 4581
4536 // Target must be inlineable. 4582 // Target must be inlineable.
4537 if (!target->IsInlineable()) { 4583 if (!target->IsInlineable()) {
4538 TraceInline(target, caller, "target not inlineable"); 4584 TraceInline(target, caller, "target not inlineable");
4539 return false; 4585 return false;
4540 } 4586 }
4541 4587
4542 CompilationInfo* outer_info = info();
4543 #if !defined(V8_TARGET_ARCH_IA32) 4588 #if !defined(V8_TARGET_ARCH_IA32)
4544 // Target must be able to use caller's context. 4589 // Target must be able to use caller's context.
4590 CompilationInfo* outer_info = info();
4545 if (target->context() != outer_info->closure()->context() || 4591 if (target->context() != outer_info->closure()->context() ||
4546 outer_info->scope()->contains_with() || 4592 outer_info->scope()->contains_with() ||
4547 outer_info->scope()->num_heap_slots() > 0) { 4593 outer_info->scope()->num_heap_slots() > 0) {
4548 TraceInline(target, caller, "target requires context change"); 4594 TraceInline(target, caller, "target requires context change");
4549 return false; 4595 return false;
4550 } 4596 }
4551 #endif 4597 #endif
4552 4598
4553 4599
4554 // Don't inline deeper than kMaxInliningLevels calls. 4600 // Don't inline deeper than kMaxInliningLevels calls.
4555 HEnvironment* env = environment(); 4601 HEnvironment* env = environment();
4556 int current_level = 1; 4602 int current_level = 1;
4557 while (env->outer() != NULL) { 4603 while (env->outer() != NULL) {
4558 if (current_level == (FLAG_limit_inlining 4604 if (current_level == Compiler::kMaxInliningLevels) {
4559 ? Compiler::kMaxInliningLevels
4560 : 2 * Compiler::kMaxInliningLevels)) {
4561 TraceInline(target, caller, "inline depth limit reached"); 4605 TraceInline(target, caller, "inline depth limit reached");
4562 return false; 4606 return false;
4563 } 4607 }
4564 current_level++; 4608 current_level++;
4565 env = env->outer(); 4609 env = env->outer();
4566 } 4610 }
4567 4611
4568 // Don't inline recursive functions. 4612 // Don't inline recursive functions.
4569 if (*target_shared == outer_info->closure()->shared()) { 4613 for (FunctionState* state = function_state();
4570 TraceInline(target, caller, "target is recursive"); 4614 state != NULL;
4571 return false; 4615 state = state->outer()) {
4616 if (state->compilation_info()->closure()->shared() == *target_shared) {
4617 TraceInline(target, caller, "target is recursive");
4618 return false;
4619 }
4572 } 4620 }
4573 4621
4574 // We don't want to add more than a certain number of nodes from inlining. 4622 // We don't want to add more than a certain number of nodes from inlining.
4575 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 4623 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
4576 TraceInline(target, caller, "cumulative AST node limit reached"); 4624 TraceInline(target, caller, "cumulative AST node limit reached");
4577 return false; 4625 return false;
4578 } 4626 }
4579 4627
4580 int count_before = AstNode::Count(); 4628 int count_before = AstNode::Count();
4581 4629
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4658 // After this point, we've made a decision to inline this function (so 4706 // After this point, we've made a decision to inline this function (so
4659 // TryInline should always return true). 4707 // TryInline should always return true).
4660 4708
4661 // Save the pending call context and type feedback oracle. Set up new ones 4709 // Save the pending call context and type feedback oracle. Set up new ones
4662 // for the inlined function. 4710 // for the inlined function.
4663 ASSERT(target_shared->has_deoptimization_support()); 4711 ASSERT(target_shared->has_deoptimization_support());
4664 TypeFeedbackOracle target_oracle( 4712 TypeFeedbackOracle target_oracle(
4665 Handle<Code>(target_shared->code()), 4713 Handle<Code>(target_shared->code()),
4666 Handle<Context>(target->context()->global_context()), 4714 Handle<Context>(target->context()->global_context()),
4667 isolate()); 4715 isolate());
4668 FunctionState target_state(this, &target_info, &target_oracle); 4716 // The function state is new-allocated because we need to delete it
4717 // in two different places.
4718 FunctionState* target_state =
4719 new FunctionState(this, &target_info, &target_oracle, drop_extra);
4669 4720
4670 HConstant* undefined = graph()->GetConstantUndefined(); 4721 HConstant* undefined = graph()->GetConstantUndefined();
4671 HEnvironment* inner_env = 4722 HEnvironment* inner_env =
4672 environment()->CopyForInlining(target, 4723 environment()->CopyForInlining(target,
4673 function, 4724 function,
4674 undefined, 4725 undefined,
4675 call_kind); 4726 call_kind);
4676 #ifdef V8_TARGET_ARCH_IA32 4727 #ifdef V8_TARGET_ARCH_IA32
4677 // IA32 only, overwrite the caller's context in the deoptimization 4728 // IA32 only, overwrite the caller's context in the deoptimization
4678 // environment with the correct one. 4729 // environment with the correct one.
(...skipping 13 matching lines...) Expand all
4692 function, 4743 function,
4693 call_kind)); 4744 call_kind));
4694 VisitDeclarations(target_info.scope()->declarations()); 4745 VisitDeclarations(target_info.scope()->declarations());
4695 VisitStatements(function->body()); 4746 VisitStatements(function->body());
4696 if (HasStackOverflow()) { 4747 if (HasStackOverflow()) {
4697 // Bail out if the inline function did, as we cannot residualize a call 4748 // Bail out if the inline function did, as we cannot residualize a call
4698 // instead. 4749 // instead.
4699 TraceInline(target, caller, "inline graph construction failed"); 4750 TraceInline(target, caller, "inline graph construction failed");
4700 target_shared->DisableOptimization(*target); 4751 target_shared->DisableOptimization(*target);
4701 inline_bailout_ = true; 4752 inline_bailout_ = true;
4753 delete target_state;
4702 return true; 4754 return true;
4703 } 4755 }
4704 4756
4705 // Update inlined nodes count. 4757 // Update inlined nodes count.
4706 inlined_count_ += nodes_added; 4758 inlined_count_ += nodes_added;
4707 4759
4708 TraceInline(target, caller, NULL); 4760 TraceInline(target, caller, NULL);
4709 4761
4710 if (current_block() != NULL) { 4762 if (current_block() != NULL) {
4711 // Add a return of undefined if control can fall off the body. In a 4763 // Add a return of undefined if control can fall off the body. In a
4712 // test context, undefined is false. 4764 // test context, undefined is false.
4713 if (inlined_test_context() == NULL) { 4765 if (inlined_test_context() == NULL) {
4714 ASSERT(function_return() != NULL); 4766 ASSERT(function_return() != NULL);
4715 ASSERT(call_context()->IsEffect() || call_context()->IsValue()); 4767 ASSERT(call_context()->IsEffect() || call_context()->IsValue());
4716 if (call_context()->IsEffect()) { 4768 if (call_context()->IsEffect()) {
4717 current_block()->Goto(function_return()); 4769 current_block()->Goto(function_return(), drop_extra);
4718 } else { 4770 } else {
4719 current_block()->AddLeaveInlined(undefined, function_return()); 4771 current_block()->AddLeaveInlined(undefined,
4772 function_return(),
4773 drop_extra);
4720 } 4774 }
4721 } else { 4775 } else {
4722 // The graph builder assumes control can reach both branches of a 4776 // The graph builder assumes control can reach both branches of a
4723 // test, so we materialize the undefined value and test it rather than 4777 // test, so we materialize the undefined value and test it rather than
4724 // simply jumping to the false target. 4778 // simply jumping to the false target.
4725 // 4779 //
4726 // TODO(3168478): refactor to avoid this. 4780 // TODO(3168478): refactor to avoid this.
4781 ASSERT(call_context()->IsTest());
4727 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4782 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4728 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4783 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4729 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false); 4784 HBranch* test = new(zone()) HBranch(undefined, empty_true, empty_false);
4730 current_block()->Finish(test); 4785 current_block()->Finish(test);
4731 4786
4732 empty_true->Goto(inlined_test_context()->if_true()); 4787 empty_true->Goto(inlined_test_context()->if_true(), drop_extra);
4733 empty_false->Goto(inlined_test_context()->if_false()); 4788 empty_false->Goto(inlined_test_context()->if_false(), drop_extra);
4734 } 4789 }
4735 } 4790 }
4736 4791
4737 // Fix up the function exits. 4792 // Fix up the function exits.
4738 if (inlined_test_context() != NULL) { 4793 if (inlined_test_context() != NULL) {
4739 HBasicBlock* if_true = inlined_test_context()->if_true(); 4794 HBasicBlock* if_true = inlined_test_context()->if_true();
4740 HBasicBlock* if_false = inlined_test_context()->if_false(); 4795 HBasicBlock* if_false = inlined_test_context()->if_false();
4741 4796
4742 // Pop the return test context from the expression context stack. 4797 // Pop the return test context from the expression context stack.
4743 ASSERT(ast_context() == inlined_test_context()); 4798 ASSERT(ast_context() == inlined_test_context());
4744 ClearInlinedTestContext(); 4799 ClearInlinedTestContext();
4800 delete target_state;
4745 4801
4746 // Forward to the real test context. 4802 // Forward to the real test context.
4747 if (if_true->HasPredecessor()) { 4803 if (if_true->HasPredecessor()) {
4748 if_true->SetJoinId(expr->id()); 4804 if_true->SetJoinId(expr->id());
4749 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4805 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4750 if_true->Goto(true_target); 4806 if_true->Goto(true_target, function_state()->drop_extra());
4751 } 4807 }
4752 if (if_false->HasPredecessor()) { 4808 if (if_false->HasPredecessor()) {
4753 if_false->SetJoinId(expr->id()); 4809 if_false->SetJoinId(expr->id());
4754 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4810 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4755 if_false->Goto(false_target); 4811 if_false->Goto(false_target, function_state()->drop_extra());
4756 } 4812 }
4757 set_current_block(NULL); 4813 set_current_block(NULL);
4814 return true;
4758 4815
4759 } else if (function_return()->HasPredecessor()) { 4816 } else if (function_return()->HasPredecessor()) {
4760 function_return()->SetJoinId(expr->id()); 4817 function_return()->SetJoinId(expr->id());
4761 set_current_block(function_return()); 4818 set_current_block(function_return());
4762 } else { 4819 } else {
4763 set_current_block(NULL); 4820 set_current_block(NULL);
4764 } 4821 }
4765 4822 delete target_state;
4766 return true; 4823 return true;
4767 } 4824 }
4768 4825
4769 4826
4770 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, 4827 bool HGraphBuilder::TryInlineBuiltinFunction(Call* expr,
4771 HValue* receiver, 4828 HValue* receiver,
4772 Handle<Map> receiver_map, 4829 Handle<Map> receiver_map,
4773 CheckType check_type) { 4830 CheckType check_type) {
4774 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 4831 ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null());
4775 // Try to inline calls like Math.* as operations in the calling function. 4832 // Try to inline calls like Math.* as operations in the calling function.
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
5007 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); 5064 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
5008 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 5065 VariableProxy* proxy = expr->expression()->AsVariableProxy();
5009 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 5066 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
5010 5067
5011 if (global_call) { 5068 if (global_call) {
5012 Variable* var = proxy->var(); 5069 Variable* var = proxy->var();
5013 bool known_global_function = false; 5070 bool known_global_function = false;
5014 // If there is a global property cell for the name at compile time and 5071 // If there is a global property cell for the name at compile time and
5015 // access check is not enabled we assume that the function will not change 5072 // access check is not enabled we assume that the function will not change
5016 // and generate optimized code for calling the function. 5073 // and generate optimized code for calling the function.
5017 LookupResult lookup; 5074 LookupResult lookup(isolate());
5018 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 5075 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
5019 if (type == kUseCell && 5076 if (type == kUseCell &&
5020 !info()->global_object()->IsAccessCheckNeeded()) { 5077 !info()->global_object()->IsAccessCheckNeeded()) {
5021 Handle<GlobalObject> global(info()->global_object()); 5078 Handle<GlobalObject> global(info()->global_object());
5022 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 5079 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
5023 } 5080 }
5024 if (known_global_function) { 5081 if (known_global_function) {
5025 // Push the global object instead of the global receiver because 5082 // Push the global object instead of the global receiver because
5026 // code generated by the full code generator expects it. 5083 // code generated by the full code generator expects it.
5027 HValue* context = environment()->LookupContext(); 5084 HValue* context = environment()->LookupContext();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5062 // evaluation of the arguments. 5119 // evaluation of the arguments.
5063 CHECK_ALIVE(VisitForValue(expr->expression())); 5120 CHECK_ALIVE(VisitForValue(expr->expression()));
5064 HValue* function = Top(); 5121 HValue* function = Top();
5065 HValue* context = environment()->LookupContext(); 5122 HValue* context = environment()->LookupContext();
5066 HGlobalObject* global = new(zone()) HGlobalObject(context); 5123 HGlobalObject* global = new(zone()) HGlobalObject(context);
5067 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 5124 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
5068 AddInstruction(global); 5125 AddInstruction(global);
5069 PushAndAdd(receiver); 5126 PushAndAdd(receiver);
5070 CHECK_ALIVE(VisitExpressions(expr->arguments())); 5127 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5071 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 5128 AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5072 if (TryInline(expr)) { 5129 if (TryInline(expr, true)) { // Drop function from environment.
5073 // The function is lingering in the deoptimization environment.
5074 // Handle it by case analysis on the AST context.
5075 if (ast_context()->IsEffect()) {
5076 Drop(1);
5077 } else if (ast_context()->IsValue()) {
5078 HValue* result = Pop();
5079 Drop(1);
5080 Push(result);
5081 } else if (ast_context()->IsTest()) {
5082 TestContext* context = TestContext::cast(ast_context());
5083 if (context->if_true()->HasPredecessor()) {
5084 context->if_true()->last_environment()->Drop(1);
5085 }
5086 if (context->if_false()->HasPredecessor()) {
5087 context->if_true()->last_environment()->Drop(1);
5088 }
5089 } else {
5090 UNREACHABLE();
5091 }
5092 return; 5130 return;
5093 } else { 5131 } else {
5094 call = PreProcessCall(new(zone()) HInvokeFunction(context, 5132 call = PreProcessCall(new(zone()) HInvokeFunction(context,
5095 function, 5133 function,
5096 argument_count)); 5134 argument_count));
5135 call->set_position(expr->position());
5136 AddInstruction(call);
5137 AddSimulate(expr->id());
5097 Drop(1); // The function. 5138 Drop(1); // The function.
5139 return ast_context()->ReturnValue(call);
5098 } 5140 }
5099 5141
5100 } else { 5142 } else {
5101 CHECK_ALIVE(VisitArgument(expr->expression())); 5143 CHECK_ALIVE(VisitArgument(expr->expression()));
5102 HValue* context = environment()->LookupContext(); 5144 HValue* context = environment()->LookupContext();
5103 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 5145 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
5104 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); 5146 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
5105 AddInstruction(global_object); 5147 AddInstruction(global_object);
5106 AddInstruction(receiver); 5148 AddInstruction(receiver);
5107 PushAndAdd(new(zone()) HPushArgument(receiver)); 5149 PushAndAdd(new(zone()) HPushArgument(receiver));
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
5297 if (info.IsUninitialized()) { 5339 if (info.IsUninitialized()) {
5298 AddInstruction(new(zone()) HSoftDeoptimize); 5340 AddInstruction(new(zone()) HSoftDeoptimize);
5299 current_block()->MarkAsDeoptimizing(); 5341 current_block()->MarkAsDeoptimizing();
5300 } 5342 }
5301 HInstruction* instr = new(zone()) HBitNot(value); 5343 HInstruction* instr = new(zone()) HBitNot(value);
5302 return ast_context()->ReturnInstruction(instr, expr->id()); 5344 return ast_context()->ReturnInstruction(instr, expr->id());
5303 } 5345 }
5304 5346
5305 5347
5306 void HGraphBuilder::VisitNot(UnaryOperation* expr) { 5348 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
5307 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
5308 if (ast_context()->IsTest()) { 5349 if (ast_context()->IsTest()) {
5309 TestContext* context = TestContext::cast(ast_context()); 5350 TestContext* context = TestContext::cast(ast_context());
5310 VisitForControl(expr->expression(), 5351 VisitForControl(expr->expression(),
5311 context->if_false(), 5352 context->if_false(),
5312 context->if_true()); 5353 context->if_true());
5313 return; 5354 return;
5314 } 5355 }
5315 5356
5316 if (ast_context()->IsEffect()) { 5357 if (ast_context()->IsEffect()) {
5317 VisitForEffect(expr->expression()); 5358 VisitForEffect(expr->expression());
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after
5784 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { 5825 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
5785 if (info.IsSmi()) return Representation::Integer32(); 5826 if (info.IsSmi()) return Representation::Integer32();
5786 if (info.IsInteger32()) return Representation::Integer32(); 5827 if (info.IsInteger32()) return Representation::Integer32();
5787 if (info.IsDouble()) return Representation::Double(); 5828 if (info.IsDouble()) return Representation::Double();
5788 if (info.IsNumber()) return Representation::Double(); 5829 if (info.IsNumber()) return Representation::Double();
5789 return Representation::Tagged(); 5830 return Representation::Tagged();
5790 } 5831 }
5791 5832
5792 5833
5793 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 5834 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
5794 Expression* sub_expr, 5835 HTypeof* typeof_expr,
5795 Handle<String> check) { 5836 Handle<String> check) {
5796 CHECK_ALIVE(VisitForTypeOf(sub_expr)); 5837 // Note: The HTypeof itself is removed during canonicalization, if possible.
5797 HValue* value = Pop(); 5838 HValue* value = typeof_expr->value();
5798 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 5839 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
5799 instr->set_position(expr->position()); 5840 instr->set_position(expr->position());
5800 return ast_context()->ReturnControl(instr, expr->id()); 5841 return ast_context()->ReturnControl(instr, expr->id());
5801 } 5842 }
5802 5843
5803 5844
5804 bool HGraphBuilder::TryLiteralCompare(CompareOperation* expr) { 5845 static bool MatchLiteralCompareNil(HValue* left,
5805 Expression *sub_expr; 5846 Token::Value op,
5806 Handle<String> check; 5847 HValue* right,
5807 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { 5848 Handle<Object> nil,
5808 HandleLiteralCompareTypeof(expr, sub_expr, check); 5849 HValue** expr) {
5850 if (left->IsConstant() &&
5851 HConstant::cast(left)->handle().is_identical_to(nil) &&
5852 Token::IsEqualityOp(op)) {
5853 *expr = right;
5809 return true; 5854 return true;
5810 } 5855 }
5856 return false;
5857 }
5811 5858
5812 if (expr->IsLiteralCompareUndefined(&sub_expr)) { 5859
5813 HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); 5860 static bool MatchLiteralCompareTypeof(HValue* left,
5861 Token::Value op,
5862 HValue* right,
5863 HTypeof** typeof_expr,
5864 Handle<String>* check) {
5865 if (left->IsTypeof() &&
5866 Token::IsEqualityOp(op) &&
5867 right->IsConstant() &&
5868 HConstant::cast(right)->HasStringValue()) {
5869 *typeof_expr = HTypeof::cast(left);
5870 *check = Handle<String>::cast(HConstant::cast(right)->handle());
5814 return true; 5871 return true;
5815 } 5872 }
5873 return false;
5874 }
5816 5875
5817 if (expr->IsLiteralCompareNull(&sub_expr)) {
5818 HandleLiteralCompareNil(expr, sub_expr, kNullValue);
5819 return true;
5820 }
5821 5876
5822 return false; 5877 static bool IsLiteralCompareTypeof(HValue* left,
5878 Token::Value op,
5879 HValue* right,
5880 HTypeof** typeof_expr,
5881 Handle<String>* check) {
5882 return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) ||
5883 MatchLiteralCompareTypeof(right, op, left, typeof_expr, check);
5884 }
5885
5886
5887 static bool IsLiteralCompareNil(HValue* left,
5888 Token::Value op,
5889 HValue* right,
5890 Handle<Object> nil,
5891 HValue** expr) {
5892 return MatchLiteralCompareNil(left, op, right, nil, expr) ||
5893 MatchLiteralCompareNil(right, op, left, nil, expr);
5823 } 5894 }
5824 5895
5825 5896
5826 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 5897 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5827 ASSERT(!HasStackOverflow()); 5898 ASSERT(!HasStackOverflow());
5828 ASSERT(current_block() != NULL); 5899 ASSERT(current_block() != NULL);
5829 ASSERT(current_block()->HasPredecessor()); 5900 ASSERT(current_block()->HasPredecessor());
5830 if (IsClassOfTest(expr)) { 5901 if (IsClassOfTest(expr)) {
5831 CallRuntime* call = expr->left()->AsCallRuntime(); 5902 CallRuntime* call = expr->left()->AsCallRuntime();
5832 ASSERT(call->arguments()->length() == 1); 5903 ASSERT(call->arguments()->length() == 1);
5833 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5904 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5834 HValue* value = Pop(); 5905 HValue* value = Pop();
5835 Literal* literal = expr->right()->AsLiteral(); 5906 Literal* literal = expr->right()->AsLiteral();
5836 Handle<String> rhs = Handle<String>::cast(literal->handle()); 5907 Handle<String> rhs = Handle<String>::cast(literal->handle());
5837 HClassOfTestAndBranch* instr = 5908 HClassOfTestAndBranch* instr =
5838 new(zone()) HClassOfTestAndBranch(value, rhs); 5909 new(zone()) HClassOfTestAndBranch(value, rhs);
5839 instr->set_position(expr->position()); 5910 instr->set_position(expr->position());
5840 return ast_context()->ReturnControl(instr, expr->id()); 5911 return ast_context()->ReturnControl(instr, expr->id());
5841 } 5912 }
5842 5913
5843 // Check for special cases that compare against literals.
5844 if (TryLiteralCompare(expr)) return;
5845
5846 TypeInfo type_info = oracle()->CompareType(expr); 5914 TypeInfo type_info = oracle()->CompareType(expr);
5847 // Check if this expression was ever executed according to type feedback. 5915 // Check if this expression was ever executed according to type feedback.
5916 // Note that for the special typeof/null/undefined cases we get unknown here.
5848 if (type_info.IsUninitialized()) { 5917 if (type_info.IsUninitialized()) {
5849 AddInstruction(new(zone()) HSoftDeoptimize); 5918 AddInstruction(new(zone()) HSoftDeoptimize);
5850 current_block()->MarkAsDeoptimizing(); 5919 current_block()->MarkAsDeoptimizing();
5851 type_info = TypeInfo::Unknown(); 5920 type_info = TypeInfo::Unknown();
5852 } 5921 }
5853 5922
5854 CHECK_ALIVE(VisitForValue(expr->left())); 5923 CHECK_ALIVE(VisitForValue(expr->left()));
5855 CHECK_ALIVE(VisitForValue(expr->right())); 5924 CHECK_ALIVE(VisitForValue(expr->right()));
5856 5925
5857 HValue* context = environment()->LookupContext(); 5926 HValue* context = environment()->LookupContext();
5858 HValue* right = Pop(); 5927 HValue* right = Pop();
5859 HValue* left = Pop(); 5928 HValue* left = Pop();
5860 Token::Value op = expr->op(); 5929 Token::Value op = expr->op();
5861 5930
5931 HTypeof* typeof_expr = NULL;
5932 Handle<String> check;
5933 if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) {
5934 return HandleLiteralCompareTypeof(expr, typeof_expr, check);
5935 }
5936 HValue* sub_expr = NULL;
5937 Factory* f = graph()->isolate()->factory();
5938 if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) {
5939 return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
5940 }
5941 if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) {
5942 return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
5943 }
5944
5862 if (op == Token::INSTANCEOF) { 5945 if (op == Token::INSTANCEOF) {
5863 // Check to see if the rhs of the instanceof is a global function not 5946 // Check to see if the rhs of the instanceof is a global function not
5864 // residing in new space. If it is we assume that the function will stay the 5947 // residing in new space. If it is we assume that the function will stay the
5865 // same. 5948 // same.
5866 Handle<JSFunction> target = Handle<JSFunction>::null(); 5949 Handle<JSFunction> target = Handle<JSFunction>::null();
5867 VariableProxy* proxy = expr->right()->AsVariableProxy(); 5950 VariableProxy* proxy = expr->right()->AsVariableProxy();
5868 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); 5951 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
5869 if (global_function && 5952 if (global_function &&
5870 info()->has_global_object() && 5953 info()->has_global_object() &&
5871 !info()->global_object()->IsAccessCheckNeeded()) { 5954 !info()->global_object()->IsAccessCheckNeeded()) {
5872 Handle<String> name = proxy->name(); 5955 Handle<String> name = proxy->name();
5873 Handle<GlobalObject> global(info()->global_object()); 5956 Handle<GlobalObject> global(info()->global_object());
5874 LookupResult lookup; 5957 LookupResult lookup(isolate());
5875 global->Lookup(*name, &lookup); 5958 global->Lookup(*name, &lookup);
5876 if (lookup.IsProperty() && 5959 if (lookup.IsProperty() &&
5877 lookup.type() == NORMAL && 5960 lookup.type() == NORMAL &&
5878 lookup.GetValue()->IsJSFunction()) { 5961 lookup.GetValue()->IsJSFunction()) {
5879 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5962 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5880 // If the function is in new space we assume it's more likely to 5963 // If the function is in new space we assume it's more likely to
5881 // change and thus prefer the general IC code. 5964 // change and thus prefer the general IC code.
5882 if (!isolate()->heap()->InNewSpace(*candidate)) { 5965 if (!isolate()->heap()->InNewSpace(*candidate)) {
5883 target = candidate; 5966 target = candidate;
5884 } 5967 }
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
5940 new(zone()) HCompareIDAndBranch(left, right, op); 6023 new(zone()) HCompareIDAndBranch(left, right, op);
5941 result->set_position(expr->position()); 6024 result->set_position(expr->position());
5942 result->SetInputRepresentation(r); 6025 result->SetInputRepresentation(r);
5943 return ast_context()->ReturnControl(result, expr->id()); 6026 return ast_context()->ReturnControl(result, expr->id());
5944 } 6027 }
5945 } 6028 }
5946 } 6029 }
5947 6030
5948 6031
5949 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 6032 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
5950 Expression* sub_expr, 6033 HValue* value,
5951 NilValue nil) { 6034 NilValue nil) {
5952 ASSERT(!HasStackOverflow()); 6035 ASSERT(!HasStackOverflow());
5953 ASSERT(current_block() != NULL); 6036 ASSERT(current_block() != NULL);
5954 ASSERT(current_block()->HasPredecessor()); 6037 ASSERT(current_block()->HasPredecessor());
5955 CHECK_ALIVE(VisitForValue(sub_expr));
5956 HValue* value = Pop();
5957 EqualityKind kind = 6038 EqualityKind kind =
5958 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; 6039 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality;
5959 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); 6040 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil);
5960 instr->set_position(expr->position()); 6041 instr->set_position(expr->position());
5961 return ast_context()->ReturnControl(instr, expr->id()); 6042 return ast_context()->ReturnControl(instr, expr->id());
5962 } 6043 }
5963 6044
5964 6045
5965 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 6046 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
5966 ASSERT(!HasStackOverflow()); 6047 ASSERT(!HasStackOverflow());
5967 ASSERT(current_block() != NULL); 6048 ASSERT(current_block() != NULL);
5968 ASSERT(current_block()->HasPredecessor()); 6049 ASSERT(current_block()->HasPredecessor());
5969 HThisFunction* self = new(zone()) HThisFunction; 6050 HThisFunction* self = new(zone()) HThisFunction(
6051 function_state()->compilation_info()->closure());
5970 return ast_context()->ReturnInstruction(self, expr->id()); 6052 return ast_context()->ReturnInstruction(self, expr->id());
5971 } 6053 }
5972 6054
5973 6055
5974 void HGraphBuilder::VisitDeclaration(Declaration* decl) { 6056 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
5975 HandleDeclaration(decl->proxy(), decl->mode(), decl->fun()); 6057 HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
5976 } 6058 }
5977 6059
5978 6060
5979 void HGraphBuilder::HandleDeclaration(VariableProxy* proxy, 6061 void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
5980 VariableMode mode, 6062 VariableMode mode,
5981 FunctionLiteral* function) { 6063 FunctionLiteral* function) {
5982 if (mode == LET) return Bailout("unsupported let declaration"); 6064 if (mode == LET || mode == CONST_HARMONY) {
6065 return Bailout("unsupported harmony declaration");
6066 }
5983 Variable* var = proxy->var(); 6067 Variable* var = proxy->var();
5984 switch (var->location()) { 6068 switch (var->location()) {
5985 case Variable::UNALLOCATED: 6069 case Variable::UNALLOCATED:
5986 return Bailout("unsupported global declaration"); 6070 return Bailout("unsupported global declaration");
5987 case Variable::PARAMETER: 6071 case Variable::PARAMETER:
5988 case Variable::LOCAL: 6072 case Variable::LOCAL:
5989 case Variable::CONTEXT: 6073 case Variable::CONTEXT:
5990 if (mode == CONST || function != NULL) { 6074 if (mode == CONST || function != NULL) {
5991 HValue* value = NULL; 6075 HValue* value = NULL;
5992 if (mode == CONST) { 6076 if (mode == CONST) {
(...skipping 946 matching lines...) Expand 10 before | Expand all | Expand 10 after
6939 } 7023 }
6940 } 7024 }
6941 7025
6942 #ifdef DEBUG 7026 #ifdef DEBUG
6943 if (graph_ != NULL) graph_->Verify(false); // No full verify. 7027 if (graph_ != NULL) graph_->Verify(false); // No full verify.
6944 if (allocator_ != NULL) allocator_->Verify(); 7028 if (allocator_ != NULL) allocator_->Verify();
6945 #endif 7029 #endif
6946 } 7030 }
6947 7031
6948 } } // namespace v8::internal 7032 } } // 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