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

Side by Side Diff: src/hydrogen.cc

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 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 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 } 415 }
416 } 416 }
417 417
418 int visited_count_; 418 int visited_count_;
419 ZoneList<HBasicBlock*> stack_; 419 ZoneList<HBasicBlock*> stack_;
420 BitVector reachable_; 420 BitVector reachable_;
421 HBasicBlock* dont_visit_; 421 HBasicBlock* dont_visit_;
422 }; 422 };
423 423
424 424
425 void HGraph::Verify() const { 425 void HGraph::Verify(bool do_full_verify) const {
426 for (int i = 0; i < blocks_.length(); i++) { 426 for (int i = 0; i < blocks_.length(); i++) {
427 HBasicBlock* block = blocks_.at(i); 427 HBasicBlock* block = blocks_.at(i);
428 428
429 block->Verify(); 429 block->Verify();
430 430
431 // Check that every block contains at least one node and that only the last 431 // Check that every block contains at least one node and that only the last
432 // node is a control instruction. 432 // node is a control instruction.
433 HInstruction* current = block->first(); 433 HInstruction* current = block->first();
434 ASSERT(current != NULL && current->IsBlockEntry()); 434 ASSERT(current != NULL && current->IsBlockEntry());
435 while (current != NULL) { 435 while (current != NULL) {
(...skipping 30 matching lines...) Expand all
466 HBasicBlock* predecessor = block->predecessors()->at(k); 466 HBasicBlock* predecessor = block->predecessors()->at(k);
467 ASSERT(predecessor->end()->IsGoto()); 467 ASSERT(predecessor->end()->IsGoto());
468 ASSERT(predecessor->last_environment()->ast_id() == id); 468 ASSERT(predecessor->last_environment()->ast_id() == id);
469 } 469 }
470 } 470 }
471 } 471 }
472 472
473 // Check special property of first block to have no predecessors. 473 // Check special property of first block to have no predecessors.
474 ASSERT(blocks_.at(0)->predecessors()->is_empty()); 474 ASSERT(blocks_.at(0)->predecessors()->is_empty());
475 475
476 // Check that the graph is fully connected. 476 if (do_full_verify) {
477 ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); 477 // Check that the graph is fully connected.
478 ASSERT(analyzer.visited_count() == blocks_.length()); 478 ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
479 ASSERT(analyzer.visited_count() == blocks_.length());
479 480
480 // Check that entry block dominator is NULL. 481 // Check that entry block dominator is NULL.
481 ASSERT(entry_block_->dominator() == NULL); 482 ASSERT(entry_block_->dominator() == NULL);
482 483
483 // Check dominators. 484 // Check dominators.
484 for (int i = 0; i < blocks_.length(); ++i) { 485 for (int i = 0; i < blocks_.length(); ++i) {
485 HBasicBlock* block = blocks_.at(i); 486 HBasicBlock* block = blocks_.at(i);
486 if (block->dominator() == NULL) { 487 if (block->dominator() == NULL) {
487 // Only start block may have no dominator assigned to. 488 // Only start block may have no dominator assigned to.
488 ASSERT(i == 0); 489 ASSERT(i == 0);
489 } else { 490 } else {
490 // Assert that block is unreachable if dominator must not be visited. 491 // Assert that block is unreachable if dominator must not be visited.
491 ReachabilityAnalyzer dominator_analyzer(entry_block_, 492 ReachabilityAnalyzer dominator_analyzer(entry_block_,
492 blocks_.length(), 493 blocks_.length(),
493 block->dominator()); 494 block->dominator());
494 ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id())); 495 ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id()));
496 }
495 } 497 }
496 } 498 }
497 } 499 }
498 500
499 #endif 501 #endif
500 502
501 503
502 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, 504 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
503 Object* value) { 505 Object* value) {
504 if (!pointer->is_set()) { 506 if (!pointer->is_set()) {
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
843 HPhi* phi = phi_list[i]; 845 HPhi* phi = phi_list[i];
844 if (!phi->is_live()) { 846 if (!phi->is_live()) {
845 HBasicBlock* block = phi->block(); 847 HBasicBlock* block = phi->block();
846 block->RemovePhi(phi); 848 block->RemovePhi(phi);
847 block->RecordDeletedPhi(phi->merged_index()); 849 block->RecordDeletedPhi(phi->merged_index());
848 } 850 }
849 } 851 }
850 } 852 }
851 853
852 854
853 bool HGraph::CheckPhis() { 855 bool HGraph::CheckArgumentsPhiUses() {
854 int block_count = blocks_.length(); 856 int block_count = blocks_.length();
855 for (int i = 0; i < block_count; ++i) { 857 for (int i = 0; i < block_count; ++i) {
856 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 858 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
857 HPhi* phi = blocks_[i]->phis()->at(j); 859 HPhi* phi = blocks_[i]->phis()->at(j);
858 // We don't support phi uses of arguments for now. 860 // We don't support phi uses of arguments for now.
859 if (phi->CheckFlag(HValue::kIsArguments)) return false; 861 if (phi->CheckFlag(HValue::kIsArguments)) return false;
860 } 862 }
861 } 863 }
862 return true; 864 return true;
863 } 865 }
864 866
865 867
866 bool HGraph::CollectPhis() { 868 bool HGraph::CheckConstPhiUses() {
867 int block_count = blocks_.length(); 869 int block_count = blocks_.length();
868 phi_list_ = new ZoneList<HPhi*>(block_count);
869 for (int i = 0; i < block_count; ++i) { 870 for (int i = 0; i < block_count; ++i) {
870 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 871 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
871 HPhi* phi = blocks_[i]->phis()->at(j); 872 HPhi* phi = blocks_[i]->phis()->at(j);
872 phi_list_->Add(phi);
873 // Check for the hole value (from an uninitialized const). 873 // Check for the hole value (from an uninitialized const).
874 for (int k = 0; k < phi->OperandCount(); k++) { 874 for (int k = 0; k < phi->OperandCount(); k++) {
875 if (phi->OperandAt(k) == GetConstantHole()) return false; 875 if (phi->OperandAt(k) == GetConstantHole()) return false;
876 } 876 }
877 } 877 }
878 } 878 }
879 return true; 879 return true;
880 } 880 }
881 881
882 882
883 void HGraph::CollectPhis() {
884 int block_count = blocks_.length();
885 phi_list_ = new ZoneList<HPhi*>(block_count);
886 for (int i = 0; i < block_count; ++i) {
887 for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
888 HPhi* phi = blocks_[i]->phis()->at(j);
889 phi_list_->Add(phi);
890 }
891 }
892 }
893
894
883 void HGraph::InferTypes(ZoneList<HValue*>* worklist) { 895 void HGraph::InferTypes(ZoneList<HValue*>* worklist) {
884 BitVector in_worklist(GetMaximumValueID()); 896 BitVector in_worklist(GetMaximumValueID());
885 for (int i = 0; i < worklist->length(); ++i) { 897 for (int i = 0; i < worklist->length(); ++i) {
886 ASSERT(!in_worklist.Contains(worklist->at(i)->id())); 898 ASSERT(!in_worklist.Contains(worklist->at(i)->id()));
887 in_worklist.Add(worklist->at(i)->id()); 899 in_worklist.Add(worklist->at(i)->id());
888 } 900 }
889 901
890 while (!worklist->is_empty()) { 902 while (!worklist->is_empty()) {
891 HValue* current = worklist->RemoveLast(); 903 HValue* current = worklist->RemoveLast();
892 in_worklist.Remove(current->id()); 904 in_worklist.Remove(current->id());
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after
1841 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); 1853 use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
1842 if (value->IsConstant()) { 1854 if (value->IsConstant()) {
1843 HConstant* constant = HConstant::cast(value); 1855 HConstant* constant = HConstant::cast(value);
1844 // Try to create a new copy of the constant with the new representation. 1856 // Try to create a new copy of the constant with the new representation.
1845 new_value = is_truncating 1857 new_value = is_truncating
1846 ? constant->CopyToTruncatedInt32() 1858 ? constant->CopyToTruncatedInt32()
1847 : constant->CopyToRepresentation(to); 1859 : constant->CopyToRepresentation(to);
1848 } 1860 }
1849 1861
1850 if (new_value == NULL) { 1862 if (new_value == NULL) {
1851 new_value = new(zone()) HChange(value, value->representation(), to, 1863 new_value = new(zone()) HChange(value, to,
1852 is_truncating, deoptimize_on_undefined); 1864 is_truncating, deoptimize_on_undefined);
1853 } 1865 }
1854 1866
1855 new_value->InsertBefore(next); 1867 new_value->InsertBefore(next);
1856 use_value->SetOperandAt(use_index, new_value); 1868 use_value->SetOperandAt(use_index, new_value);
1857 } 1869 }
1858 1870
1859 1871
1860 void HGraph::InsertRepresentationChangesForValue(HValue* value) { 1872 void HGraph::InsertRepresentationChangesForValue(HValue* value) {
1861 Representation r = value->representation(); 1873 Representation r = value->representation();
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
2313 2325
2314 if (current_block() != NULL) { 2326 if (current_block() != NULL) {
2315 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); 2327 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
2316 current_block()->FinishExit(instr); 2328 current_block()->FinishExit(instr);
2317 set_current_block(NULL); 2329 set_current_block(NULL);
2318 } 2330 }
2319 } 2331 }
2320 2332
2321 graph()->OrderBlocks(); 2333 graph()->OrderBlocks();
2322 graph()->AssignDominators(); 2334 graph()->AssignDominators();
2335
2336 #ifdef DEBUG
2337 // Do a full verify after building the graph and computing dominators.
2338 graph()->Verify(true);
2339 #endif
2340
2323 graph()->PropagateDeoptimizingMark(); 2341 graph()->PropagateDeoptimizingMark();
2342 if (!graph()->CheckConstPhiUses()) {
2343 Bailout("Unsupported phi use of const variable");
2344 return NULL;
2345 }
2324 graph()->EliminateRedundantPhis(); 2346 graph()->EliminateRedundantPhis();
2325 if (!graph()->CheckPhis()) { 2347 if (!graph()->CheckArgumentsPhiUses()) {
2326 Bailout("Unsupported phi use of arguments object"); 2348 Bailout("Unsupported phi use of arguments");
2327 return NULL; 2349 return NULL;
2328 } 2350 }
2329 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); 2351 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis();
2330 if (!graph()->CollectPhis()) { 2352 graph()->CollectPhis();
2331 Bailout("Unsupported phi use of uninitialized constant");
2332 return NULL;
2333 }
2334 2353
2335 HInferRepresentation rep(graph()); 2354 HInferRepresentation rep(graph());
2336 rep.Analyze(); 2355 rep.Analyze();
2337 2356
2338 graph()->MarkDeoptimizeOnUndefined(); 2357 graph()->MarkDeoptimizeOnUndefined();
2339 graph()->InsertRepresentationChanges(); 2358 graph()->InsertRepresentationChanges();
2340 2359
2341 graph()->InitializeInferredTypes(); 2360 graph()->InitializeInferredTypes();
2342 graph()->Canonicalize(); 2361 graph()->Canonicalize();
2343 2362
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3139 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3121 ASSERT(!HasStackOverflow()); 3140 ASSERT(!HasStackOverflow());
3122 ASSERT(current_block() != NULL); 3141 ASSERT(current_block() != NULL);
3123 ASSERT(current_block()->HasPredecessor()); 3142 ASSERT(current_block()->HasPredecessor());
3124 Variable* variable = expr->var(); 3143 Variable* variable = expr->var();
3125 if (variable->mode() == Variable::LET) { 3144 if (variable->mode() == Variable::LET) {
3126 return Bailout("reference to let variable"); 3145 return Bailout("reference to let variable");
3127 } 3146 }
3128 switch (variable->location()) { 3147 switch (variable->location()) {
3129 case Variable::UNALLOCATED: { 3148 case Variable::UNALLOCATED: {
3149 // Handle known global constants like 'undefined' specially to avoid a
3150 // load from a global cell for them.
3151 Handle<Object> constant_value =
3152 isolate()->factory()->GlobalConstantFor(variable->name());
3153 if (!constant_value.is_null()) {
3154 HConstant* instr =
3155 new(zone()) HConstant(constant_value, Representation::Tagged());
3156 return ast_context()->ReturnInstruction(instr, expr->id());
3157 }
3158
3130 LookupResult lookup; 3159 LookupResult lookup;
3131 GlobalPropertyAccess type = 3160 GlobalPropertyAccess type =
3132 LookupGlobalProperty(variable, &lookup, false); 3161 LookupGlobalProperty(variable, &lookup, false);
3133 3162
3134 if (type == kUseCell && 3163 if (type == kUseCell &&
3135 info()->global_object()->IsAccessCheckNeeded()) { 3164 info()->global_object()->IsAccessCheckNeeded()) {
3136 type = kUseGeneric; 3165 type = kUseGeneric;
3137 } 3166 }
3138 3167
3139 if (type == kUseCell) { 3168 if (type == kUseCell) {
3140 Handle<GlobalObject> global(info()->global_object()); 3169 Handle<GlobalObject> global(info()->global_object());
3141 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3170 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3142 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3171 HLoadGlobalCell* instr =
3143 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); 3172 new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails());
3144 return ast_context()->ReturnInstruction(instr, expr->id()); 3173 return ast_context()->ReturnInstruction(instr, expr->id());
3145 } else { 3174 } else {
3146 HValue* context = environment()->LookupContext(); 3175 HValue* context = environment()->LookupContext();
3147 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3176 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3148 AddInstruction(global_object); 3177 AddInstruction(global_object);
3149 HLoadGlobalGeneric* instr = 3178 HLoadGlobalGeneric* instr =
3150 new(zone()) HLoadGlobalGeneric(context, 3179 new(zone()) HLoadGlobalGeneric(context,
3151 global_object, 3180 global_object,
3152 variable->name(), 3181 variable->name(),
3153 ast_context()->is_for_typeof()); 3182 ast_context()->is_for_typeof());
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
3310 3339
3311 // Load the elements array before the first store. 3340 // Load the elements array before the first store.
3312 if (elements == NULL) { 3341 if (elements == NULL) {
3313 elements = new(zone()) HLoadElements(literal); 3342 elements = new(zone()) HLoadElements(literal);
3314 AddInstruction(elements); 3343 AddInstruction(elements);
3315 } 3344 }
3316 3345
3317 HValue* key = AddInstruction( 3346 HValue* key = AddInstruction(
3318 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 3347 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)),
3319 Representation::Integer32())); 3348 Representation::Integer32()));
3320 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); 3349 if (FLAG_smi_only_arrays) {
3350 HInstruction* elements_kind =
3351 AddInstruction(new(zone()) HElementsKind(literal));
3352 HBasicBlock* store_fast = graph()->CreateBasicBlock();
3353 // Two empty blocks to satisfy edge split form.
3354 HBasicBlock* store_fast_edgesplit1 = graph()->CreateBasicBlock();
3355 HBasicBlock* store_fast_edgesplit2 = graph()->CreateBasicBlock();
3356 HBasicBlock* store_generic = graph()->CreateBasicBlock();
3357 HBasicBlock* check_smi_only_elements = graph()->CreateBasicBlock();
3358 HBasicBlock* join = graph()->CreateBasicBlock();
3359
3360 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(value);
3361 smicheck->SetSuccessorAt(0, store_fast_edgesplit1);
3362 smicheck->SetSuccessorAt(1, check_smi_only_elements);
3363 current_block()->Finish(smicheck);
3364 store_fast_edgesplit1->Finish(new(zone()) HGoto(store_fast));
3365
3366 set_current_block(check_smi_only_elements);
3367 HCompareConstantEqAndBranch* smi_elements_check =
3368 new(zone()) HCompareConstantEqAndBranch(elements_kind,
3369 FAST_SMI_ONLY_ELEMENTS,
3370 Token::EQ_STRICT);
3371 smi_elements_check->SetSuccessorAt(0, store_generic);
3372 smi_elements_check->SetSuccessorAt(1, store_fast_edgesplit2);
3373 current_block()->Finish(smi_elements_check);
3374 store_fast_edgesplit2->Finish(new(zone()) HGoto(store_fast));
3375
3376 set_current_block(store_fast);
3377 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3378 store_fast->Goto(join);
3379
3380 set_current_block(store_generic);
3381 AddInstruction(BuildStoreKeyedGeneric(literal, key, value));
3382 store_generic->Goto(join);
3383
3384 join->SetJoinId(expr->id());
3385 set_current_block(join);
3386 } else {
3387 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value));
3388 }
3389
3321 AddSimulate(expr->GetIdForElement(i)); 3390 AddSimulate(expr->GetIdForElement(i));
3322 } 3391 }
3323 return ast_context()->ReturnValue(Pop()); 3392 return ast_context()->ReturnValue(Pop());
3324 } 3393 }
3325 3394
3326 3395
3327 // Sets the lookup result and returns true if the store can be inlined. 3396 // Sets the lookup result and returns true if the store can be inlined.
3328 static bool ComputeStoredField(Handle<Map> type, 3397 static bool ComputeStoredField(Handle<Map> type,
3329 Handle<String> name, 3398 Handle<String> name,
3330 LookupResult* lookup) { 3399 LookupResult* lookup) {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
3554 // Because not every expression has a position and there is not common 3623 // Because not every expression has a position and there is not common
3555 // superclass of Assignment and CountOperation, we cannot just pass the 3624 // superclass of Assignment and CountOperation, we cannot just pass the
3556 // owning expression instead of position and ast_id separately. 3625 // owning expression instead of position and ast_id separately.
3557 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3626 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3558 HValue* value, 3627 HValue* value,
3559 int position, 3628 int position,
3560 int ast_id) { 3629 int ast_id) {
3561 LookupResult lookup; 3630 LookupResult lookup;
3562 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 3631 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true);
3563 if (type == kUseCell) { 3632 if (type == kUseCell) {
3564 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3565 Handle<GlobalObject> global(info()->global_object()); 3633 Handle<GlobalObject> global(info()->global_object());
3566 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3634 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3567 HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole); 3635 HInstruction* instr =
3636 new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails());
3568 instr->set_position(position); 3637 instr->set_position(position);
3569 AddInstruction(instr); 3638 AddInstruction(instr);
3570 if (instr->HasSideEffects()) AddSimulate(ast_id); 3639 if (instr->HasSideEffects()) AddSimulate(ast_id);
3571 } else { 3640 } else {
3572 HValue* context = environment()->LookupContext(); 3641 HValue* context = environment()->LookupContext();
3573 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3642 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3574 AddInstruction(global_object); 3643 AddInstruction(global_object);
3575 HStoreGlobalGeneric* instr = 3644 HStoreGlobalGeneric* instr =
3576 new(zone()) HStoreGlobalGeneric(context, 3645 new(zone()) HStoreGlobalGeneric(context,
3577 global_object, 3646 global_object,
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
3921 case EXTERNAL_INT_ELEMENTS: 3990 case EXTERNAL_INT_ELEMENTS:
3922 case EXTERNAL_UNSIGNED_INT_ELEMENTS: { 3991 case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
3923 HToInt32* floor_val = new(zone()) HToInt32(val); 3992 HToInt32* floor_val = new(zone()) HToInt32(val);
3924 AddInstruction(floor_val); 3993 AddInstruction(floor_val);
3925 val = floor_val; 3994 val = floor_val;
3926 break; 3995 break;
3927 } 3996 }
3928 case EXTERNAL_FLOAT_ELEMENTS: 3997 case EXTERNAL_FLOAT_ELEMENTS:
3929 case EXTERNAL_DOUBLE_ELEMENTS: 3998 case EXTERNAL_DOUBLE_ELEMENTS:
3930 break; 3999 break;
4000 case FAST_SMI_ONLY_ELEMENTS:
3931 case FAST_ELEMENTS: 4001 case FAST_ELEMENTS:
3932 case FAST_DOUBLE_ELEMENTS: 4002 case FAST_DOUBLE_ELEMENTS:
3933 case DICTIONARY_ELEMENTS: 4003 case DICTIONARY_ELEMENTS:
3934 case NON_STRICT_ARGUMENTS_ELEMENTS: 4004 case NON_STRICT_ARGUMENTS_ELEMENTS:
3935 UNREACHABLE(); 4005 UNREACHABLE();
3936 break; 4006 break;
3937 } 4007 }
3938 return new(zone()) HStoreKeyedSpecializedArrayElement( 4008 return new(zone()) HStoreKeyedSpecializedArrayElement(
3939 external_elements, checked_key, val, elements_kind); 4009 external_elements, checked_key, val, elements_kind);
3940 } else { 4010 } else {
3941 return new(zone()) HLoadKeyedSpecializedArrayElement( 4011 return new(zone()) HLoadKeyedSpecializedArrayElement(
3942 external_elements, checked_key, elements_kind); 4012 external_elements, checked_key, elements_kind);
3943 } 4013 }
3944 } 4014 }
3945 4015
3946 4016
4017 HInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements,
4018 HValue* checked_key,
4019 HValue* val,
4020 ElementsKind elements_kind,
4021 bool is_store) {
4022 if (is_store) {
4023 ASSERT(val != NULL);
4024 if (elements_kind == FAST_DOUBLE_ELEMENTS) {
4025 return new(zone()) HStoreKeyedFastDoubleElement(
4026 elements, checked_key, val);
4027 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
4028 return new(zone()) HStoreKeyedFastElement(
4029 elements, checked_key, val, elements_kind);
4030 }
4031 }
4032 // It's an element load (!is_store).
4033 if (elements_kind == FAST_DOUBLE_ELEMENTS) {
4034 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
4035 } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS.
4036 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
4037 }
4038 }
4039
4040
3947 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 4041 HInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object,
3948 HValue* key, 4042 HValue* key,
3949 HValue* val, 4043 HValue* val,
3950 Expression* expr, 4044 Expression* expr,
3951 bool is_store) { 4045 bool is_store) {
3952 ASSERT(expr->IsMonomorphic()); 4046 ASSERT(expr->IsMonomorphic());
3953 Handle<Map> map = expr->GetMonomorphicReceiverType(); 4047 Handle<Map> map = expr->GetMonomorphicReceiverType();
3954 if (!map->has_fast_elements() && 4048 AddInstruction(new(zone()) HCheckNonSmi(object));
3955 !map->has_fast_double_elements() && 4049 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
4050 bool fast_smi_only_elements = map->has_fast_smi_only_elements();
4051 bool fast_elements = map->has_fast_elements();
4052 bool fast_double_elements = map->has_fast_double_elements();
4053 if (!fast_smi_only_elements &&
4054 !fast_elements &&
4055 !fast_double_elements &&
3956 !map->has_external_array_elements()) { 4056 !map->has_external_array_elements()) {
3957 return is_store ? BuildStoreKeyedGeneric(object, key, val) 4057 return is_store ? BuildStoreKeyedGeneric(object, key, val)
3958 : BuildLoadKeyedGeneric(object, key); 4058 : BuildLoadKeyedGeneric(object, key);
3959 } 4059 }
3960 AddInstruction(new(zone()) HCheckNonSmi(object));
3961 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map));
3962 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 4060 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
3963 bool fast_double_elements = map->has_fast_double_elements(); 4061 if (is_store && (fast_elements || fast_smi_only_elements)) {
3964 if (is_store && map->has_fast_elements()) {
3965 AddInstruction(new(zone()) HCheckMap( 4062 AddInstruction(new(zone()) HCheckMap(
3966 elements, isolate()->factory()->fixed_array_map())); 4063 elements, isolate()->factory()->fixed_array_map()));
3967 } 4064 }
3968 HInstruction* length = NULL; 4065 HInstruction* length = NULL;
3969 HInstruction* checked_key = NULL; 4066 HInstruction* checked_key = NULL;
3970 if (map->has_external_array_elements()) { 4067 if (map->has_external_array_elements()) {
3971 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 4068 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
3972 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4069 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3973 HLoadExternalArrayPointer* external_elements = 4070 HLoadExternalArrayPointer* external_elements =
3974 new(zone()) HLoadExternalArrayPointer(elements); 4071 new(zone()) HLoadExternalArrayPointer(elements);
3975 AddInstruction(external_elements); 4072 AddInstruction(external_elements);
3976 return BuildExternalArrayElementAccess(external_elements, checked_key, 4073 return BuildExternalArrayElementAccess(external_elements, checked_key,
3977 val, map->elements_kind(), is_store); 4074 val, map->elements_kind(), is_store);
3978 } 4075 }
3979 ASSERT(map->has_fast_elements() || fast_double_elements); 4076 ASSERT(fast_smi_only_elements || fast_elements || fast_double_elements);
3980 if (map->instance_type() == JS_ARRAY_TYPE) { 4077 if (map->instance_type() == JS_ARRAY_TYPE) {
3981 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); 4078 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck));
3982 } else { 4079 } else {
3983 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 4080 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
3984 } 4081 }
3985 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4082 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
3986 if (is_store) { 4083 return BuildFastElementAccess(elements, checked_key, val,
3987 if (fast_double_elements) { 4084 map->elements_kind(), is_store);
3988 return new(zone()) HStoreKeyedFastDoubleElement(elements,
3989 checked_key,
3990 val);
3991 } else {
3992 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val);
3993 }
3994 } else {
3995 if (fast_double_elements) {
3996 return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key);
3997 } else {
3998 return new(zone()) HLoadKeyedFastElement(elements, checked_key);
3999 }
4000 }
4001 } 4085 }
4002 4086
4003 4087
4004 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, 4088 HValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object,
4005 HValue* key, 4089 HValue* key,
4006 HValue* val, 4090 HValue* val,
4007 Expression* prop, 4091 Expression* prop,
4008 int ast_id, 4092 int ast_id,
4009 int position, 4093 int position,
4010 bool is_store, 4094 bool is_store,
(...skipping 21 matching lines...) Expand all
4032 4116
4033 HBasicBlock* join = graph()->CreateBasicBlock(); 4117 HBasicBlock* join = graph()->CreateBasicBlock();
4034 4118
4035 HInstruction* elements_kind_instr = 4119 HInstruction* elements_kind_instr =
4036 AddInstruction(new(zone()) HElementsKind(object)); 4120 AddInstruction(new(zone()) HElementsKind(object));
4037 HCompareConstantEqAndBranch* elements_kind_branch = NULL; 4121 HCompareConstantEqAndBranch* elements_kind_branch = NULL;
4038 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 4122 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object));
4039 HLoadExternalArrayPointer* external_elements = NULL; 4123 HLoadExternalArrayPointer* external_elements = NULL;
4040 HInstruction* checked_key = NULL; 4124 HInstruction* checked_key = NULL;
4041 4125
4042 // FAST_ELEMENTS is assumed to be the first case. 4126 // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS,
4043 STATIC_ASSERT(FAST_ELEMENTS == 0); 4127 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external
4128 // arrays.
4129 STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4130 STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4131 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4132 STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND);
4044 4133
4045 for (ElementsKind elements_kind = FAST_ELEMENTS; 4134 for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND;
4046 elements_kind <= LAST_ELEMENTS_KIND; 4135 elements_kind <= LAST_ELEMENTS_KIND;
4047 elements_kind = ElementsKind(elements_kind + 1)) { 4136 elements_kind = ElementsKind(elements_kind + 1)) {
4048 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we 4137 // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS,
4049 // need to add some code that's executed for all external array cases. 4138 // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code
4139 // that's executed for all external array cases.
4050 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 4140 STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND ==
4051 LAST_ELEMENTS_KIND); 4141 LAST_ELEMENTS_KIND);
4052 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 4142 if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND
4053 && todo_external_array) { 4143 && todo_external_array) {
4054 HInstruction* length = 4144 HInstruction* length =
4055 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 4145 AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
4056 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4146 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4057 external_elements = new(zone()) HLoadExternalArrayPointer(elements); 4147 external_elements = new(zone()) HLoadExternalArrayPointer(elements);
4058 AddInstruction(external_elements); 4148 AddInstruction(external_elements);
4059 } 4149 }
4060 if (type_todo[elements_kind]) { 4150 if (type_todo[elements_kind]) {
4061 HBasicBlock* if_true = graph()->CreateBasicBlock(); 4151 HBasicBlock* if_true = graph()->CreateBasicBlock();
4062 HBasicBlock* if_false = graph()->CreateBasicBlock(); 4152 HBasicBlock* if_false = graph()->CreateBasicBlock();
4063 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( 4153 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch(
4064 elements_kind_instr, elements_kind, Token::EQ_STRICT); 4154 elements_kind_instr, elements_kind, Token::EQ_STRICT);
4065 elements_kind_branch->SetSuccessorAt(0, if_true); 4155 elements_kind_branch->SetSuccessorAt(0, if_true);
4066 elements_kind_branch->SetSuccessorAt(1, if_false); 4156 elements_kind_branch->SetSuccessorAt(1, if_false);
4067 current_block()->Finish(elements_kind_branch); 4157 current_block()->Finish(elements_kind_branch);
4068 4158
4069 set_current_block(if_true); 4159 set_current_block(if_true);
4070 HInstruction* access; 4160 HInstruction* access;
4071 if (elements_kind == FAST_ELEMENTS || 4161 if (elements_kind == FAST_SMI_ONLY_ELEMENTS ||
4162 elements_kind == FAST_ELEMENTS ||
4072 elements_kind == FAST_DOUBLE_ELEMENTS) { 4163 elements_kind == FAST_DOUBLE_ELEMENTS) {
4073 bool fast_double_elements = 4164 if (is_store && elements_kind == FAST_SMI_ONLY_ELEMENTS) {
4074 elements_kind == FAST_DOUBLE_ELEMENTS; 4165 AddInstruction(new(zone()) HCheckSmi(val));
4075 if (is_store && elements_kind == FAST_ELEMENTS) { 4166 }
4167 if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) {
4076 AddInstruction(new(zone()) HCheckMap( 4168 AddInstruction(new(zone()) HCheckMap(
4077 elements, isolate()->factory()->fixed_array_map(), 4169 elements, isolate()->factory()->fixed_array_map(),
4078 elements_kind_branch)); 4170 elements_kind_branch));
4079 } 4171 }
4172 // TODO(jkummerow): The need for these two blocks could be avoided
4173 // in one of two ways:
4174 // (1) Introduce ElementsKinds for JSArrays that are distinct from
4175 // those for fast objects.
4176 // (2) Put the common instructions into a third "join" block. This
4177 // requires additional AST IDs that we can deopt to from inside
4178 // that join block. They must be added to the Property class (when
4179 // it's a keyed property) and registered in the full codegen.
4080 HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); 4180 HBasicBlock* if_jsarray = graph()->CreateBasicBlock();
4081 HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); 4181 HBasicBlock* if_fastobject = graph()->CreateBasicBlock();
4082 HHasInstanceTypeAndBranch* typecheck = 4182 HHasInstanceTypeAndBranch* typecheck =
4083 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); 4183 new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE);
4084 typecheck->SetSuccessorAt(0, if_jsarray); 4184 typecheck->SetSuccessorAt(0, if_jsarray);
4085 typecheck->SetSuccessorAt(1, if_fastobject); 4185 typecheck->SetSuccessorAt(1, if_fastobject);
4086 current_block()->Finish(typecheck); 4186 current_block()->Finish(typecheck);
4087 4187
4088 set_current_block(if_jsarray); 4188 set_current_block(if_jsarray);
4089 HInstruction* length = new(zone()) HJSArrayLength(object, typecheck); 4189 HInstruction* length;
4090 AddInstruction(length); 4190 length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck));
4091 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4191 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4092 if (is_store) { 4192 access = AddInstruction(BuildFastElementAccess(
4093 if (fast_double_elements) { 4193 elements, checked_key, val, elements_kind, is_store));
4094 access = AddInstruction( 4194 if (!is_store) {
4095 new(zone()) HStoreKeyedFastDoubleElement(elements,
4096 checked_key,
4097 val));
4098 } else {
4099 access = AddInstruction(
4100 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4101 }
4102 } else {
4103 if (fast_double_elements) {
4104 access = AddInstruction(
4105 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
4106 } else {
4107 access = AddInstruction(
4108 new(zone()) HLoadKeyedFastElement(elements, checked_key));
4109 }
4110 Push(access); 4195 Push(access);
4111 } 4196 }
4197
4112 *has_side_effects |= access->HasSideEffects(); 4198 *has_side_effects |= access->HasSideEffects();
4113 if (position != -1) { 4199 if (position != -1) {
4114 access->set_position(position); 4200 access->set_position(position);
4115 } 4201 }
4116 if_jsarray->Goto(join); 4202 if_jsarray->Goto(join);
4117 4203
4118 set_current_block(if_fastobject); 4204 set_current_block(if_fastobject);
4119 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 4205 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements));
4120 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4206 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length));
4121 if (is_store) { 4207 access = AddInstruction(BuildFastElementAccess(
4122 if (fast_double_elements) { 4208 elements, checked_key, val, elements_kind, is_store));
4123 access = AddInstruction(
4124 new(zone()) HStoreKeyedFastDoubleElement(elements,
4125 checked_key,
4126 val));
4127 } else {
4128 access = AddInstruction(
4129 new(zone()) HStoreKeyedFastElement(elements, checked_key, val));
4130 }
4131 } else {
4132 if (fast_double_elements) {
4133 access = AddInstruction(
4134 new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key));
4135 } else {
4136 access = AddInstruction(
4137 new(zone()) HLoadKeyedFastElement(elements, checked_key));
4138 }
4139 }
4140 } else if (elements_kind == DICTIONARY_ELEMENTS) { 4209 } else if (elements_kind == DICTIONARY_ELEMENTS) {
4141 if (is_store) { 4210 if (is_store) {
4142 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 4211 access = AddInstruction(BuildStoreKeyedGeneric(object, key, val));
4143 } else { 4212 } else {
4144 access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 4213 access = AddInstruction(BuildLoadKeyedGeneric(object, key));
4145 } 4214 }
4146 } else { // External array elements. 4215 } else { // External array elements.
4147 access = AddInstruction(BuildExternalArrayElementAccess( 4216 access = AddInstruction(BuildExternalArrayElementAccess(
4148 external_elements, checked_key, val, elements_kind, is_store)); 4217 external_elements, checked_key, val, elements_kind, is_store));
4149 } 4218 }
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
4467 TraceInline(target, caller, "target text too big"); 4536 TraceInline(target, caller, "target text too big");
4468 return false; 4537 return false;
4469 } 4538 }
4470 4539
4471 // Target must be inlineable. 4540 // Target must be inlineable.
4472 if (!target->IsInlineable()) { 4541 if (!target->IsInlineable()) {
4473 TraceInline(target, caller, "target not inlineable"); 4542 TraceInline(target, caller, "target not inlineable");
4474 return false; 4543 return false;
4475 } 4544 }
4476 4545
4477 // No context change required.
4478 CompilationInfo* outer_info = info(); 4546 CompilationInfo* outer_info = info();
4547 #if !defined(V8_TARGET_ARCH_IA32)
4548 // Target must be able to use caller's context.
4479 if (target->context() != outer_info->closure()->context() || 4549 if (target->context() != outer_info->closure()->context() ||
4480 outer_info->scope()->contains_with() || 4550 outer_info->scope()->contains_with() ||
4481 outer_info->scope()->num_heap_slots() > 0) { 4551 outer_info->scope()->num_heap_slots() > 0) {
4482 TraceInline(target, caller, "target requires context change"); 4552 TraceInline(target, caller, "target requires context change");
4483 return false; 4553 return false;
4484 } 4554 }
4555 #endif
4556
4485 4557
4486 // Don't inline deeper than kMaxInliningLevels calls. 4558 // Don't inline deeper than kMaxInliningLevels calls.
4487 HEnvironment* env = environment(); 4559 HEnvironment* env = environment();
4488 int current_level = 1; 4560 int current_level = 1;
4489 while (env->outer() != NULL) { 4561 while (env->outer() != NULL) {
4490 if (current_level == Compiler::kMaxInliningLevels) { 4562 if (current_level == (FLAG_limit_inlining
4563 ? Compiler::kMaxInliningLevels
4564 : 2 * Compiler::kMaxInliningLevels)) {
4491 TraceInline(target, caller, "inline depth limit reached"); 4565 TraceInline(target, caller, "inline depth limit reached");
4492 return false; 4566 return false;
4493 } 4567 }
4494 current_level++; 4568 current_level++;
4495 env = env->outer(); 4569 env = env->outer();
4496 } 4570 }
4497 4571
4498 // Don't inline recursive functions. 4572 // Don't inline recursive functions.
4499 if (*target_shared == outer_info->closure()->shared()) { 4573 if (*target_shared == outer_info->closure()->shared()) {
4500 TraceInline(target, caller, "target is recursive"); 4574 TraceInline(target, caller, "target is recursive");
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4595 Handle<Code>(target_shared->code()), 4669 Handle<Code>(target_shared->code()),
4596 Handle<Context>(target->context()->global_context())); 4670 Handle<Context>(target->context()->global_context()));
4597 FunctionState target_state(this, &target_info, &target_oracle); 4671 FunctionState target_state(this, &target_info, &target_oracle);
4598 4672
4599 HConstant* undefined = graph()->GetConstantUndefined(); 4673 HConstant* undefined = graph()->GetConstantUndefined();
4600 HEnvironment* inner_env = 4674 HEnvironment* inner_env =
4601 environment()->CopyForInlining(target, 4675 environment()->CopyForInlining(target,
4602 function, 4676 function,
4603 undefined, 4677 undefined,
4604 call_kind); 4678 call_kind);
4679 #ifdef V8_TARGET_ARCH_IA32
4680 // IA32 only, overwrite the caller's context in the deoptimization
4681 // environment with the correct one.
4682 //
4683 // TODO(kmillikin): implement the same inlining on other platforms so we
4684 // can remove the unsightly ifdefs in this function.
4685 HConstant* context = new HConstant(Handle<Context>(target->context()),
4686 Representation::Tagged());
4687 AddInstruction(context);
4688 inner_env->BindContext(context);
4689 #endif
4605 HBasicBlock* body_entry = CreateBasicBlock(inner_env); 4690 HBasicBlock* body_entry = CreateBasicBlock(inner_env);
4606 current_block()->Goto(body_entry); 4691 current_block()->Goto(body_entry);
4607 body_entry->SetJoinId(expr->ReturnId()); 4692 body_entry->SetJoinId(expr->ReturnId());
4608 set_current_block(body_entry); 4693 set_current_block(body_entry);
4609 AddInstruction(new(zone()) HEnterInlined(target, 4694 AddInstruction(new(zone()) HEnterInlined(target,
4610 function, 4695 function,
4611 call_kind)); 4696 call_kind));
4612 VisitDeclarations(target_info.scope()->declarations()); 4697 VisitDeclarations(target_info.scope()->declarations());
4613 VisitStatements(function->body()); 4698 VisitStatements(function->body());
4614 if (HasStackOverflow()) { 4699 if (HasStackOverflow()) {
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
4915 HandlePolymorphicCallNamed(expr, receiver, types, name); 5000 HandlePolymorphicCallNamed(expr, receiver, types, name);
4916 return; 5001 return;
4917 5002
4918 } else { 5003 } else {
4919 HValue* context = environment()->LookupContext(); 5004 HValue* context = environment()->LookupContext();
4920 call = PreProcessCall( 5005 call = PreProcessCall(
4921 new(zone()) HCallNamed(context, name, argument_count)); 5006 new(zone()) HCallNamed(context, name, argument_count));
4922 } 5007 }
4923 5008
4924 } else { 5009 } else {
5010 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION);
4925 VariableProxy* proxy = expr->expression()->AsVariableProxy(); 5011 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4926 // FIXME.
4927 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 5012 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
4928 5013
4929 if (global_call) { 5014 if (global_call) {
4930 Variable* var = proxy->var(); 5015 Variable* var = proxy->var();
4931 bool known_global_function = false; 5016 bool known_global_function = false;
4932 // If there is a global property cell for the name at compile time and 5017 // If there is a global property cell for the name at compile time and
4933 // access check is not enabled we assume that the function will not change 5018 // access check is not enabled we assume that the function will not change
4934 // and generate optimized code for calling the function. 5019 // and generate optimized code for calling the function.
4935 LookupResult lookup; 5020 LookupResult lookup;
4936 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 5021 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4968 HValue* context = environment()->LookupContext(); 5053 HValue* context = environment()->LookupContext();
4969 HGlobalObject* receiver = new(zone()) HGlobalObject(context); 5054 HGlobalObject* receiver = new(zone()) HGlobalObject(context);
4970 AddInstruction(receiver); 5055 AddInstruction(receiver);
4971 PushAndAdd(new(zone()) HPushArgument(receiver)); 5056 PushAndAdd(new(zone()) HPushArgument(receiver));
4972 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5057 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4973 5058
4974 call = new(zone()) HCallGlobal(context, var->name(), argument_count); 5059 call = new(zone()) HCallGlobal(context, var->name(), argument_count);
4975 Drop(argument_count); 5060 Drop(argument_count);
4976 } 5061 }
4977 5062
5063 } else if (expr->IsMonomorphic()) {
5064 // The function is on the stack in the unoptimized code during
5065 // evaluation of the arguments.
5066 CHECK_ALIVE(VisitForValue(expr->expression()));
5067 HValue* function = Top();
5068 HValue* context = environment()->LookupContext();
5069 HGlobalObject* global = new(zone()) HGlobalObject(context);
5070 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global);
5071 AddInstruction(global);
5072 PushAndAdd(receiver);
5073 CHECK_ALIVE(VisitExpressions(expr->arguments()));
5074 AddInstruction(new(zone()) HCheckFunction(function, expr->target()));
5075 if (TryInline(expr)) {
5076 // The function is lingering in the deoptimization environment.
5077 // Handle it by case analysis on the AST context.
5078 if (ast_context()->IsEffect()) {
5079 Drop(1);
5080 } else if (ast_context()->IsValue()) {
5081 HValue* result = Pop();
5082 Drop(1);
5083 Push(result);
5084 } else if (ast_context()->IsTest()) {
5085 TestContext* context = TestContext::cast(ast_context());
5086 if (context->if_true()->HasPredecessor()) {
5087 context->if_true()->last_environment()->Drop(1);
5088 }
5089 if (context->if_false()->HasPredecessor()) {
5090 context->if_true()->last_environment()->Drop(1);
5091 }
5092 } else {
5093 UNREACHABLE();
5094 }
5095 return;
5096 } else {
5097 call = PreProcessCall(new(zone()) HInvokeFunction(context,
5098 function,
5099 argument_count));
5100 Drop(1); // The function.
5101 }
5102
4978 } else { 5103 } else {
4979 CHECK_ALIVE(VisitArgument(expr->expression())); 5104 CHECK_ALIVE(VisitArgument(expr->expression()));
4980 HValue* context = environment()->LookupContext(); 5105 HValue* context = environment()->LookupContext();
4981 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 5106 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
4982 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); 5107 HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object);
4983 AddInstruction(global_object); 5108 AddInstruction(global_object);
4984 AddInstruction(receiver); 5109 AddInstruction(receiver);
4985 PushAndAdd(new(zone()) HPushArgument(receiver)); 5110 PushAndAdd(new(zone()) HPushArgument(receiver));
4986 CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5111 CHECK_ALIVE(VisitArgumentList(expr->arguments()));
4987 5112
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
5661 5786
5662 Representation HGraphBuilder::ToRepresentation(TypeInfo info) { 5787 Representation HGraphBuilder::ToRepresentation(TypeInfo info) {
5663 if (info.IsSmi()) return Representation::Integer32(); 5788 if (info.IsSmi()) return Representation::Integer32();
5664 if (info.IsInteger32()) return Representation::Integer32(); 5789 if (info.IsInteger32()) return Representation::Integer32();
5665 if (info.IsDouble()) return Representation::Double(); 5790 if (info.IsDouble()) return Representation::Double();
5666 if (info.IsNumber()) return Representation::Double(); 5791 if (info.IsNumber()) return Representation::Double();
5667 return Representation::Tagged(); 5792 return Representation::Tagged();
5668 } 5793 }
5669 5794
5670 5795
5671 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* compare_expr, 5796 void HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
5672 Expression* expr, 5797 Expression* sub_expr,
5673 Handle<String> check) { 5798 Handle<String> check) {
5674 CHECK_ALIVE(VisitForTypeOf(expr)); 5799 CHECK_ALIVE(VisitForTypeOf(sub_expr));
5675 HValue* expr_value = Pop(); 5800 HValue* value = Pop();
5676 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(expr_value, check); 5801 HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check);
5677 instr->set_position(compare_expr->position()); 5802 instr->set_position(expr->position());
5678 return ast_context()->ReturnControl(instr, compare_expr->id()); 5803 return ast_context()->ReturnControl(instr, expr->id());
5679 } 5804 }
5680 5805
5681 5806
5682 void HGraphBuilder::HandleLiteralCompareUndefined( 5807 bool HGraphBuilder::TryLiteralCompare(CompareOperation* expr) {
5683 CompareOperation* compare_expr, Expression* expr) { 5808 Expression *sub_expr;
5684 CHECK_ALIVE(VisitForValue(expr)); 5809 Handle<String> check;
5685 HValue* lhs = Pop(); 5810 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
5686 HValue* rhs = graph()->GetConstantUndefined(); 5811 HandleLiteralCompareTypeof(expr, sub_expr, check);
5687 HCompareObjectEqAndBranch* instr = 5812 return true;
5688 new(zone()) HCompareObjectEqAndBranch(lhs, rhs); 5813 }
5689 instr->set_position(compare_expr->position()); 5814
5690 return ast_context()->ReturnControl(instr, compare_expr->id()); 5815 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
5816 HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
5817 return true;
5818 }
5819
5820 if (expr->IsLiteralCompareNull(&sub_expr)) {
5821 HandleLiteralCompareNil(expr, sub_expr, kNullValue);
5822 return true;
5823 }
5824
5825 return false;
5691 } 5826 }
5692 5827
5693 5828
5694 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 5829 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
5695 ASSERT(!HasStackOverflow()); 5830 ASSERT(!HasStackOverflow());
5696 ASSERT(current_block() != NULL); 5831 ASSERT(current_block() != NULL);
5697 ASSERT(current_block()->HasPredecessor()); 5832 ASSERT(current_block()->HasPredecessor());
5698 if (IsClassOfTest(expr)) { 5833 if (IsClassOfTest(expr)) {
5699 CallRuntime* call = expr->left()->AsCallRuntime(); 5834 CallRuntime* call = expr->left()->AsCallRuntime();
5700 ASSERT(call->arguments()->length() == 1); 5835 ASSERT(call->arguments()->length() == 1);
5701 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5836 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5702 HValue* value = Pop(); 5837 HValue* value = Pop();
5703 Literal* literal = expr->right()->AsLiteral(); 5838 Literal* literal = expr->right()->AsLiteral();
5704 Handle<String> rhs = Handle<String>::cast(literal->handle()); 5839 Handle<String> rhs = Handle<String>::cast(literal->handle());
5705 HClassOfTestAndBranch* instr = 5840 HClassOfTestAndBranch* instr =
5706 new(zone()) HClassOfTestAndBranch(value, rhs); 5841 new(zone()) HClassOfTestAndBranch(value, rhs);
5707 instr->set_position(expr->position()); 5842 instr->set_position(expr->position());
5708 return ast_context()->ReturnControl(instr, expr->id()); 5843 return ast_context()->ReturnControl(instr, expr->id());
5709 } 5844 }
5710 5845
5711 // Check for special cases that compare against literals. 5846 // Check for special cases that compare against literals.
5712 Expression *sub_expr; 5847 if (TryLiteralCompare(expr)) return;
5713 Handle<String> check;
5714 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
5715 HandleLiteralCompareTypeof(expr, sub_expr, check);
5716 return;
5717 }
5718
5719 if (expr->IsLiteralCompareUndefined(&sub_expr)) {
5720 HandleLiteralCompareUndefined(expr, sub_expr);
5721 return;
5722 }
5723 5848
5724 TypeInfo type_info = oracle()->CompareType(expr); 5849 TypeInfo type_info = oracle()->CompareType(expr);
5725 // Check if this expression was ever executed according to type feedback. 5850 // Check if this expression was ever executed according to type feedback.
5726 if (type_info.IsUninitialized()) { 5851 if (type_info.IsUninitialized()) {
5727 AddInstruction(new(zone()) HSoftDeoptimize); 5852 AddInstruction(new(zone()) HSoftDeoptimize);
5728 current_block()->MarkAsDeoptimizing(); 5853 current_block()->MarkAsDeoptimizing();
5729 type_info = TypeInfo::Unknown(); 5854 type_info = TypeInfo::Unknown();
5730 } 5855 }
5731 5856
5732 CHECK_ALIVE(VisitForValue(expr->left())); 5857 CHECK_ALIVE(VisitForValue(expr->left()));
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
5817 HCompareIDAndBranch* result = 5942 HCompareIDAndBranch* result =
5818 new(zone()) HCompareIDAndBranch(left, right, op); 5943 new(zone()) HCompareIDAndBranch(left, right, op);
5819 result->set_position(expr->position()); 5944 result->set_position(expr->position());
5820 result->SetInputRepresentation(r); 5945 result->SetInputRepresentation(r);
5821 return ast_context()->ReturnControl(result, expr->id()); 5946 return ast_context()->ReturnControl(result, expr->id());
5822 } 5947 }
5823 } 5948 }
5824 } 5949 }
5825 5950
5826 5951
5827 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 5952 void HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
5953 Expression* sub_expr,
5954 NilValue nil) {
5828 ASSERT(!HasStackOverflow()); 5955 ASSERT(!HasStackOverflow());
5829 ASSERT(current_block() != NULL); 5956 ASSERT(current_block() != NULL);
5830 ASSERT(current_block()->HasPredecessor()); 5957 ASSERT(current_block()->HasPredecessor());
5831 CHECK_ALIVE(VisitForValue(expr->expression())); 5958 CHECK_ALIVE(VisitForValue(sub_expr));
5832 HValue* value = Pop(); 5959 HValue* value = Pop();
5833 HIsNullAndBranch* instr = 5960 EqualityKind kind =
5834 new(zone()) HIsNullAndBranch(value, expr->is_strict()); 5961 expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality;
5962 HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil);
5963 instr->set_position(expr->position());
5835 return ast_context()->ReturnControl(instr, expr->id()); 5964 return ast_context()->ReturnControl(instr, expr->id());
5836 } 5965 }
5837 5966
5838 5967
5839 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 5968 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
5840 ASSERT(!HasStackOverflow()); 5969 ASSERT(!HasStackOverflow());
5841 ASSERT(current_block() != NULL); 5970 ASSERT(current_block() != NULL);
5842 ASSERT(current_block()->HasPredecessor()); 5971 ASSERT(current_block()->HasPredecessor());
5843 HThisFunction* self = new(zone()) HThisFunction; 5972 HThisFunction* self = new(zone()) HThisFunction;
5844 return ast_context()->ReturnInstruction(self, expr->id()); 5973 return ast_context()->ReturnInstruction(self, expr->id());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
5907 LAST_SPEC_OBJECT_TYPE); 6036 LAST_SPEC_OBJECT_TYPE);
5908 return ast_context()->ReturnControl(result, call->id()); 6037 return ast_context()->ReturnControl(result, call->id());
5909 } 6038 }
5910 6039
5911 6040
5912 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { 6041 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) {
5913 ASSERT(call->arguments()->length() == 1); 6042 ASSERT(call->arguments()->length() == 1);
5914 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 6043 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5915 HValue* value = Pop(); 6044 HValue* value = Pop();
5916 HHasInstanceTypeAndBranch* result = 6045 HHasInstanceTypeAndBranch* result =
5917 new(zone()) HHasInstanceTypeAndBranch(value, 6046 new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE);
5918 JS_FUNCTION_TYPE,
5919 JS_FUNCTION_PROXY_TYPE);
5920 return ast_context()->ReturnControl(result, call->id()); 6047 return ast_context()->ReturnControl(result, call->id());
5921 } 6048 }
5922 6049
5923 6050
5924 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 6051 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
5925 ASSERT(call->arguments()->length() == 1); 6052 ASSERT(call->arguments()->length() == 1);
5926 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 6053 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5927 HValue* value = Pop(); 6054 HValue* value = Pop();
5928 HHasCachedArrayIndexAndBranch* result = 6055 HHasCachedArrayIndexAndBranch* result =
5929 new(zone()) HHasCachedArrayIndexAndBranch(value); 6056 new(zone()) HHasCachedArrayIndexAndBranch(value);
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
6809 6936
6810 if (FLAG_trace_hydrogen) { 6937 if (FLAG_trace_hydrogen) {
6811 if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); 6938 if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_);
6812 if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); 6939 if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_);
6813 if (allocator_ != NULL) { 6940 if (allocator_ != NULL) {
6814 HTracer::Instance()->TraceLiveRanges(name_, allocator_); 6941 HTracer::Instance()->TraceLiveRanges(name_, allocator_);
6815 } 6942 }
6816 } 6943 }
6817 6944
6818 #ifdef DEBUG 6945 #ifdef DEBUG
6819 if (graph_ != NULL) graph_->Verify(); 6946 if (graph_ != NULL) graph_->Verify(false); // No full verify.
6820 if (allocator_ != NULL) allocator_->Verify(); 6947 if (allocator_ != NULL) allocator_->Verify();
6821 #endif 6948 #endif
6822 } 6949 }
6823 6950
6824 } } // namespace v8::internal 6951 } } // 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