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

Side by Side Diff: src/hydrogen.cc

Issue 7860035: Merge bleeding edge up to 9192 into the GC branch. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 3 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 1364 matching lines...) Expand 10 before | Expand all | Expand 10 after
1375 1375
1376 1376
1377 void HGlobalValueNumberer::ComputeBlockSideEffects() { 1377 void HGlobalValueNumberer::ComputeBlockSideEffects() {
1378 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1378 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) {
1379 // Compute side effects for the block. 1379 // Compute side effects for the block.
1380 HBasicBlock* block = graph_->blocks()->at(i); 1380 HBasicBlock* block = graph_->blocks()->at(i);
1381 HInstruction* instr = block->first(); 1381 HInstruction* instr = block->first();
1382 int id = block->block_id(); 1382 int id = block->block_id();
1383 int side_effects = 0; 1383 int side_effects = 0;
1384 while (instr != NULL) { 1384 while (instr != NULL) {
1385 side_effects |= (instr->flags() & HValue::ChangesFlagsMask()); 1385 side_effects |= instr->ChangesFlags();
1386 instr = instr->next(); 1386 instr = instr->next();
1387 } 1387 }
1388 block_side_effects_[id] |= side_effects; 1388 block_side_effects_[id] |= side_effects;
1389 1389
1390 // Loop headers are part of their loop. 1390 // Loop headers are part of their loop.
1391 if (block->IsLoopHeader()) { 1391 if (block->IsLoopHeader()) {
1392 loop_side_effects_[id] |= side_effects; 1392 loop_side_effects_[id] |= side_effects;
1393 } 1393 }
1394 1394
1395 // Propagate loop side effects upwards. 1395 // Propagate loop side effects upwards.
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 1492
1493 // If this is a loop header kill everything killed by the loop. 1493 // If this is a loop header kill everything killed by the loop.
1494 if (block->IsLoopHeader()) { 1494 if (block->IsLoopHeader()) {
1495 map->Kill(loop_side_effects_[block->block_id()]); 1495 map->Kill(loop_side_effects_[block->block_id()]);
1496 } 1496 }
1497 1497
1498 // Go through all instructions of the current block. 1498 // Go through all instructions of the current block.
1499 HInstruction* instr = block->first(); 1499 HInstruction* instr = block->first();
1500 while (instr != NULL) { 1500 while (instr != NULL) {
1501 HInstruction* next = instr->next(); 1501 HInstruction* next = instr->next();
1502 int flags = (instr->flags() & HValue::ChangesFlagsMask()); 1502 int flags = instr->ChangesFlags();
1503 if (flags != 0) { 1503 if (flags != 0) {
1504 ASSERT(!instr->CheckFlag(HValue::kUseGVN)); 1504 ASSERT(!instr->CheckFlag(HValue::kUseGVN));
1505 // Clear all instructions in the map that are affected by side effects. 1505 // Clear all instructions in the map that are affected by side effects.
1506 map->Kill(flags); 1506 map->Kill(flags);
1507 TraceGVN("Instruction %d kills\n", instr->id()); 1507 TraceGVN("Instruction %d kills\n", instr->id());
1508 } else if (instr->CheckFlag(HValue::kUseGVN)) { 1508 } else if (instr->CheckFlag(HValue::kUseGVN)) {
1509 HValue* other = map->Lookup(instr); 1509 HValue* other = map->Lookup(instr);
1510 if (other != NULL) { 1510 if (other != NULL) {
1511 ASSERT(instr->Equals(other) && other->Equals(instr)); 1511 ASSERT(instr->Equals(other) && other->Equals(instr));
1512 TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1512 TraceGVN("Replacing value %d (%s) with value %d (%s)\n",
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1668 connected_set->Add(i); 1668 connected_set->Add(i);
1669 connected_phis.Add(connected_set); 1669 connected_phis.Add(connected_set);
1670 } 1670 }
1671 1671
1672 // (2) Do a fixed point iteration to find the set of connected phis. A 1672 // (2) Do a fixed point iteration to find the set of connected phis. A
1673 // phi is connected to another phi if its value is used either directly or 1673 // phi is connected to another phi if its value is used either directly or
1674 // indirectly through a transitive closure of the def-use relation. 1674 // indirectly through a transitive closure of the def-use relation.
1675 bool change = true; 1675 bool change = true;
1676 while (change) { 1676 while (change) {
1677 change = false; 1677 change = false;
1678 for (int i = 0; i < phi_count; ++i) { 1678 // We normally have far more "forward edges" than "backward edges",
1679 // so we terminate faster when we walk backwards.
1680 for (int i = phi_count - 1; i >= 0; --i) {
1679 HPhi* phi = phi_list->at(i); 1681 HPhi* phi = phi_list->at(i);
1680 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { 1682 for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
1681 HValue* use = it.value(); 1683 HValue* use = it.value();
1682 if (use->IsPhi()) { 1684 if (use->IsPhi()) {
1683 int id = HPhi::cast(use)->phi_id(); 1685 int id = HPhi::cast(use)->phi_id();
1684 if (connected_phis[i]->UnionIsChanged(*connected_phis[id])) 1686 if (connected_phis[i]->UnionIsChanged(*connected_phis[id]))
1685 change = true; 1687 change = true;
1686 } 1688 }
1687 } 1689 }
1688 } 1690 }
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
2266 { 2268 {
2267 HPhase phase("Block building"); 2269 HPhase phase("Block building");
2268 current_block_ = graph()->entry_block(); 2270 current_block_ = graph()->entry_block();
2269 2271
2270 Scope* scope = info()->scope(); 2272 Scope* scope = info()->scope();
2271 if (scope->HasIllegalRedeclaration()) { 2273 if (scope->HasIllegalRedeclaration()) {
2272 Bailout("function with illegal redeclaration"); 2274 Bailout("function with illegal redeclaration");
2273 return NULL; 2275 return NULL;
2274 } 2276 }
2275 SetupScope(scope); 2277 SetupScope(scope);
2276 VisitDeclarations(scope->declarations());
2277 HValue* context = environment()->LookupContext();
2278 AddInstruction(
2279 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
2280 2278
2281 // Add an edge to the body entry. This is warty: the graph's start 2279 // Add an edge to the body entry. This is warty: the graph's start
2282 // environment will be used by the Lithium translation as the initial 2280 // environment will be used by the Lithium translation as the initial
2283 // environment on graph entry, but it has now been mutated by the 2281 // environment on graph entry, but it has now been mutated by the
2284 // Hydrogen translation of the instructions in the start block. This 2282 // Hydrogen translation of the instructions in the start block. This
2285 // environment uses values which have not been defined yet. These 2283 // environment uses values which have not been defined yet. These
2286 // Hydrogen instructions will then be replayed by the Lithium 2284 // Hydrogen instructions will then be replayed by the Lithium
2287 // translation, so they cannot have an environment effect. The edge to 2285 // translation, so they cannot have an environment effect. The edge to
2288 // the body's entry block (along with some special logic for the start 2286 // the body's entry block (along with some special logic for the start
2289 // block in HInstruction::InsertAfter) seals the start block from 2287 // block in HInstruction::InsertAfter) seals the start block from
2290 // getting unwanted instructions inserted. 2288 // getting unwanted instructions inserted.
2291 // 2289 //
2292 // TODO(kmillikin): Fix this. Stop mutating the initial environment. 2290 // TODO(kmillikin): Fix this. Stop mutating the initial environment.
2293 // Make the Hydrogen instructions in the initial block into Hydrogen 2291 // Make the Hydrogen instructions in the initial block into Hydrogen
2294 // values (but not instructions), present in the initial environment and 2292 // values (but not instructions), present in the initial environment and
2295 // not replayed by the Lithium translation. 2293 // not replayed by the Lithium translation.
2296 HEnvironment* initial_env = environment()->CopyWithoutHistory(); 2294 HEnvironment* initial_env = environment()->CopyWithoutHistory();
2297 HBasicBlock* body_entry = CreateBasicBlock(initial_env); 2295 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2298 current_block()->Goto(body_entry); 2296 current_block()->Goto(body_entry);
2299 body_entry->SetJoinId(AstNode::kFunctionEntryId); 2297 body_entry->SetJoinId(AstNode::kFunctionEntryId);
2300 set_current_block(body_entry); 2298 set_current_block(body_entry);
2299
2300 // Handle implicit declaration of the function name in named function
2301 // expressions before other declarations.
2302 if (scope->is_function_scope() && scope->function() != NULL) {
2303 HandleDeclaration(scope->function(), Variable::CONST, NULL);
2304 }
2305 VisitDeclarations(scope->declarations());
2306 AddSimulate(AstNode::kDeclarationsId);
2307
2308 HValue* context = environment()->LookupContext();
2309 AddInstruction(
2310 new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry));
2311
2301 VisitStatements(info()->function()->body()); 2312 VisitStatements(info()->function()->body());
2302 if (HasStackOverflow()) return NULL; 2313 if (HasStackOverflow()) return NULL;
2303 2314
2304 if (current_block() != NULL) { 2315 if (current_block() != NULL) {
2305 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); 2316 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined());
2306 current_block()->FinishExit(instr); 2317 current_block()->FinishExit(instr);
2307 set_current_block(NULL); 2318 set_current_block(NULL);
2308 } 2319 }
2309 } 2320 }
2310 2321
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
2636 2647
2637 2648
2638 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2649 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) {
2639 ASSERT(!HasStackOverflow()); 2650 ASSERT(!HasStackOverflow());
2640 ASSERT(current_block() != NULL); 2651 ASSERT(current_block() != NULL);
2641 ASSERT(current_block()->HasPredecessor()); 2652 ASSERT(current_block()->HasPredecessor());
2642 return Bailout("WithStatement"); 2653 return Bailout("WithStatement");
2643 } 2654 }
2644 2655
2645 2656
2646 void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) {
2647 ASSERT(!HasStackOverflow());
2648 ASSERT(current_block() != NULL);
2649 ASSERT(current_block()->HasPredecessor());
2650 return Bailout("ExitContextStatement");
2651 }
2652
2653
2654 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2657 void HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
2655 ASSERT(!HasStackOverflow()); 2658 ASSERT(!HasStackOverflow());
2656 ASSERT(current_block() != NULL); 2659 ASSERT(current_block() != NULL);
2657 ASSERT(current_block()->HasPredecessor()); 2660 ASSERT(current_block()->HasPredecessor());
2658 // We only optimize switch statements with smi-literal smi comparisons, 2661 // We only optimize switch statements with smi-literal smi comparisons,
2659 // with a bounded number of clauses. 2662 // with a bounded number of clauses.
2660 const int kCaseClauseLimit = 128; 2663 const int kCaseClauseLimit = 128;
2661 ZoneList<CaseClause*>* clauses = stmt->cases(); 2664 ZoneList<CaseClause*>* clauses = stmt->cases();
2662 int clause_count = clauses->length(); 2665 int clause_count = clauses->length();
2663 if (clause_count > kCaseClauseLimit) { 2666 if (clause_count > kCaseClauseLimit) {
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after
3112 context = context_instruction; 3115 context = context_instruction;
3113 } 3116 }
3114 return context; 3117 return context;
3115 } 3118 }
3116 3119
3117 3120
3118 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3121 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
3119 ASSERT(!HasStackOverflow()); 3122 ASSERT(!HasStackOverflow());
3120 ASSERT(current_block() != NULL); 3123 ASSERT(current_block() != NULL);
3121 ASSERT(current_block()->HasPredecessor()); 3124 ASSERT(current_block()->HasPredecessor());
3122 Variable* variable = expr->AsVariable(); 3125 Variable* variable = expr->var();
3123 if (variable == NULL) { 3126 if (variable->mode() == Variable::LET) {
3124 return Bailout("reference to rewritten variable"); 3127 return Bailout("reference to let variable");
3125 } else if (variable->IsStackAllocated()) { 3128 }
3126 HValue* value = environment()->Lookup(variable); 3129 switch (variable->location()) {
3127 if (variable->mode() == Variable::CONST && 3130 case Variable::UNALLOCATED: {
3128 value == graph()->GetConstantHole()) { 3131 LookupResult lookup;
3129 return Bailout("reference to uninitialized const variable"); 3132 GlobalPropertyAccess type =
3130 } 3133 LookupGlobalProperty(variable, &lookup, false);
3131 return ast_context()->ReturnValue(value);
3132 } else if (variable->IsContextSlot()) {
3133 if (variable->mode() == Variable::CONST) {
3134 return Bailout("reference to const context slot");
3135 }
3136 HValue* context = BuildContextChainWalk(variable);
3137 int index = variable->AsSlot()->index();
3138 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index);
3139 return ast_context()->ReturnInstruction(instr, expr->id());
3140 } else if (variable->is_global()) {
3141 LookupResult lookup;
3142 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false);
3143 3134
3144 if (type == kUseCell && 3135 if (type == kUseCell &&
3145 info()->global_object()->IsAccessCheckNeeded()) { 3136 info()->global_object()->IsAccessCheckNeeded()) {
3146 type = kUseGeneric; 3137 type = kUseGeneric;
3138 }
3139
3140 if (type == kUseCell) {
3141 Handle<GlobalObject> global(info()->global_object());
3142 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3143 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3144 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole);
3145 return ast_context()->ReturnInstruction(instr, expr->id());
3146 } else {
3147 HValue* context = environment()->LookupContext();
3148 HGlobalObject* global_object = new(zone()) HGlobalObject(context);
3149 AddInstruction(global_object);
3150 HLoadGlobalGeneric* instr =
3151 new(zone()) HLoadGlobalGeneric(context,
3152 global_object,
3153 variable->name(),
3154 ast_context()->is_for_typeof());
3155 instr->set_position(expr->position());
3156 return ast_context()->ReturnInstruction(instr, expr->id());
3157 }
3147 } 3158 }
3148 3159
3149 if (type == kUseCell) { 3160 case Variable::PARAMETER:
3150 Handle<GlobalObject> global(info()->global_object()); 3161 case Variable::LOCAL: {
3151 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3162 HValue* value = environment()->Lookup(variable);
3152 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3163 if (variable->mode() == Variable::CONST &&
3153 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); 3164 value == graph()->GetConstantHole()) {
3154 return ast_context()->ReturnInstruction(instr, expr->id()); 3165 return Bailout("reference to uninitialized const variable");
3155 } else { 3166 }
3156 HValue* context = environment()->LookupContext(); 3167 return ast_context()->ReturnValue(value);
3157 HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3168 }
3158 AddInstruction(global_object); 3169
3159 HLoadGlobalGeneric* instr = 3170 case Variable::CONTEXT: {
3160 new(zone()) HLoadGlobalGeneric(context, 3171 if (variable->mode() == Variable::CONST) {
3161 global_object, 3172 return Bailout("reference to const context slot");
3162 variable->name(), 3173 }
3163 ast_context()->is_for_typeof()); 3174 HValue* context = BuildContextChainWalk(variable);
3164 instr->set_position(expr->position()); 3175 HLoadContextSlot* instr =
3165 ASSERT(instr->HasSideEffects()); 3176 new(zone()) HLoadContextSlot(context, variable->index());
3166 return ast_context()->ReturnInstruction(instr, expr->id()); 3177 return ast_context()->ReturnInstruction(instr, expr->id());
3167 } 3178 }
3168 } else { 3179
3169 return Bailout("reference to a variable which requires dynamic lookup"); 3180 case Variable::LOOKUP:
3181 return Bailout("reference to a variable which requires dynamic lookup");
3170 } 3182 }
3171 } 3183 }
3172 3184
3173 3185
3174 void HGraphBuilder::VisitLiteral(Literal* expr) { 3186 void HGraphBuilder::VisitLiteral(Literal* expr) {
3175 ASSERT(!HasStackOverflow()); 3187 ASSERT(!HasStackOverflow());
3176 ASSERT(current_block() != NULL); 3188 ASSERT(current_block() != NULL);
3177 ASSERT(current_block()->HasPredecessor()); 3189 ASSERT(current_block()->HasPredecessor());
3178 HConstant* instr = 3190 HConstant* instr =
3179 new(zone()) HConstant(expr->handle(), Representation::Tagged()); 3191 new(zone()) HConstant(expr->handle(), Representation::Tagged());
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
3571 AddInstruction(instr); 3583 AddInstruction(instr);
3572 ASSERT(instr->HasSideEffects()); 3584 ASSERT(instr->HasSideEffects());
3573 if (instr->HasSideEffects()) AddSimulate(ast_id); 3585 if (instr->HasSideEffects()) AddSimulate(ast_id);
3574 } 3586 }
3575 } 3587 }
3576 3588
3577 3589
3578 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3590 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3579 Expression* target = expr->target(); 3591 Expression* target = expr->target();
3580 VariableProxy* proxy = target->AsVariableProxy(); 3592 VariableProxy* proxy = target->AsVariableProxy();
3581 Variable* var = proxy->AsVariable();
3582 Property* prop = target->AsProperty(); 3593 Property* prop = target->AsProperty();
3583 ASSERT(var == NULL || prop == NULL); 3594 ASSERT(proxy == NULL || prop == NULL);
3584 3595
3585 // We have a second position recorded in the FullCodeGenerator to have 3596 // We have a second position recorded in the FullCodeGenerator to have
3586 // type feedback for the binary operation. 3597 // type feedback for the binary operation.
3587 BinaryOperation* operation = expr->binary_operation(); 3598 BinaryOperation* operation = expr->binary_operation();
3588 3599
3589 if (var != NULL) { 3600 if (proxy != NULL) {
3590 if (var->mode() == Variable::CONST) { 3601 Variable* var = proxy->var();
3591 return Bailout("unsupported const compound assignment"); 3602 if (var->mode() == Variable::CONST || var->mode() == Variable::LET) {
3603 return Bailout("unsupported let or const compound assignment");
3592 } 3604 }
3593 3605
3594 CHECK_ALIVE(VisitForValue(operation)); 3606 CHECK_ALIVE(VisitForValue(operation));
3595 3607
3596 if (var->is_global()) { 3608 switch (var->location()) {
3597 HandleGlobalVariableAssignment(var, 3609 case Variable::UNALLOCATED:
3598 Top(), 3610 HandleGlobalVariableAssignment(var,
3599 expr->position(), 3611 Top(),
3600 expr->AssignmentId()); 3612 expr->position(),
3601 } else if (var->IsStackAllocated()) { 3613 expr->AssignmentId());
3602 Bind(var, Top()); 3614 break;
3603 } else if (var->IsContextSlot()) { 3615
3604 // Bail out if we try to mutate a parameter value in a function using 3616 case Variable::PARAMETER:
3605 // the arguments object. We do not (yet) correctly handle the 3617 case Variable::LOCAL:
3606 // arguments property of the function. 3618 Bind(var, Top());
3607 if (info()->scope()->arguments() != NULL) { 3619 break;
3608 // Parameters will rewrite to context slots. We have no direct way 3620
3609 // to detect that the variable is a parameter. 3621 case Variable::CONTEXT: {
3610 int count = info()->scope()->num_parameters(); 3622 // Bail out if we try to mutate a parameter value in a function
3611 for (int i = 0; i < count; ++i) { 3623 // using the arguments object. We do not (yet) correctly handle the
3612 if (var == info()->scope()->parameter(i)) { 3624 // arguments property of the function.
3613 Bailout("assignment to parameter, function uses arguments object"); 3625 if (info()->scope()->arguments() != NULL) {
3626 // Parameters will be allocated to context slots. We have no
3627 // direct way to detect that the variable is a parameter so we do
3628 // a linear search of the parameter variables.
3629 int count = info()->scope()->num_parameters();
3630 for (int i = 0; i < count; ++i) {
3631 if (var == info()->scope()->parameter(i)) {
3632 Bailout(
3633 "assignment to parameter, function uses arguments object");
3634 }
3614 } 3635 }
3615 } 3636 }
3637
3638 HValue* context = BuildContextChainWalk(var);
3639 HStoreContextSlot* instr =
3640 new(zone()) HStoreContextSlot(context, var->index(), Top());
3641 AddInstruction(instr);
3642 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3643 break;
3616 } 3644 }
3617 3645
3618 HValue* context = BuildContextChainWalk(var); 3646 case Variable::LOOKUP:
3619 int index = var->AsSlot()->index(); 3647 return Bailout("compound assignment to lookup slot");
3620 HStoreContextSlot* instr =
3621 new(zone()) HStoreContextSlot(context, index, Top());
3622 AddInstruction(instr);
3623 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3624 } else {
3625 return Bailout("compound assignment to lookup slot");
3626 } 3648 }
3627 return ast_context()->ReturnValue(Pop()); 3649 return ast_context()->ReturnValue(Pop());
3628 3650
3629 } else if (prop != NULL) { 3651 } else if (prop != NULL) {
3630 prop->RecordTypeFeedback(oracle()); 3652 prop->RecordTypeFeedback(oracle());
3631 3653
3632 if (prop->key()->IsPropertyName()) { 3654 if (prop->key()->IsPropertyName()) {
3633 // Named property. 3655 // Named property.
3634 CHECK_ALIVE(VisitForValue(prop->obj())); 3656 CHECK_ALIVE(VisitForValue(prop->obj()));
3635 HValue* obj = Top(); 3657 HValue* obj = Top();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
3703 return Bailout("invalid lhs in compound assignment"); 3725 return Bailout("invalid lhs in compound assignment");
3704 } 3726 }
3705 } 3727 }
3706 3728
3707 3729
3708 void HGraphBuilder::VisitAssignment(Assignment* expr) { 3730 void HGraphBuilder::VisitAssignment(Assignment* expr) {
3709 ASSERT(!HasStackOverflow()); 3731 ASSERT(!HasStackOverflow());
3710 ASSERT(current_block() != NULL); 3732 ASSERT(current_block() != NULL);
3711 ASSERT(current_block()->HasPredecessor()); 3733 ASSERT(current_block()->HasPredecessor());
3712 VariableProxy* proxy = expr->target()->AsVariableProxy(); 3734 VariableProxy* proxy = expr->target()->AsVariableProxy();
3713 Variable* var = proxy->AsVariable();
3714 Property* prop = expr->target()->AsProperty(); 3735 Property* prop = expr->target()->AsProperty();
3715 ASSERT(var == NULL || prop == NULL); 3736 ASSERT(proxy == NULL || prop == NULL);
3716 3737
3717 if (expr->is_compound()) { 3738 if (expr->is_compound()) {
3718 HandleCompoundAssignment(expr); 3739 HandleCompoundAssignment(expr);
3719 return; 3740 return;
3720 } 3741 }
3721 3742
3722 if (var != NULL) { 3743 if (prop != NULL) {
3744 HandlePropertyAssignment(expr);
3745 } else if (proxy != NULL) {
3746 Variable* var = proxy->var();
3723 if (var->mode() == Variable::CONST) { 3747 if (var->mode() == Variable::CONST) {
3724 if (expr->op() != Token::INIT_CONST) { 3748 if (expr->op() != Token::INIT_CONST) {
3725 return Bailout("non-initializer assignment to const"); 3749 return Bailout("non-initializer assignment to const");
3726 } 3750 }
3727 if (!var->IsStackAllocated()) { 3751 if (!var->IsStackAllocated()) {
3728 return Bailout("assignment to const context slot"); 3752 return Bailout("assignment to const context slot");
3729 } 3753 }
3730 // We insert a use of the old value to detect unsupported uses of const 3754 // We insert a use of the old value to detect unsupported uses of const
3731 // variables (e.g. initialization inside a loop). 3755 // variables (e.g. initialization inside a loop).
3732 HValue* old_value = environment()->Lookup(var); 3756 HValue* old_value = environment()->Lookup(var);
3733 AddInstruction(new HUseConst(old_value)); 3757 AddInstruction(new HUseConst(old_value));
3758 } else if (var->mode() == Variable::LET) {
3759 return Bailout("unsupported assignment to let");
3734 } 3760 }
3735 3761
3736 if (proxy->IsArguments()) return Bailout("assignment to arguments"); 3762 if (proxy->IsArguments()) return Bailout("assignment to arguments");
3737 3763
3738 // Handle the assignment. 3764 // Handle the assignment.
3739 if (var->IsStackAllocated()) { 3765 switch (var->location()) {
3740 // We do not allow the arguments object to occur in a context where it 3766 case Variable::UNALLOCATED:
3741 // may escape, but assignments to stack-allocated locals are 3767 CHECK_ALIVE(VisitForValue(expr->value()));
3742 // permitted. 3768 HandleGlobalVariableAssignment(var,
3743 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); 3769 Top(),
3744 HValue* value = Pop(); 3770 expr->position(),
3745 Bind(var, value); 3771 expr->AssignmentId());
3746 return ast_context()->ReturnValue(value); 3772 return ast_context()->ReturnValue(Pop());
3747 3773
3748 } else if (var->IsContextSlot()) { 3774 case Variable::PARAMETER:
3749 ASSERT(var->mode() != Variable::CONST); 3775 case Variable::LOCAL: {
3750 // Bail out if we try to mutate a parameter value in a function using 3776 // We do not allow the arguments object to occur in a context where it
3751 // the arguments object. We do not (yet) correctly handle the 3777 // may escape, but assignments to stack-allocated locals are
3752 // arguments property of the function. 3778 // permitted.
3753 if (info()->scope()->arguments() != NULL) { 3779 CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
3754 // Parameters will rewrite to context slots. We have no direct way 3780 HValue* value = Pop();
3755 // to detect that the variable is a parameter. 3781 Bind(var, value);
3756 int count = info()->scope()->num_parameters(); 3782 return ast_context()->ReturnValue(value);
3757 for (int i = 0; i < count; ++i) { 3783 }
3758 if (var == info()->scope()->parameter(i)) { 3784
3759 Bailout("assignment to parameter, function uses arguments object"); 3785 case Variable::CONTEXT: {
3786 ASSERT(var->mode() != Variable::CONST);
3787 // Bail out if we try to mutate a parameter value in a function using
3788 // the arguments object. We do not (yet) correctly handle the
3789 // arguments property of the function.
3790 if (info()->scope()->arguments() != NULL) {
3791 // Parameters will rewrite to context slots. We have no direct way
3792 // to detect that the variable is a parameter.
3793 int count = info()->scope()->num_parameters();
3794 for (int i = 0; i < count; ++i) {
3795 if (var == info()->scope()->parameter(i)) {
3796 return Bailout("assignment to parameter in arguments object");
3797 }
3760 } 3798 }
3761 } 3799 }
3800
3801 CHECK_ALIVE(VisitForValue(expr->value()));
3802 HValue* context = BuildContextChainWalk(var);
3803 HStoreContextSlot* instr =
3804 new(zone()) HStoreContextSlot(context, var->index(), Top());
3805 AddInstruction(instr);
3806 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3807 return ast_context()->ReturnValue(Pop());
3762 } 3808 }
3763 3809
3764 CHECK_ALIVE(VisitForValue(expr->value())); 3810 case Variable::LOOKUP:
3765 HValue* context = BuildContextChainWalk(var); 3811 return Bailout("assignment to LOOKUP variable");
3766 int index = var->AsSlot()->index();
3767 HStoreContextSlot* instr =
3768 new(zone()) HStoreContextSlot(context, index, Top());
3769 AddInstruction(instr);
3770 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
3771 return ast_context()->ReturnValue(Pop());
3772
3773 } else if (var->is_global()) {
3774 CHECK_ALIVE(VisitForValue(expr->value()));
3775 HandleGlobalVariableAssignment(var,
3776 Top(),
3777 expr->position(),
3778 expr->AssignmentId());
3779 return ast_context()->ReturnValue(Pop());
3780
3781 } else {
3782 return Bailout("assignment to LOOKUP or const CONTEXT variable");
3783 } 3812 }
3784
3785 } else if (prop != NULL) {
3786 HandlePropertyAssignment(expr);
3787 } else { 3813 } else {
3788 return Bailout("invalid left-hand side in assignment"); 3814 return Bailout("invalid left-hand side in assignment");
3789 } 3815 }
3790 } 3816 }
3791 3817
3792 3818
3793 void HGraphBuilder::VisitThrow(Throw* expr) { 3819 void HGraphBuilder::VisitThrow(Throw* expr) {
3794 ASSERT(!HasStackOverflow()); 3820 ASSERT(!HasStackOverflow());
3795 ASSERT(current_block() != NULL); 3821 ASSERT(current_block() != NULL);
3796 ASSERT(current_block()->HasPredecessor()); 3822 ASSERT(current_block()->HasPredecessor());
(...skipping 991 matching lines...) Expand 10 before | Expand all | Expand 10 after
4788 // Our implementation of arguments (based on this stack frame or an 4814 // Our implementation of arguments (based on this stack frame or an
4789 // adapter below it) does not work for inlined functions. 4815 // adapter below it) does not work for inlined functions.
4790 if (function_state()->outer() != NULL) { 4816 if (function_state()->outer() != NULL) {
4791 Bailout("Function.prototype.apply optimization in inlined function"); 4817 Bailout("Function.prototype.apply optimization in inlined function");
4792 return true; 4818 return true;
4793 } 4819 }
4794 4820
4795 // Found pattern f.apply(receiver, arguments). 4821 // Found pattern f.apply(receiver, arguments).
4796 VisitForValue(prop->obj()); 4822 VisitForValue(prop->obj());
4797 if (HasStackOverflow() || current_block() == NULL) return true; 4823 if (HasStackOverflow() || current_block() == NULL) return true;
4798 HValue* function = Pop(); 4824 HValue* function = Top();
4825 AddCheckConstantFunction(expr, function, function_map, true);
4826 Drop(1);
4827
4799 VisitForValue(args->at(0)); 4828 VisitForValue(args->at(0));
4800 if (HasStackOverflow() || current_block() == NULL) return true; 4829 if (HasStackOverflow() || current_block() == NULL) return true;
4801 HValue* receiver = Pop(); 4830 HValue* receiver = Pop();
4802 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 4831 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements);
4803 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 4832 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements));
4804 AddCheckConstantFunction(expr, function, function_map, true);
4805 HInstruction* result = 4833 HInstruction* result =
4806 new(zone()) HApplyArguments(function, receiver, length, elements); 4834 new(zone()) HApplyArguments(function, receiver, length, elements);
4807 result->set_position(expr->position()); 4835 result->set_position(expr->position());
4808 ast_context()->ReturnInstruction(result, expr->id()); 4836 ast_context()->ReturnInstruction(result, expr->id());
4809 return true; 4837 return true;
4810 } 4838 }
4811 4839
4812 4840
4813 void HGraphBuilder::VisitCall(Call* expr) { 4841 void HGraphBuilder::VisitCall(Call* expr) {
4814 ASSERT(!HasStackOverflow()); 4842 ASSERT(!HasStackOverflow());
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
4886 HandlePolymorphicCallNamed(expr, receiver, types, name); 4914 HandlePolymorphicCallNamed(expr, receiver, types, name);
4887 return; 4915 return;
4888 4916
4889 } else { 4917 } else {
4890 HValue* context = environment()->LookupContext(); 4918 HValue* context = environment()->LookupContext();
4891 call = PreProcessCall( 4919 call = PreProcessCall(
4892 new(zone()) HCallNamed(context, name, argument_count)); 4920 new(zone()) HCallNamed(context, name, argument_count));
4893 } 4921 }
4894 4922
4895 } else { 4923 } else {
4896 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4924 VariableProxy* proxy = expr->expression()->AsVariableProxy();
4897 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4925 // FIXME.
4926 bool global_call = proxy != NULL && proxy->var()->IsUnallocated();
4898 4927
4899 if (global_call) { 4928 if (global_call) {
4929 Variable* var = proxy->var();
4900 bool known_global_function = false; 4930 bool known_global_function = false;
4901 // If there is a global property cell for the name at compile time and 4931 // If there is a global property cell for the name at compile time and
4902 // access check is not enabled we assume that the function will not change 4932 // access check is not enabled we assume that the function will not change
4903 // and generate optimized code for calling the function. 4933 // and generate optimized code for calling the function.
4904 LookupResult lookup; 4934 LookupResult lookup;
4905 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 4935 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false);
4906 if (type == kUseCell && 4936 if (type == kUseCell &&
4907 !info()->global_object()->IsAccessCheckNeeded()) { 4937 !info()->global_object()->IsAccessCheckNeeded()) {
4908 Handle<GlobalObject> global(info()->global_object()); 4938 Handle<GlobalObject> global(info()->global_object());
4909 known_global_function = expr->ComputeGlobalTarget(global, &lookup); 4939 known_global_function = expr->ComputeGlobalTarget(global, &lookup);
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
5053 case Token::ADD: return VisitAdd(expr); 5083 case Token::ADD: return VisitAdd(expr);
5054 case Token::SUB: return VisitSub(expr); 5084 case Token::SUB: return VisitSub(expr);
5055 case Token::BIT_NOT: return VisitBitNot(expr); 5085 case Token::BIT_NOT: return VisitBitNot(expr);
5056 case Token::NOT: return VisitNot(expr); 5086 case Token::NOT: return VisitNot(expr);
5057 default: UNREACHABLE(); 5087 default: UNREACHABLE();
5058 } 5088 }
5059 } 5089 }
5060 5090
5061 void HGraphBuilder::VisitDelete(UnaryOperation* expr) { 5091 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
5062 Property* prop = expr->expression()->AsProperty(); 5092 Property* prop = expr->expression()->AsProperty();
5063 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 5093 VariableProxy* proxy = expr->expression()->AsVariableProxy();
5064 if (prop == NULL && var == NULL) { 5094 if (prop != NULL) {
5095 CHECK_ALIVE(VisitForValue(prop->obj()));
5096 CHECK_ALIVE(VisitForValue(prop->key()));
5097 HValue* key = Pop();
5098 HValue* obj = Pop();
5099 HValue* context = environment()->LookupContext();
5100 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
5101 return ast_context()->ReturnInstruction(instr, expr->id());
5102 } else if (proxy != NULL) {
5103 Variable* var = proxy->var();
5104 if (var->IsUnallocated()) {
5105 Bailout("delete with global variable");
5106 } else if (var->IsStackAllocated() || var->IsContextSlot()) {
5107 // Result of deleting non-global variables is false. 'this' is not
5108 // really a variable, though we implement it as one. The
5109 // subexpression does not have side effects.
5110 HValue* value = var->is_this()
5111 ? graph()->GetConstantTrue()
5112 : graph()->GetConstantFalse();
5113 return ast_context()->ReturnValue(value);
5114 } else {
5115 Bailout("delete with non-global variable");
5116 }
5117 } else {
5065 // Result of deleting non-property, non-variable reference is true. 5118 // Result of deleting non-property, non-variable reference is true.
5066 // Evaluate the subexpression for side effects. 5119 // Evaluate the subexpression for side effects.
5067 CHECK_ALIVE(VisitForEffect(expr->expression())); 5120 CHECK_ALIVE(VisitForEffect(expr->expression()));
5068 return ast_context()->ReturnValue(graph()->GetConstantTrue()); 5121 return ast_context()->ReturnValue(graph()->GetConstantTrue());
5069 } else if (var != NULL &&
5070 !var->is_global() &&
5071 var->AsSlot() != NULL &&
5072 var->AsSlot()->type() != Slot::LOOKUP) {
5073 // Result of deleting non-global, non-dynamic variables is false.
5074 // The subexpression does not have side effects.
5075 return ast_context()->ReturnValue(graph()->GetConstantFalse());
5076 } else if (prop != NULL) {
5077 if (prop->is_synthetic()) {
5078 // Result of deleting parameters is false, even when they rewrite
5079 // to accesses on the arguments object.
5080 return ast_context()->ReturnValue(graph()->GetConstantFalse());
5081 } else {
5082 CHECK_ALIVE(VisitForValue(prop->obj()));
5083 CHECK_ALIVE(VisitForValue(prop->key()));
5084 HValue* key = Pop();
5085 HValue* obj = Pop();
5086 HValue* context = environment()->LookupContext();
5087 HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key);
5088 return ast_context()->ReturnInstruction(instr, expr->id());
5089 }
5090 } else if (var->is_global()) {
5091 Bailout("delete with global variable");
5092 } else {
5093 Bailout("delete with non-global variable");
5094 } 5122 }
5095 } 5123 }
5096 5124
5097 5125
5098 void HGraphBuilder::VisitVoid(UnaryOperation* expr) { 5126 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
5099 CHECK_ALIVE(VisitForEffect(expr->expression())); 5127 CHECK_ALIVE(VisitForEffect(expr->expression()));
5100 return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 5128 return ast_context()->ReturnValue(graph()->GetConstantUndefined());
5101 } 5129 }
5102 5130
5103 5131
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
5230 return instr; 5258 return instr;
5231 } 5259 }
5232 5260
5233 5261
5234 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { 5262 void HGraphBuilder::VisitCountOperation(CountOperation* expr) {
5235 ASSERT(!HasStackOverflow()); 5263 ASSERT(!HasStackOverflow());
5236 ASSERT(current_block() != NULL); 5264 ASSERT(current_block() != NULL);
5237 ASSERT(current_block()->HasPredecessor()); 5265 ASSERT(current_block()->HasPredecessor());
5238 Expression* target = expr->expression(); 5266 Expression* target = expr->expression();
5239 VariableProxy* proxy = target->AsVariableProxy(); 5267 VariableProxy* proxy = target->AsVariableProxy();
5240 Variable* var = proxy->AsVariable();
5241 Property* prop = target->AsProperty(); 5268 Property* prop = target->AsProperty();
5242 if (var == NULL && prop == NULL) { 5269 if (proxy == NULL && prop == NULL) {
5243 return Bailout("invalid lhs in count operation"); 5270 return Bailout("invalid lhs in count operation");
5244 } 5271 }
5245 5272
5246 // Match the full code generator stack by simulating an extra stack 5273 // Match the full code generator stack by simulating an extra stack
5247 // element for postfix operations in a non-effect context. The return 5274 // element for postfix operations in a non-effect context. The return
5248 // value is ToNumber(input). 5275 // value is ToNumber(input).
5249 bool returns_original_input = 5276 bool returns_original_input =
5250 expr->is_postfix() && !ast_context()->IsEffect(); 5277 expr->is_postfix() && !ast_context()->IsEffect();
5251 HValue* input = NULL; // ToNumber(original_input). 5278 HValue* input = NULL; // ToNumber(original_input).
5252 HValue* after = NULL; // The result after incrementing or decrementing. 5279 HValue* after = NULL; // The result after incrementing or decrementing.
5253 5280
5254 if (var != NULL) { 5281 if (proxy != NULL) {
5282 Variable* var = proxy->var();
5255 if (var->mode() == Variable::CONST) { 5283 if (var->mode() == Variable::CONST) {
5256 return Bailout("unsupported count operation with const"); 5284 return Bailout("unsupported count operation with const");
5257 } 5285 }
5258 // Argument of the count operation is a variable, not a property. 5286 // Argument of the count operation is a variable, not a property.
5259 ASSERT(prop == NULL); 5287 ASSERT(prop == NULL);
5260 CHECK_ALIVE(VisitForValue(target)); 5288 CHECK_ALIVE(VisitForValue(target));
5261 5289
5262 after = BuildIncrement(returns_original_input, expr); 5290 after = BuildIncrement(returns_original_input, expr);
5263 input = returns_original_input ? Top() : Pop(); 5291 input = returns_original_input ? Top() : Pop();
5264 Push(after); 5292 Push(after);
5265 5293
5266 if (var->is_global()) { 5294 switch (var->location()) {
5267 HandleGlobalVariableAssignment(var, 5295 case Variable::UNALLOCATED:
5268 after, 5296 HandleGlobalVariableAssignment(var,
5269 expr->position(), 5297 after,
5270 expr->AssignmentId()); 5298 expr->position(),
5271 } else if (var->IsStackAllocated()) { 5299 expr->AssignmentId());
5272 Bind(var, after); 5300 break;
5273 } else if (var->IsContextSlot()) { 5301
5274 // Bail out if we try to mutate a parameter value in a function using 5302 case Variable::PARAMETER:
5275 // the arguments object. We do not (yet) correctly handle the 5303 case Variable::LOCAL:
5276 // arguments property of the function. 5304 Bind(var, after);
5277 if (info()->scope()->arguments() != NULL) { 5305 break;
5278 // Parameters will rewrite to context slots. We have no direct way 5306
5279 // to detect that the variable is a parameter. 5307 case Variable::CONTEXT: {
5280 int count = info()->scope()->num_parameters(); 5308 // Bail out if we try to mutate a parameter value in a function
5281 for (int i = 0; i < count; ++i) { 5309 // using the arguments object. We do not (yet) correctly handle the
5282 if (var == info()->scope()->parameter(i)) { 5310 // arguments property of the function.
5283 Bailout("assignment to parameter, function uses arguments object"); 5311 if (info()->scope()->arguments() != NULL) {
5312 // Parameters will rewrite to context slots. We have no direct
5313 // way to detect that the variable is a parameter so we use a
5314 // linear search of the parameter list.
5315 int count = info()->scope()->num_parameters();
5316 for (int i = 0; i < count; ++i) {
5317 if (var == info()->scope()->parameter(i)) {
5318 return Bailout("assignment to parameter in arguments object");
5319 }
5284 } 5320 }
5285 } 5321 }
5322
5323 HValue* context = BuildContextChainWalk(var);
5324 HStoreContextSlot* instr =
5325 new(zone()) HStoreContextSlot(context, var->index(), after);
5326 AddInstruction(instr);
5327 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
5328 break;
5286 } 5329 }
5287 5330
5288 HValue* context = BuildContextChainWalk(var); 5331 case Variable::LOOKUP:
5289 int index = var->AsSlot()->index(); 5332 return Bailout("lookup variable in count operation");
5290 HStoreContextSlot* instr =
5291 new(zone()) HStoreContextSlot(context, index, after);
5292 AddInstruction(instr);
5293 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId());
5294 } else {
5295 return Bailout("lookup variable in count operation");
5296 } 5333 }
5297 5334
5298 } else { 5335 } else {
5299 // Argument of the count operation is a property. 5336 // Argument of the count operation is a property.
5300 ASSERT(prop != NULL); 5337 ASSERT(prop != NULL);
5301 prop->RecordTypeFeedback(oracle()); 5338 prop->RecordTypeFeedback(oracle());
5302 5339
5303 if (prop->key()->IsPropertyName()) { 5340 if (prop->key()->IsPropertyName()) {
5304 // Named property. 5341 // Named property.
5305 if (returns_original_input) Push(graph_->GetConstantUndefined()); 5342 if (returns_original_input) Push(graph_->GetConstantUndefined());
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
5697 HValue* context = environment()->LookupContext(); 5734 HValue* context = environment()->LookupContext();
5698 HValue* right = Pop(); 5735 HValue* right = Pop();
5699 HValue* left = Pop(); 5736 HValue* left = Pop();
5700 Token::Value op = expr->op(); 5737 Token::Value op = expr->op();
5701 5738
5702 if (op == Token::INSTANCEOF) { 5739 if (op == Token::INSTANCEOF) {
5703 // Check to see if the rhs of the instanceof is a global function not 5740 // Check to see if the rhs of the instanceof is a global function not
5704 // residing in new space. If it is we assume that the function will stay the 5741 // residing in new space. If it is we assume that the function will stay the
5705 // same. 5742 // same.
5706 Handle<JSFunction> target = Handle<JSFunction>::null(); 5743 Handle<JSFunction> target = Handle<JSFunction>::null();
5707 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5744 VariableProxy* proxy = expr->right()->AsVariableProxy();
5708 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5745 bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
5709 if (global_function && 5746 if (global_function &&
5710 info()->has_global_object() && 5747 info()->has_global_object() &&
5711 !info()->global_object()->IsAccessCheckNeeded()) { 5748 !info()->global_object()->IsAccessCheckNeeded()) {
5712 Handle<String> name = var->name(); 5749 Handle<String> name = proxy->name();
5713 Handle<GlobalObject> global(info()->global_object()); 5750 Handle<GlobalObject> global(info()->global_object());
5714 LookupResult lookup; 5751 LookupResult lookup;
5715 global->Lookup(*name, &lookup); 5752 global->Lookup(*name, &lookup);
5716 if (lookup.IsProperty() && 5753 if (lookup.IsProperty() &&
5717 lookup.type() == NORMAL && 5754 lookup.type() == NORMAL &&
5718 lookup.GetValue()->IsJSFunction()) { 5755 lookup.GetValue()->IsJSFunction()) {
5719 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5756 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5720 // If the function is in new space we assume it's more likely to 5757 // If the function is in new space we assume it's more likely to
5721 // change and thus prefer the general IC code. 5758 // change and thus prefer the general IC code.
5722 if (!isolate()->heap()->InNewSpace(*candidate)) { 5759 if (!isolate()->heap()->InNewSpace(*candidate)) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
5801 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 5838 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) {
5802 ASSERT(!HasStackOverflow()); 5839 ASSERT(!HasStackOverflow());
5803 ASSERT(current_block() != NULL); 5840 ASSERT(current_block() != NULL);
5804 ASSERT(current_block()->HasPredecessor()); 5841 ASSERT(current_block()->HasPredecessor());
5805 HThisFunction* self = new(zone()) HThisFunction; 5842 HThisFunction* self = new(zone()) HThisFunction;
5806 return ast_context()->ReturnInstruction(self, expr->id()); 5843 return ast_context()->ReturnInstruction(self, expr->id());
5807 } 5844 }
5808 5845
5809 5846
5810 void HGraphBuilder::VisitDeclaration(Declaration* decl) { 5847 void HGraphBuilder::VisitDeclaration(Declaration* decl) {
5811 // We support only declarations that do not require code generation. 5848 HandleDeclaration(decl->proxy(), decl->mode(), decl->fun());
5812 Variable* var = decl->proxy()->var(); 5849 }
5813 if (!var->IsStackAllocated() || decl->fun() != NULL) {
5814 return Bailout("unsupported declaration");
5815 }
5816 5850
5817 if (decl->mode() == Variable::CONST) { 5851
5818 ASSERT(var->IsStackAllocated()); 5852 void HGraphBuilder::HandleDeclaration(VariableProxy* proxy,
5819 environment()->Bind(var, graph()->GetConstantHole()); 5853 Variable::Mode mode,
5854 FunctionLiteral* function) {
5855 if (mode == Variable::LET) return Bailout("unsupported let declaration");
5856 Variable* var = proxy->var();
5857 switch (var->location()) {
5858 case Variable::UNALLOCATED:
5859 return Bailout("unsupported global declaration");
5860 case Variable::PARAMETER:
5861 case Variable::LOCAL:
5862 case Variable::CONTEXT:
5863 if (mode == Variable::CONST || function != NULL) {
5864 HValue* value = NULL;
5865 if (mode == Variable::CONST) {
5866 value = graph()->GetConstantHole();
5867 } else {
5868 VisitForValue(function);
5869 value = Pop();
5870 }
5871 if (var->IsContextSlot()) {
5872 HValue* context = environment()->LookupContext();
5873 HStoreContextSlot* store =
5874 new HStoreContextSlot(context, var->index(), value);
5875 AddInstruction(store);
5876 if (store->HasSideEffects()) AddSimulate(proxy->id());
5877 } else {
5878 environment()->Bind(var, value);
5879 }
5880 }
5881 break;
5882 case Variable::LOOKUP:
5883 return Bailout("unsupported lookup slot in declaration");
5820 } 5884 }
5821 } 5885 }
5822 5886
5823 5887
5824 // Generators for inline runtime functions. 5888 // Generators for inline runtime functions.
5825 // Support for types. 5889 // Support for types.
5826 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { 5890 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) {
5827 ASSERT(call->arguments()->length() == 1); 5891 ASSERT(call->arguments()->length() == 1);
5828 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5892 CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
5829 HValue* value = Pop(); 5893 HValue* value = Pop();
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after
6215 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 6279 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value);
6216 return ast_context()->ReturnInstruction(result, call->id()); 6280 return ast_context()->ReturnInstruction(result, call->id());
6217 } 6281 }
6218 6282
6219 6283
6220 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 6284 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) {
6221 return Bailout("inlined runtime function: FastAsciiArrayJoin"); 6285 return Bailout("inlined runtime function: FastAsciiArrayJoin");
6222 } 6286 }
6223 6287
6224 6288
6225 void HGraphBuilder::GenerateIsNativeOrStrictMode(CallRuntime* call) {
6226 return Bailout("inlined runtime function: IsNativeOrStrictMode");
6227 }
6228
6229
6230 #undef CHECK_BAILOUT 6289 #undef CHECK_BAILOUT
6231 #undef CHECK_ALIVE 6290 #undef CHECK_ALIVE
6232 6291
6233 6292
6234 HEnvironment::HEnvironment(HEnvironment* outer, 6293 HEnvironment::HEnvironment(HEnvironment* outer,
6235 Scope* scope, 6294 Scope* scope,
6236 Handle<JSFunction> closure) 6295 Handle<JSFunction> closure)
6237 : closure_(closure), 6296 : closure_(closure),
6238 values_(0), 6297 values_(0),
6239 assigned_variables_(4), 6298 assigned_variables_(4),
(...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after
6751 } 6810 }
6752 } 6811 }
6753 6812
6754 #ifdef DEBUG 6813 #ifdef DEBUG
6755 if (graph_ != NULL) graph_->Verify(); 6814 if (graph_ != NULL) graph_->Verify();
6756 if (allocator_ != NULL) allocator_->Verify(); 6815 if (allocator_ != NULL) allocator_->Verify();
6757 #endif 6816 #endif
6758 } 6817 }
6759 6818
6760 } } // namespace v8::internal 6819 } } // 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