| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 } | 863 } |
| 864 } | 864 } |
| 865 // Replace the uses and add phis modified to the work list. | 865 // Replace the uses and add phis modified to the work list. |
| 866 for (int i = 0; i < uses_to_replace.length(); ++i) { | 866 for (int i = 0; i < uses_to_replace.length(); ++i) { |
| 867 HValue* use = uses_to_replace[i]; | 867 HValue* use = uses_to_replace[i]; |
| 868 phi->ReplaceAtUse(use, value); | 868 phi->ReplaceAtUse(use, value); |
| 869 if (use->IsPhi()) worklist.Add(HPhi::cast(use)); | 869 if (use->IsPhi()) worklist.Add(HPhi::cast(use)); |
| 870 } | 870 } |
| 871 uses_to_replace.Rewind(0); | 871 uses_to_replace.Rewind(0); |
| 872 block->RemovePhi(phi); | 872 block->RemovePhi(phi); |
| 873 } else if (phi->HasNoUses() && | 873 } else if (FLAG_eliminate_dead_phis && phi->HasNoUses() && |
| 874 !phi->HasReceiverOperand() && | 874 !phi->IsReceiver()) { |
| 875 FLAG_eliminate_dead_phis) { | 875 // We can't eliminate phis in the receiver position in the environment |
| 876 // We can't eliminate phis that have the receiver as an operand | 876 // because in case of throwing an error we need this value to |
| 877 // because in case of throwing an error we need the correct | 877 // construct a stack trace. |
| 878 // receiver value in the environment to construct a corrent | |
| 879 // stack trace. | |
| 880 block->RemovePhi(phi); | 878 block->RemovePhi(phi); |
| 881 block->RecordDeletedPhi(phi->merged_index()); | 879 block->RecordDeletedPhi(phi->merged_index()); |
| 882 } | 880 } |
| 883 } | 881 } |
| 884 } | 882 } |
| 885 | 883 |
| 886 | 884 |
| 887 bool HGraph::CollectPhis() { | 885 bool HGraph::CollectPhis() { |
| 888 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); | 886 const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); |
| 889 phi_list_ = new ZoneList<HPhi*>(blocks->length()); | 887 phi_list_ = new ZoneList<HPhi*>(blocks->length()); |
| (...skipping 916 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1806 | 1804 |
| 1807 current = current->EnsureAndPropagateNotMinusZero(visited); | 1805 current = current->EnsureAndPropagateNotMinusZero(visited); |
| 1808 } | 1806 } |
| 1809 } | 1807 } |
| 1810 | 1808 |
| 1811 | 1809 |
| 1812 void HGraph::InsertRepresentationChangeForUse(HValue* value, | 1810 void HGraph::InsertRepresentationChangeForUse(HValue* value, |
| 1813 HValue* use, | 1811 HValue* use, |
| 1814 Representation to, | 1812 Representation to, |
| 1815 bool is_truncating) { | 1813 bool is_truncating) { |
| 1816 // Propagate flags for negative zero checks upwards from conversions | |
| 1817 // int32-to-tagged and int32-to-double. | |
| 1818 Representation from = value->representation(); | |
| 1819 if (from.IsInteger32()) { | |
| 1820 ASSERT(to.IsTagged() || to.IsDouble()); | |
| 1821 BitVector visited(GetMaximumValueID()); | |
| 1822 PropagateMinusZeroChecks(value, &visited); | |
| 1823 } | |
| 1824 | |
| 1825 // Insert the representation change right before its use. For phi-uses we | 1814 // Insert the representation change right before its use. For phi-uses we |
| 1826 // insert at the end of the corresponding predecessor. | 1815 // insert at the end of the corresponding predecessor. |
| 1827 HBasicBlock* insert_block = use->block(); | 1816 HBasicBlock* insert_block = use->block(); |
| 1828 if (use->IsPhi()) { | 1817 if (use->IsPhi()) { |
| 1829 int index = 0; | 1818 int index = 0; |
| 1830 while (use->OperandAt(index) != value) ++index; | 1819 while (use->OperandAt(index) != value) ++index; |
| 1831 insert_block = insert_block->predecessors()->at(index); | 1820 insert_block = insert_block->predecessors()->at(index); |
| 1832 } | 1821 } |
| 1833 | 1822 |
| 1834 HInstruction* next = (insert_block == use->block()) | 1823 HInstruction* next = (insert_block == use->block()) |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1977 // Process normal instructions. | 1966 // Process normal instructions. |
| 1978 HInstruction* current = blocks_[i]->first(); | 1967 HInstruction* current = blocks_[i]->first(); |
| 1979 while (current != NULL) { | 1968 while (current != NULL) { |
| 1980 InsertRepresentationChanges(current); | 1969 InsertRepresentationChanges(current); |
| 1981 current = current->next(); | 1970 current = current->next(); |
| 1982 } | 1971 } |
| 1983 } | 1972 } |
| 1984 } | 1973 } |
| 1985 | 1974 |
| 1986 | 1975 |
| 1976 void HGraph::ComputeMinusZeroChecks() { |
| 1977 BitVector visited(GetMaximumValueID()); |
| 1978 for (int i = 0; i < blocks_.length(); ++i) { |
| 1979 for (HInstruction* current = blocks_[i]->first(); |
| 1980 current != NULL; |
| 1981 current = current->next()) { |
| 1982 if (current->IsChange()) { |
| 1983 HChange* change = HChange::cast(current); |
| 1984 // Propagate flags for negative zero checks upwards from conversions |
| 1985 // int32-to-tagged and int32-to-double. |
| 1986 Representation from = change->value()->representation(); |
| 1987 ASSERT(from.Equals(change->from())); |
| 1988 if (from.IsInteger32()) { |
| 1989 ASSERT(change->to().IsTagged() || change->to().IsDouble()); |
| 1990 ASSERT(visited.IsEmpty()); |
| 1991 PropagateMinusZeroChecks(change->value(), &visited); |
| 1992 visited.Clear(); |
| 1993 } |
| 1994 } |
| 1995 } |
| 1996 } |
| 1997 } |
| 1998 |
| 1999 |
| 1987 // Implementation of utility classes to represent an expression's context in | 2000 // Implementation of utility classes to represent an expression's context in |
| 1988 // the AST. | 2001 // the AST. |
| 1989 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) | 2002 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) |
| 1990 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { | 2003 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { |
| 1991 owner->set_ast_context(this); // Push. | 2004 owner->set_ast_context(this); // Push. |
| 1992 #ifdef DEBUG | 2005 #ifdef DEBUG |
| 1993 original_length_ = owner->environment()->length(); | 2006 original_length_ = owner->environment()->length(); |
| 1994 #endif | 2007 #endif |
| 1995 } | 2008 } |
| 1996 | 2009 |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2236 rep.Analyze(); | 2249 rep.Analyze(); |
| 2237 | 2250 |
| 2238 if (FLAG_use_range) { | 2251 if (FLAG_use_range) { |
| 2239 HRangeAnalysis rangeAnalysis(graph_); | 2252 HRangeAnalysis rangeAnalysis(graph_); |
| 2240 rangeAnalysis.Analyze(); | 2253 rangeAnalysis.Analyze(); |
| 2241 } | 2254 } |
| 2242 | 2255 |
| 2243 graph_->InitializeInferredTypes(); | 2256 graph_->InitializeInferredTypes(); |
| 2244 graph_->Canonicalize(); | 2257 graph_->Canonicalize(); |
| 2245 graph_->InsertRepresentationChanges(); | 2258 graph_->InsertRepresentationChanges(); |
| 2259 graph_->ComputeMinusZeroChecks(); |
| 2246 | 2260 |
| 2247 // Eliminate redundant stack checks on backwards branches. | 2261 // Eliminate redundant stack checks on backwards branches. |
| 2248 HStackCheckEliminator sce(graph_); | 2262 HStackCheckEliminator sce(graph_); |
| 2249 sce.Process(); | 2263 sce.Process(); |
| 2250 | 2264 |
| 2251 // Perform common subexpression elimination and loop-invariant code motion. | 2265 // Perform common subexpression elimination and loop-invariant code motion. |
| 2252 if (FLAG_use_gvn) { | 2266 if (FLAG_use_gvn) { |
| 2253 HPhase phase("Global value numbering", graph_); | 2267 HPhase phase("Global value numbering", graph_); |
| 2254 HGlobalValueNumberer gvn(graph_); | 2268 HGlobalValueNumberer gvn(graph_); |
| 2255 gvn.Analyze(); | 2269 gvn.Analyze(); |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2929 global->Lookup(*var->name(), lookup); | 2943 global->Lookup(*var->name(), lookup); |
| 2930 if (!lookup->IsProperty()) { | 2944 if (!lookup->IsProperty()) { |
| 2931 BAILOUT("global variable cell not yet introduced"); | 2945 BAILOUT("global variable cell not yet introduced"); |
| 2932 } | 2946 } |
| 2933 if (lookup->type() != NORMAL) { | 2947 if (lookup->type() != NORMAL) { |
| 2934 BAILOUT("global variable has accessors"); | 2948 BAILOUT("global variable has accessors"); |
| 2935 } | 2949 } |
| 2936 if (is_store && lookup->IsReadOnly()) { | 2950 if (is_store && lookup->IsReadOnly()) { |
| 2937 BAILOUT("read-only global variable"); | 2951 BAILOUT("read-only global variable"); |
| 2938 } | 2952 } |
| 2953 if (lookup->holder() != *global) { |
| 2954 BAILOUT("global property on prototype of global object"); |
| 2955 } |
| 2956 } |
| 2957 |
| 2958 |
| 2959 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 2960 ASSERT(var->IsContextSlot()); |
| 2961 HInstruction* context = new HContext; |
| 2962 AddInstruction(context); |
| 2963 int length = graph()->info()->scope()->ContextChainLength(var->scope()); |
| 2964 while (length-- > 0) { |
| 2965 context = new HOuterContext(context); |
| 2966 AddInstruction(context); |
| 2967 } |
| 2968 return context; |
| 2939 } | 2969 } |
| 2940 | 2970 |
| 2941 | 2971 |
| 2942 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2972 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 2943 Variable* variable = expr->AsVariable(); | 2973 Variable* variable = expr->AsVariable(); |
| 2944 if (variable == NULL) { | 2974 if (variable == NULL) { |
| 2945 BAILOUT("reference to rewritten variable"); | 2975 BAILOUT("reference to rewritten variable"); |
| 2946 } else if (variable->IsStackAllocated()) { | 2976 } else if (variable->IsStackAllocated()) { |
| 2947 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2977 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
| 2948 BAILOUT("unsupported context for arguments object"); | 2978 BAILOUT("unsupported context for arguments object"); |
| 2949 } | 2979 } |
| 2950 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2980 ast_context()->ReturnValue(environment()->Lookup(variable)); |
| 2951 } else if (variable->IsContextSlot()) { | 2981 } else if (variable->IsContextSlot()) { |
| 2952 if (variable->mode() == Variable::CONST) { | 2982 if (variable->mode() == Variable::CONST) { |
| 2953 BAILOUT("reference to const context slot"); | 2983 BAILOUT("reference to const context slot"); |
| 2954 } | 2984 } |
| 2955 Slot* slot = variable->AsSlot(); | 2985 HValue* context = BuildContextChainWalk(variable); |
| 2956 CompilationInfo* info = graph()->info(); | 2986 int index = variable->AsSlot()->index(); |
| 2957 int context_chain_length = info->function()->scope()-> | 2987 HLoadContextSlot* instr = new HLoadContextSlot(context, index); |
| 2958 ContextChainLength(slot->var()->scope()); | |
| 2959 ASSERT(context_chain_length >= 0); | |
| 2960 // TODO(antonm): if slot's value is not modified by closures, instead | |
| 2961 // of reading it out of context, we could just embed the value as | |
| 2962 // a constant. | |
| 2963 HLoadContextSlot* instr = | |
| 2964 new HLoadContextSlot(context_chain_length, slot->index()); | |
| 2965 ast_context()->ReturnInstruction(instr, expr->id()); | 2988 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2966 } else if (variable->is_global()) { | 2989 } else if (variable->is_global()) { |
| 2967 LookupResult lookup; | 2990 LookupResult lookup; |
| 2968 LookupGlobalPropertyCell(variable, &lookup, false); | 2991 LookupGlobalPropertyCell(variable, &lookup, false); |
| 2969 CHECK_BAILOUT; | 2992 CHECK_BAILOUT; |
| 2970 | 2993 |
| 2971 Handle<GlobalObject> global(graph()->info()->global_object()); | 2994 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 2972 // TODO(3039103): Handle global property load through an IC call when access | 2995 // TODO(3039103): Handle global property load through an IC call when access |
| 2973 // checks are enabled. | 2996 // checks are enabled. |
| 2974 if (global->IsAccessCheckNeeded()) { | 2997 if (global->IsAccessCheckNeeded()) { |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3363 // superclass of Assignment and CountOperation, we cannot just pass the | 3386 // superclass of Assignment and CountOperation, we cannot just pass the |
| 3364 // owning expression instead of position and ast_id separately. | 3387 // owning expression instead of position and ast_id separately. |
| 3365 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3388 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
| 3366 HValue* value, | 3389 HValue* value, |
| 3367 int position, | 3390 int position, |
| 3368 int ast_id) { | 3391 int ast_id) { |
| 3369 LookupResult lookup; | 3392 LookupResult lookup; |
| 3370 LookupGlobalPropertyCell(var, &lookup, true); | 3393 LookupGlobalPropertyCell(var, &lookup, true); |
| 3371 CHECK_BAILOUT; | 3394 CHECK_BAILOUT; |
| 3372 | 3395 |
| 3396 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 3373 Handle<GlobalObject> global(graph()->info()->global_object()); | 3397 Handle<GlobalObject> global(graph()->info()->global_object()); |
| 3374 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3398 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 3375 HInstruction* instr = new HStoreGlobal(value, cell); | 3399 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); |
| 3376 instr->set_position(position); | 3400 instr->set_position(position); |
| 3377 AddInstruction(instr); | 3401 AddInstruction(instr); |
| 3378 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3402 if (instr->HasSideEffects()) AddSimulate(ast_id); |
| 3379 } | 3403 } |
| 3380 | 3404 |
| 3381 | 3405 |
| 3382 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3406 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 3383 Expression* target = expr->target(); | 3407 Expression* target = expr->target(); |
| 3384 VariableProxy* proxy = target->AsVariableProxy(); | 3408 VariableProxy* proxy = target->AsVariableProxy(); |
| 3385 Variable* var = proxy->AsVariable(); | 3409 Variable* var = proxy->AsVariable(); |
| 3386 Property* prop = target->AsProperty(); | 3410 Property* prop = target->AsProperty(); |
| 3387 ASSERT(var == NULL || prop == NULL); | 3411 ASSERT(var == NULL || prop == NULL); |
| 3388 | 3412 |
| 3389 // We have a second position recorded in the FullCodeGenerator to have | 3413 // We have a second position recorded in the FullCodeGenerator to have |
| 3390 // type feedback for the binary operation. | 3414 // type feedback for the binary operation. |
| 3391 BinaryOperation* operation = expr->binary_operation(); | 3415 BinaryOperation* operation = expr->binary_operation(); |
| 3392 operation->RecordTypeFeedback(oracle()); | |
| 3393 | 3416 |
| 3394 if (var != NULL) { | 3417 if (var != NULL) { |
| 3395 if (!var->is_global() && !var->IsStackAllocated()) { | 3418 if (!var->is_global() && !var->IsStackAllocated()) { |
| 3396 BAILOUT("non-stack/non-global in compound assignment"); | 3419 BAILOUT("non-stack/non-global in compound assignment"); |
| 3397 } | 3420 } |
| 3398 | 3421 |
| 3399 VISIT_FOR_VALUE(operation); | 3422 VISIT_FOR_VALUE(operation); |
| 3400 | 3423 |
| 3401 if (var->is_global()) { | 3424 if (var->is_global()) { |
| 3402 HandleGlobalVariableAssignment(var, | 3425 HandleGlobalVariableAssignment(var, |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3492 | 3515 |
| 3493 if (expr->is_compound()) { | 3516 if (expr->is_compound()) { |
| 3494 HandleCompoundAssignment(expr); | 3517 HandleCompoundAssignment(expr); |
| 3495 return; | 3518 return; |
| 3496 } | 3519 } |
| 3497 | 3520 |
| 3498 if (var != NULL) { | 3521 if (var != NULL) { |
| 3499 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); | 3522 if (proxy->IsArguments()) BAILOUT("assignment to arguments"); |
| 3500 | 3523 |
| 3501 // Handle the assignment. | 3524 // Handle the assignment. |
| 3502 if (var->is_global()) { | 3525 if (var->IsStackAllocated()) { |
| 3526 HValue* value = NULL; |
| 3527 // Handle stack-allocated variables on the right-hand side directly. |
| 3528 // We do not allow the arguments object to occur in a context where it |
| 3529 // may escape, but assignments to stack-allocated locals are |
| 3530 // permitted. Handling such assignments here bypasses the check for |
| 3531 // the arguments object in VisitVariableProxy. |
| 3532 Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable(); |
| 3533 if (rhs_var != NULL && rhs_var->IsStackAllocated()) { |
| 3534 value = environment()->Lookup(rhs_var); |
| 3535 } else { |
| 3536 VISIT_FOR_VALUE(expr->value()); |
| 3537 value = Pop(); |
| 3538 } |
| 3539 Bind(var, value); |
| 3540 ast_context()->ReturnValue(value); |
| 3541 |
| 3542 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { |
| 3543 VISIT_FOR_VALUE(expr->value()); |
| 3544 HValue* context = BuildContextChainWalk(var); |
| 3545 int index = var->AsSlot()->index(); |
| 3546 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top()); |
| 3547 AddInstruction(instr); |
| 3548 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| 3549 ast_context()->ReturnValue(Pop()); |
| 3550 |
| 3551 } else if (var->is_global()) { |
| 3503 VISIT_FOR_VALUE(expr->value()); | 3552 VISIT_FOR_VALUE(expr->value()); |
| 3504 HandleGlobalVariableAssignment(var, | 3553 HandleGlobalVariableAssignment(var, |
| 3505 Top(), | 3554 Top(), |
| 3506 expr->position(), | 3555 expr->position(), |
| 3507 expr->AssignmentId()); | 3556 expr->AssignmentId()); |
| 3508 } else if (var->IsStackAllocated()) { | 3557 ast_context()->ReturnValue(Pop()); |
| 3509 // We allow reference to the arguments object only in assignemtns | 3558 |
| 3510 // to local variables to make sure that the arguments object does | |
| 3511 // not escape and is not modified. | |
| 3512 VariableProxy* rhs = expr->value()->AsVariableProxy(); | |
| 3513 if (rhs != NULL && | |
| 3514 rhs->var()->IsStackAllocated() && | |
| 3515 environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { | |
| 3516 Push(environment()->Lookup(rhs->var())); | |
| 3517 } else { | |
| 3518 VISIT_FOR_VALUE(expr->value()); | |
| 3519 } | |
| 3520 Bind(proxy->var(), Top()); | |
| 3521 } else { | 3559 } else { |
| 3522 BAILOUT("Assigning to no non-stack-allocated/non-global variable"); | 3560 BAILOUT("assignment to LOOKUP or const CONTEXT variable"); |
| 3523 } | 3561 } |
| 3524 // Return the value. | |
| 3525 ast_context()->ReturnValue(Pop()); | |
| 3526 | 3562 |
| 3527 } else if (prop != NULL) { | 3563 } else if (prop != NULL) { |
| 3528 HandlePropertyAssignment(expr); | 3564 HandlePropertyAssignment(expr); |
| 3529 } else { | 3565 } else { |
| 3530 BAILOUT("unsupported invalid lhs"); | 3566 BAILOUT("invalid left-hand side in assignment"); |
| 3531 } | 3567 } |
| 3532 } | 3568 } |
| 3533 | 3569 |
| 3534 | 3570 |
| 3535 void HGraphBuilder::VisitThrow(Throw* expr) { | 3571 void HGraphBuilder::VisitThrow(Throw* expr) { |
| 3536 // We don't optimize functions with invalid left-hand sides in | 3572 // We don't optimize functions with invalid left-hand sides in |
| 3537 // assignments, count operations, or for-in. Consequently throw can | 3573 // assignments, count operations, or for-in. Consequently throw can |
| 3538 // currently only occur in an effect context. | 3574 // currently only occur in an effect context. |
| 3539 ASSERT(ast_context()->IsEffect()); | 3575 ASSERT(ast_context()->IsEffect()); |
| 3540 VISIT_FOR_VALUE(expr->exception()); | 3576 VISIT_FOR_VALUE(expr->exception()); |
| 3541 | 3577 |
| 3542 HValue* value = environment()->Pop(); | 3578 HValue* value = environment()->Pop(); |
| 3543 HControlInstruction* instr = new HThrow(value); | 3579 HThrow* instr = new HThrow(value); |
| 3544 instr->set_position(expr->position()); | 3580 instr->set_position(expr->position()); |
| 3545 current_subgraph_->FinishExit(instr); | 3581 AddInstruction(instr); |
| 3582 AddSimulate(expr->id()); |
| 3583 current_subgraph_->FinishExit(new HAbnormalExit); |
| 3546 } | 3584 } |
| 3547 | 3585 |
| 3548 | 3586 |
| 3549 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, | 3587 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, |
| 3550 HValue* object, | 3588 HValue* object, |
| 3551 ZoneMapList* types, | 3589 ZoneMapList* types, |
| 3552 Handle<String> name) { | 3590 Handle<String> name) { |
| 3553 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); | 3591 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); |
| 3554 ZoneMapList maps(number_of_types); | 3592 ZoneMapList maps(number_of_types); |
| 3555 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); | 3593 ZoneList<HSubgraph*> subgraphs(number_of_types + 1); |
| (...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4397 // access check is not enabled we assume that the function will not change | 4435 // access check is not enabled we assume that the function will not change |
| 4398 // and generate optimized code for calling the function. | 4436 // and generate optimized code for calling the function. |
| 4399 CompilationInfo* info = graph()->info(); | 4437 CompilationInfo* info = graph()->info(); |
| 4400 bool known_global_function = info->has_global_object() && | 4438 bool known_global_function = info->has_global_object() && |
| 4401 !info->global_object()->IsAccessCheckNeeded() && | 4439 !info->global_object()->IsAccessCheckNeeded() && |
| 4402 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), | 4440 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), |
| 4403 var->name()); | 4441 var->name()); |
| 4404 if (known_global_function) { | 4442 if (known_global_function) { |
| 4405 // Push the global object instead of the global receiver because | 4443 // Push the global object instead of the global receiver because |
| 4406 // code generated by the full code generator expects it. | 4444 // code generated by the full code generator expects it. |
| 4407 PushAndAdd(new HGlobalObject); | 4445 HContext* context = new HContext; |
| 4446 HGlobalObject* global_object = new HGlobalObject(context); |
| 4447 AddInstruction(context); |
| 4448 PushAndAdd(global_object); |
| 4408 VisitArgumentList(expr->arguments()); | 4449 VisitArgumentList(expr->arguments()); |
| 4409 CHECK_BAILOUT; | 4450 CHECK_BAILOUT; |
| 4410 | 4451 |
| 4411 VISIT_FOR_VALUE(expr->expression()); | 4452 VISIT_FOR_VALUE(expr->expression()); |
| 4412 HValue* function = Pop(); | 4453 HValue* function = Pop(); |
| 4413 AddInstruction(new HCheckFunction(function, expr->target())); | 4454 AddInstruction(new HCheckFunction(function, expr->target())); |
| 4414 | 4455 |
| 4415 // Replace the global object with the global receiver. | 4456 // Replace the global object with the global receiver. |
| 4416 HGlobalReceiver* global_receiver = new HGlobalReceiver; | 4457 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); |
| 4417 // Index of the receiver from the top of the expression stack. | 4458 // Index of the receiver from the top of the expression stack. |
| 4418 const int receiver_index = argument_count - 1; | 4459 const int receiver_index = argument_count - 1; |
| 4419 AddInstruction(global_receiver); | 4460 AddInstruction(global_receiver); |
| 4420 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4461 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
| 4421 IsGlobalObject()); | 4462 IsGlobalObject()); |
| 4422 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4463 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
| 4423 | 4464 |
| 4424 if (TryInline(expr)) { | 4465 if (TryInline(expr)) { |
| 4425 if (subgraph()->HasExit()) { | 4466 if (subgraph()->HasExit()) { |
| 4426 HValue* return_value = Pop(); | 4467 HValue* return_value = Pop(); |
| 4427 // If we inlined a function in a test context then we need to | 4468 // If we inlined a function in a test context then we need to |
| 4428 // emit a simulate here to shadow the ones at the end of the | 4469 // emit a simulate here to shadow the ones at the end of the |
| 4429 // predecessor blocks. Those environments contain the return | 4470 // predecessor blocks. Those environments contain the return |
| 4430 // value on top and do not correspond to any actual state of the | 4471 // value on top and do not correspond to any actual state of the |
| 4431 // unoptimized code. | 4472 // unoptimized code. |
| 4432 if (ast_context()->IsEffect()) AddSimulate(expr->id()); | 4473 if (ast_context()->IsEffect()) AddSimulate(expr->id()); |
| 4433 ast_context()->ReturnValue(return_value); | 4474 ast_context()->ReturnValue(return_value); |
| 4434 } | 4475 } |
| 4435 return; | 4476 return; |
| 4436 } | 4477 } |
| 4437 // Check for bailout, as trying to inline might fail due to bailout | 4478 // Check for bailout, as trying to inline might fail due to bailout |
| 4438 // during hydrogen processing. | 4479 // during hydrogen processing. |
| 4439 CHECK_BAILOUT; | 4480 CHECK_BAILOUT; |
| 4440 | 4481 |
| 4441 call = new HCallKnownGlobal(expr->target(), argument_count); | 4482 call = new HCallKnownGlobal(expr->target(), argument_count); |
| 4442 } else { | 4483 } else { |
| 4443 PushAndAdd(new HGlobalObject); | 4484 HContext* context = new HContext; |
| 4485 AddInstruction(context); |
| 4486 PushAndAdd(new HGlobalObject(context)); |
| 4444 VisitArgumentList(expr->arguments()); | 4487 VisitArgumentList(expr->arguments()); |
| 4445 CHECK_BAILOUT; | 4488 CHECK_BAILOUT; |
| 4446 | 4489 |
| 4447 call = new HCallGlobal(var->name(), argument_count); | 4490 call = new HCallGlobal(var->name(), argument_count); |
| 4448 } | 4491 } |
| 4449 | 4492 |
| 4450 } else { | 4493 } else { |
| 4451 PushAndAdd(new HGlobalReceiver); | 4494 HContext* context = new HContext; |
| 4495 HGlobalObject* global_object = new HGlobalObject(context); |
| 4496 AddInstruction(context); |
| 4497 AddInstruction(global_object); |
| 4498 PushAndAdd(new HGlobalReceiver(global_object)); |
| 4452 VisitArgumentList(expr->arguments()); | 4499 VisitArgumentList(expr->arguments()); |
| 4453 CHECK_BAILOUT; | 4500 CHECK_BAILOUT; |
| 4454 | 4501 |
| 4455 call = new HCallFunction(argument_count); | 4502 call = new HCallFunction(argument_count); |
| 4456 } | 4503 } |
| 4457 } | 4504 } |
| 4458 | 4505 |
| 4459 call->set_position(expr->position()); | 4506 call->set_position(expr->position()); |
| 4460 ProcessCall(call); | 4507 ProcessCall(call); |
| 4461 ast_context()->ReturnInstruction(call, expr->id()); | 4508 ast_context()->ReturnInstruction(call, expr->id()); |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4806 break; | 4853 break; |
| 4807 case Token::SHR: | 4854 case Token::SHR: |
| 4808 instr = new HShr(left, right); | 4855 instr = new HShr(left, right); |
| 4809 break; | 4856 break; |
| 4810 case Token::SHL: | 4857 case Token::SHL: |
| 4811 instr = new HShl(left, right); | 4858 instr = new HShl(left, right); |
| 4812 break; | 4859 break; |
| 4813 default: | 4860 default: |
| 4814 UNREACHABLE(); | 4861 UNREACHABLE(); |
| 4815 } | 4862 } |
| 4816 TypeInfo info = oracle()->BinaryType(expr, TypeFeedbackOracle::RESULT); | 4863 TypeInfo info = oracle()->BinaryType(expr); |
| 4817 // If we hit an uninitialized binary op stub we will get type info | 4864 // If we hit an uninitialized binary op stub we will get type info |
| 4818 // for a smi operation. If one of the operands is a constant string | 4865 // for a smi operation. If one of the operands is a constant string |
| 4819 // do not generate code assuming it is a smi operation. | 4866 // do not generate code assuming it is a smi operation. |
| 4820 if (info.IsSmi() && | 4867 if (info.IsSmi() && |
| 4821 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || | 4868 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || |
| 4822 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { | 4869 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { |
| 4823 return instr; | 4870 return instr; |
| 4824 } | 4871 } |
| 4825 if (FLAG_trace_representation) { | 4872 if (FLAG_trace_representation) { |
| 4826 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic()); | 4873 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic()); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4957 return; | 5004 return; |
| 4958 } | 5005 } |
| 4959 | 5006 |
| 4960 VISIT_FOR_VALUE(expr->left()); | 5007 VISIT_FOR_VALUE(expr->left()); |
| 4961 VISIT_FOR_VALUE(expr->right()); | 5008 VISIT_FOR_VALUE(expr->right()); |
| 4962 | 5009 |
| 4963 HValue* right = Pop(); | 5010 HValue* right = Pop(); |
| 4964 HValue* left = Pop(); | 5011 HValue* left = Pop(); |
| 4965 Token::Value op = expr->op(); | 5012 Token::Value op = expr->op(); |
| 4966 | 5013 |
| 4967 TypeInfo info = oracle()->CompareType(expr, TypeFeedbackOracle::RESULT); | 5014 TypeInfo info = oracle()->CompareType(expr); |
| 4968 HInstruction* instr = NULL; | 5015 HInstruction* instr = NULL; |
| 4969 if (op == Token::INSTANCEOF) { | 5016 if (op == Token::INSTANCEOF) { |
| 4970 // Check to see if the rhs of the instanceof is a global function not | 5017 // Check to see if the rhs of the instanceof is a global function not |
| 4971 // residing in new space. If it is we assume that the function will stay the | 5018 // residing in new space. If it is we assume that the function will stay the |
| 4972 // same. | 5019 // same. |
| 4973 Handle<JSFunction> target = Handle<JSFunction>::null(); | 5020 Handle<JSFunction> target = Handle<JSFunction>::null(); |
| 4974 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); | 5021 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); |
| 4975 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); | 5022 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); |
| 4976 CompilationInfo* info = graph()->info(); | 5023 CompilationInfo* info = graph()->info(); |
| 4977 if (global_function && | 5024 if (global_function && |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5132 } | 5179 } |
| 5133 | 5180 |
| 5134 | 5181 |
| 5135 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 5182 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 5136 int argument_count, | 5183 int argument_count, |
| 5137 int ast_id) { | 5184 int ast_id) { |
| 5138 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 5185 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| 5139 } | 5186 } |
| 5140 | 5187 |
| 5141 | 5188 |
| 5142 // Support for construct call checks. | 5189 // Support for construct call checks. |
| 5143 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { | 5190 void HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { |
| 5144 BAILOUT("inlined runtime function: IsConstructCall"); | 5191 ASSERT(argument_count == 0); |
| 5192 ast_context()->ReturnInstruction(new HIsConstructCall, ast_id); |
| 5145 } | 5193 } |
| 5146 | 5194 |
| 5147 | 5195 |
| 5148 // Support for arguments.length and arguments[?]. | 5196 // Support for arguments.length and arguments[?]. |
| 5149 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { | 5197 void HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { |
| 5150 ASSERT(argument_count == 0); | 5198 ASSERT(argument_count == 0); |
| 5151 HInstruction* elements = AddInstruction(new HArgumentsElements); | 5199 HInstruction* elements = AddInstruction(new HArgumentsElements); |
| 5152 HArgumentsLength* result = new HArgumentsLength(elements); | 5200 HArgumentsLength* result = new HArgumentsLength(elements); |
| 5153 ast_context()->ReturnInstruction(result, ast_id); | 5201 ast_context()->ReturnInstruction(result, ast_id); |
| 5154 } | 5202 } |
| (...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5878 } | 5926 } |
| 5879 } | 5927 } |
| 5880 | 5928 |
| 5881 #ifdef DEBUG | 5929 #ifdef DEBUG |
| 5882 if (graph_ != NULL) graph_->Verify(); | 5930 if (graph_ != NULL) graph_->Verify(); |
| 5883 if (allocator_ != NULL) allocator_->Verify(); | 5931 if (allocator_ != NULL) allocator_->Verify(); |
| 5884 #endif | 5932 #endif |
| 5885 } | 5933 } |
| 5886 | 5934 |
| 5887 } } // namespace v8::internal | 5935 } } // namespace v8::internal |
| OLD | NEW |