| 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 2211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2222 // We don't yet handle the function name for named function expressions. | 2222 // We don't yet handle the function name for named function expressions. |
| 2223 if (scope->function() != NULL) return Bailout("named function expression"); | 2223 if (scope->function() != NULL) return Bailout("named function expression"); |
| 2224 | 2224 |
| 2225 HConstant* undefined_constant = new(zone()) HConstant( | 2225 HConstant* undefined_constant = new(zone()) HConstant( |
| 2226 isolate()->factory()->undefined_value(), Representation::Tagged()); | 2226 isolate()->factory()->undefined_value(), Representation::Tagged()); |
| 2227 AddInstruction(undefined_constant); | 2227 AddInstruction(undefined_constant); |
| 2228 graph_->set_undefined_constant(undefined_constant); | 2228 graph_->set_undefined_constant(undefined_constant); |
| 2229 | 2229 |
| 2230 // Set the initial values of parameters including "this". "This" has | 2230 // Set the initial values of parameters including "this". "This" has |
| 2231 // parameter index 0. | 2231 // parameter index 0. |
| 2232 int count = scope->num_parameters() + 1; | 2232 ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); |
| 2233 for (int i = 0; i < count; ++i) { | 2233 |
| 2234 for (int i = 0; i < environment()->parameter_count(); ++i) { |
| 2234 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); | 2235 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); |
| 2235 environment()->Bind(i, parameter); | 2236 environment()->Bind(i, parameter); |
| 2236 } | 2237 } |
| 2237 | 2238 |
| 2238 // Set the initial values of stack-allocated locals. | 2239 // First special is HContext. |
| 2239 for (int i = count; i < environment()->length(); ++i) { | 2240 HInstruction* context = AddInstruction(new(zone()) HContext); |
| 2241 environment()->BindContext(context); |
| 2242 |
| 2243 // Initialize specials and locals to undefined. |
| 2244 for (int i = environment()->parameter_count() + 1; |
| 2245 i < environment()->length(); |
| 2246 ++i) { |
| 2240 environment()->Bind(i, undefined_constant); | 2247 environment()->Bind(i, undefined_constant); |
| 2241 } | 2248 } |
| 2242 | 2249 |
| 2243 // Handle the arguments and arguments shadow variables specially (they do | 2250 // Handle the arguments and arguments shadow variables specially (they do |
| 2244 // not have declarations). | 2251 // not have declarations). |
| 2245 if (scope->arguments() != NULL) { | 2252 if (scope->arguments() != NULL) { |
| 2246 if (!scope->arguments()->IsStackAllocated() || | 2253 if (!scope->arguments()->IsStackAllocated() || |
| 2247 (scope->arguments_shadow() != NULL && | 2254 (scope->arguments_shadow() != NULL && |
| 2248 !scope->arguments_shadow()->IsStackAllocated())) { | 2255 !scope->arguments_shadow()->IsStackAllocated())) { |
| 2249 return Bailout("context-allocated arguments"); | 2256 return Bailout("context-allocated arguments"); |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2586 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); | 2593 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); |
| 2587 current_block()->Finish(test); | 2594 current_block()->Finish(test); |
| 2588 | 2595 |
| 2589 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 2596 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
| 2590 non_osr_entry->Goto(loop_predecessor); | 2597 non_osr_entry->Goto(loop_predecessor); |
| 2591 | 2598 |
| 2592 set_current_block(osr_entry); | 2599 set_current_block(osr_entry); |
| 2593 int osr_entry_id = statement->OsrEntryId(); | 2600 int osr_entry_id = statement->OsrEntryId(); |
| 2594 // We want the correct environment at the OsrEntry instruction. Build | 2601 // We want the correct environment at the OsrEntry instruction. Build |
| 2595 // it explicitly. The expression stack should be empty. | 2602 // it explicitly. The expression stack should be empty. |
| 2596 int count = environment()->length(); | 2603 ASSERT(environment()->ExpressionStackIsEmpty()); |
| 2597 ASSERT(count == | 2604 for (int i = 0; i < environment()->length(); ++i) { |
| 2598 (environment()->parameter_count() + environment()->local_count())); | 2605 HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; |
| 2599 for (int i = 0; i < count; ++i) { | 2606 AddInstruction(osr_value); |
| 2600 HUnknownOSRValue* unknown = new(zone()) HUnknownOSRValue; | 2607 environment()->Bind(i, osr_value); |
| 2601 AddInstruction(unknown); | |
| 2602 environment()->Bind(i, unknown); | |
| 2603 } | 2608 } |
| 2604 | 2609 |
| 2605 AddSimulate(osr_entry_id); | 2610 AddSimulate(osr_entry_id); |
| 2606 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); | 2611 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); |
| 2612 HContext* context = new(zone()) HContext; |
| 2613 AddInstruction(context); |
| 2614 environment()->BindContext(context); |
| 2607 current_block()->Goto(loop_predecessor); | 2615 current_block()->Goto(loop_predecessor); |
| 2608 loop_predecessor->SetJoinId(statement->EntryId()); | 2616 loop_predecessor->SetJoinId(statement->EntryId()); |
| 2609 set_current_block(loop_predecessor); | 2617 set_current_block(loop_predecessor); |
| 2610 } | 2618 } |
| 2611 | 2619 |
| 2612 | 2620 |
| 2613 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2621 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 2614 ASSERT(!HasStackOverflow()); | 2622 ASSERT(!HasStackOverflow()); |
| 2615 ASSERT(current_block() != NULL); | 2623 ASSERT(current_block() != NULL); |
| 2616 ASSERT(current_block()->HasPredecessor()); | 2624 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2879 lookup->holder() != *global) { | 2887 lookup->holder() != *global) { |
| 2880 return kUseGeneric; | 2888 return kUseGeneric; |
| 2881 } | 2889 } |
| 2882 | 2890 |
| 2883 return kUseCell; | 2891 return kUseCell; |
| 2884 } | 2892 } |
| 2885 | 2893 |
| 2886 | 2894 |
| 2887 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 2895 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 2888 ASSERT(var->IsContextSlot()); | 2896 ASSERT(var->IsContextSlot()); |
| 2889 HInstruction* context = new(zone()) HContext; | 2897 HValue* context = environment()->LookupContext(); |
| 2890 AddInstruction(context); | |
| 2891 int length = info()->scope()->ContextChainLength(var->scope()); | 2898 int length = info()->scope()->ContextChainLength(var->scope()); |
| 2892 while (length-- > 0) { | 2899 while (length-- > 0) { |
| 2893 context = new(zone()) HOuterContext(context); | 2900 HInstruction* context_instruction = new(zone()) HOuterContext(context); |
| 2894 AddInstruction(context); | 2901 AddInstruction(context_instruction); |
| 2902 context = context_instruction; |
| 2895 } | 2903 } |
| 2896 return context; | 2904 return context; |
| 2897 } | 2905 } |
| 2898 | 2906 |
| 2899 | 2907 |
| 2900 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2908 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 2901 ASSERT(!HasStackOverflow()); | 2909 ASSERT(!HasStackOverflow()); |
| 2902 ASSERT(current_block() != NULL); | 2910 ASSERT(current_block() != NULL); |
| 2903 ASSERT(current_block()->HasPredecessor()); | 2911 ASSERT(current_block()->HasPredecessor()); |
| 2904 Variable* variable = expr->AsVariable(); | 2912 Variable* variable = expr->AsVariable(); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2923 type = kUseGeneric; | 2931 type = kUseGeneric; |
| 2924 } | 2932 } |
| 2925 | 2933 |
| 2926 if (type == kUseCell) { | 2934 if (type == kUseCell) { |
| 2927 Handle<GlobalObject> global(info()->global_object()); | 2935 Handle<GlobalObject> global(info()->global_object()); |
| 2928 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 2936 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 2929 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 2937 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 2930 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); | 2938 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); |
| 2931 ast_context()->ReturnInstruction(instr, expr->id()); | 2939 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2932 } else { | 2940 } else { |
| 2933 HContext* context = new(zone()) HContext; | 2941 HValue* context = environment()->LookupContext(); |
| 2934 AddInstruction(context); | |
| 2935 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 2942 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 2936 AddInstruction(global_object); | 2943 AddInstruction(global_object); |
| 2937 HLoadGlobalGeneric* instr = | 2944 HLoadGlobalGeneric* instr = |
| 2938 new(zone()) HLoadGlobalGeneric(context, | 2945 new(zone()) HLoadGlobalGeneric(context, |
| 2939 global_object, | 2946 global_object, |
| 2940 variable->name(), | 2947 variable->name(), |
| 2941 ast_context()->is_for_typeof()); | 2948 ast_context()->is_for_typeof()); |
| 2942 instr->set_position(expr->position()); | 2949 instr->set_position(expr->position()); |
| 2943 ASSERT(instr->HasSideEffects()); | 2950 ASSERT(instr->HasSideEffects()); |
| 2944 ast_context()->ReturnInstruction(instr, expr->id()); | 2951 ast_context()->ReturnInstruction(instr, expr->id()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2967 expr->flags(), | 2974 expr->flags(), |
| 2968 expr->literal_index()); | 2975 expr->literal_index()); |
| 2969 ast_context()->ReturnInstruction(instr, expr->id()); | 2976 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2970 } | 2977 } |
| 2971 | 2978 |
| 2972 | 2979 |
| 2973 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 2980 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 2974 ASSERT(!HasStackOverflow()); | 2981 ASSERT(!HasStackOverflow()); |
| 2975 ASSERT(current_block() != NULL); | 2982 ASSERT(current_block() != NULL); |
| 2976 ASSERT(current_block()->HasPredecessor()); | 2983 ASSERT(current_block()->HasPredecessor()); |
| 2977 HContext* context = new(zone()) HContext; | 2984 HValue* context = environment()->LookupContext(); |
| 2978 AddInstruction(context); | |
| 2979 HObjectLiteral* literal = | 2985 HObjectLiteral* literal = |
| 2980 new(zone()) HObjectLiteral(context, | 2986 new(zone()) HObjectLiteral(context, |
| 2981 expr->constant_properties(), | 2987 expr->constant_properties(), |
| 2982 expr->fast_elements(), | 2988 expr->fast_elements(), |
| 2983 expr->literal_index(), | 2989 expr->literal_index(), |
| 2984 expr->depth(), | 2990 expr->depth(), |
| 2985 expr->has_function()); | 2991 expr->has_function()); |
| 2986 // The object is expected in the bailout environment during computation | 2992 // The object is expected in the bailout environment during computation |
| 2987 // of the property values and is the value of the entire expression. | 2993 // of the property values and is the value of the entire expression. |
| 2988 PushAndAdd(literal); | 2994 PushAndAdd(literal); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3150 // enable elimination of redundant checks after the transition store. | 3156 // enable elimination of redundant checks after the transition store. |
| 3151 instr->SetFlag(HValue::kChangesMaps); | 3157 instr->SetFlag(HValue::kChangesMaps); |
| 3152 } | 3158 } |
| 3153 return instr; | 3159 return instr; |
| 3154 } | 3160 } |
| 3155 | 3161 |
| 3156 | 3162 |
| 3157 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 3163 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
| 3158 Handle<String> name, | 3164 Handle<String> name, |
| 3159 HValue* value) { | 3165 HValue* value) { |
| 3160 HContext* context = new(zone()) HContext; | 3166 HValue* context = environment()->LookupContext(); |
| 3161 AddInstruction(context); | |
| 3162 return new(zone()) HStoreNamedGeneric( | 3167 return new(zone()) HStoreNamedGeneric( |
| 3163 context, | 3168 context, |
| 3164 object, | 3169 object, |
| 3165 name, | 3170 name, |
| 3166 value, | 3171 value, |
| 3167 function_strict_mode()); | 3172 function_strict_mode()); |
| 3168 } | 3173 } |
| 3169 | 3174 |
| 3170 | 3175 |
| 3171 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, | 3176 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3327 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 3332 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 3328 if (type == kUseCell) { | 3333 if (type == kUseCell) { |
| 3329 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3334 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 3330 Handle<GlobalObject> global(info()->global_object()); | 3335 Handle<GlobalObject> global(info()->global_object()); |
| 3331 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3336 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 3332 HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole); | 3337 HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole); |
| 3333 instr->set_position(position); | 3338 instr->set_position(position); |
| 3334 AddInstruction(instr); | 3339 AddInstruction(instr); |
| 3335 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3340 if (instr->HasSideEffects()) AddSimulate(ast_id); |
| 3336 } else { | 3341 } else { |
| 3337 HContext* context = new(zone()) HContext; | 3342 HValue* context = environment()->LookupContext(); |
| 3338 AddInstruction(context); | |
| 3339 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 3343 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 3340 AddInstruction(global_object); | 3344 AddInstruction(global_object); |
| 3341 HStoreGlobalGeneric* instr = | 3345 HStoreGlobalGeneric* instr = |
| 3342 new(zone()) HStoreGlobalGeneric(context, | 3346 new(zone()) HStoreGlobalGeneric(context, |
| 3343 global_object, | 3347 global_object, |
| 3344 var->name(), | 3348 var->name(), |
| 3345 value, | 3349 value, |
| 3346 function_strict_mode()); | 3350 function_strict_mode()); |
| 3347 instr->set_position(position); | 3351 instr->set_position(position); |
| 3348 AddInstruction(instr); | 3352 AddInstruction(instr); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3553 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 3557 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 3554 return new(zone()) HLoadNamedField(object, false, offset); | 3558 return new(zone()) HLoadNamedField(object, false, offset); |
| 3555 } | 3559 } |
| 3556 } | 3560 } |
| 3557 | 3561 |
| 3558 | 3562 |
| 3559 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, | 3563 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, |
| 3560 Property* expr) { | 3564 Property* expr) { |
| 3561 ASSERT(expr->key()->IsPropertyName()); | 3565 ASSERT(expr->key()->IsPropertyName()); |
| 3562 Handle<Object> name = expr->key()->AsLiteral()->handle(); | 3566 Handle<Object> name = expr->key()->AsLiteral()->handle(); |
| 3563 HContext* context = new(zone()) HContext; | 3567 HValue* context = environment()->LookupContext(); |
| 3564 AddInstruction(context); | |
| 3565 return new(zone()) HLoadNamedGeneric(context, obj, name); | 3568 return new(zone()) HLoadNamedGeneric(context, obj, name); |
| 3566 } | 3569 } |
| 3567 | 3570 |
| 3568 | 3571 |
| 3569 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, | 3572 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, |
| 3570 Property* expr, | 3573 Property* expr, |
| 3571 Handle<Map> map, | 3574 Handle<Map> map, |
| 3572 Handle<String> name) { | 3575 Handle<String> name) { |
| 3573 LookupResult lookup; | 3576 LookupResult lookup; |
| 3574 map->LookupInDescriptors(NULL, *name, &lookup); | 3577 map->LookupInDescriptors(NULL, *name, &lookup); |
| 3575 if (lookup.IsProperty() && lookup.type() == FIELD) { | 3578 if (lookup.IsProperty() && lookup.type() == FIELD) { |
| 3576 return BuildLoadNamedField(obj, | 3579 return BuildLoadNamedField(obj, |
| 3577 expr, | 3580 expr, |
| 3578 map, | 3581 map, |
| 3579 &lookup, | 3582 &lookup, |
| 3580 true); | 3583 true); |
| 3581 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { | 3584 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { |
| 3582 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 3585 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 3583 AddInstruction(new(zone()) HCheckMap(obj, map)); | 3586 AddInstruction(new(zone()) HCheckMap(obj, map)); |
| 3584 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 3587 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 3585 return new(zone()) HConstant(function, Representation::Tagged()); | 3588 return new(zone()) HConstant(function, Representation::Tagged()); |
| 3586 } else { | 3589 } else { |
| 3587 return BuildLoadNamedGeneric(obj, expr); | 3590 return BuildLoadNamedGeneric(obj, expr); |
| 3588 } | 3591 } |
| 3589 } | 3592 } |
| 3590 | 3593 |
| 3591 | 3594 |
| 3592 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 3595 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 3593 HValue* key) { | 3596 HValue* key) { |
| 3594 HContext* context = new(zone()) HContext; | 3597 HValue* context = environment()->LookupContext(); |
| 3595 AddInstruction(context); | |
| 3596 return new(zone()) HLoadKeyedGeneric(context, object, key); | 3598 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 3597 } | 3599 } |
| 3598 | 3600 |
| 3599 | 3601 |
| 3600 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, | 3602 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, |
| 3601 HValue* key, | 3603 HValue* key, |
| 3602 Property* expr) { | 3604 Property* expr) { |
| 3603 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); | 3605 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); |
| 3604 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3606 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3605 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3607 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3660 return BuildLoadKeyedFastElement(obj, key, prop); | 3662 return BuildLoadKeyedFastElement(obj, key, prop); |
| 3661 } | 3663 } |
| 3662 } | 3664 } |
| 3663 return BuildLoadKeyedGeneric(obj, key); | 3665 return BuildLoadKeyedGeneric(obj, key); |
| 3664 } | 3666 } |
| 3665 | 3667 |
| 3666 | 3668 |
| 3667 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, | 3669 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, |
| 3668 HValue* key, | 3670 HValue* key, |
| 3669 HValue* value) { | 3671 HValue* value) { |
| 3670 HContext* context = new(zone()) HContext; | 3672 HValue* context = environment()->LookupContext(); |
| 3671 AddInstruction(context); | |
| 3672 return new(zone()) HStoreKeyedGeneric( | 3673 return new(zone()) HStoreKeyedGeneric( |
| 3673 context, | 3674 context, |
| 3674 object, | 3675 object, |
| 3675 key, | 3676 key, |
| 3676 value, | 3677 value, |
| 3677 function_strict_mode()); | 3678 function_strict_mode()); |
| 3678 } | 3679 } |
| 3679 | 3680 |
| 3680 | 3681 |
| 3681 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, | 3682 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3914 set_current_block(if_false); | 3915 set_current_block(if_false); |
| 3915 } | 3916 } |
| 3916 } | 3917 } |
| 3917 | 3918 |
| 3918 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 3919 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 3919 // know about and do not want to handle ones we've never seen. Otherwise | 3920 // know about and do not want to handle ones we've never seen. Otherwise |
| 3920 // use a generic IC. | 3921 // use a generic IC. |
| 3921 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 3922 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 3922 current_block()->FinishExitWithDeoptimization(); | 3923 current_block()->FinishExitWithDeoptimization(); |
| 3923 } else { | 3924 } else { |
| 3924 HContext* context = new(zone()) HContext; | 3925 HValue* context = environment()->LookupContext(); |
| 3925 AddInstruction(context); | |
| 3926 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); | 3926 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
| 3927 call->set_position(expr->position()); | 3927 call->set_position(expr->position()); |
| 3928 PreProcessCall(call); | 3928 PreProcessCall(call); |
| 3929 | 3929 |
| 3930 if (join != NULL) { | 3930 if (join != NULL) { |
| 3931 AddInstruction(call); | 3931 AddInstruction(call); |
| 3932 if (!ast_context()->IsEffect()) Push(call); | 3932 if (!ast_context()->IsEffect()) Push(call); |
| 3933 current_block()->Goto(join); | 3933 current_block()->Goto(join); |
| 3934 } else { | 3934 } else { |
| 3935 ast_context()->ReturnInstruction(call, expr->id()); | 3935 ast_context()->ReturnInstruction(call, expr->id()); |
| (...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4342 | 4342 |
| 4343 CHECK_ALIVE(VisitForValue(prop->key())); | 4343 CHECK_ALIVE(VisitForValue(prop->key())); |
| 4344 // Push receiver and key like the non-optimized code generator expects it. | 4344 // Push receiver and key like the non-optimized code generator expects it. |
| 4345 HValue* key = Pop(); | 4345 HValue* key = Pop(); |
| 4346 HValue* receiver = Pop(); | 4346 HValue* receiver = Pop(); |
| 4347 Push(key); | 4347 Push(key); |
| 4348 Push(receiver); | 4348 Push(receiver); |
| 4349 | 4349 |
| 4350 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4350 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4351 | 4351 |
| 4352 HContext* context = new(zone()) HContext; | 4352 HValue* context = environment()->LookupContext(); |
| 4353 AddInstruction(context); | |
| 4354 call = PreProcessCall( | 4353 call = PreProcessCall( |
| 4355 new(zone()) HCallKeyed(context, key, argument_count)); | 4354 new(zone()) HCallKeyed(context, key, argument_count)); |
| 4356 call->set_position(expr->position()); | 4355 call->set_position(expr->position()); |
| 4357 Drop(1); // Key. | 4356 Drop(1); // Key. |
| 4358 ast_context()->ReturnInstruction(call, expr->id()); | 4357 ast_context()->ReturnInstruction(call, expr->id()); |
| 4359 return; | 4358 return; |
| 4360 } | 4359 } |
| 4361 | 4360 |
| 4362 // Named function call. | 4361 // Named function call. |
| 4363 expr->RecordTypeFeedback(oracle()); | 4362 expr->RecordTypeFeedback(oracle()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4382 receiver_map, | 4381 receiver_map, |
| 4383 expr->check_type())) { | 4382 expr->check_type())) { |
| 4384 return; | 4383 return; |
| 4385 } | 4384 } |
| 4386 | 4385 |
| 4387 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || | 4386 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || |
| 4388 expr->check_type() != RECEIVER_MAP_CHECK) { | 4387 expr->check_type() != RECEIVER_MAP_CHECK) { |
| 4389 // When the target has a custom call IC generator, use the IC, | 4388 // When the target has a custom call IC generator, use the IC, |
| 4390 // because it is likely to generate better code. Also use the IC | 4389 // because it is likely to generate better code. Also use the IC |
| 4391 // when a primitive receiver check is required. | 4390 // when a primitive receiver check is required. |
| 4392 HContext* context = new(zone()) HContext; | 4391 HValue* context = environment()->LookupContext(); |
| 4393 AddInstruction(context); | |
| 4394 call = PreProcessCall( | 4392 call = PreProcessCall( |
| 4395 new(zone()) HCallNamed(context, name, argument_count)); | 4393 new(zone()) HCallNamed(context, name, argument_count)); |
| 4396 } else { | 4394 } else { |
| 4397 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4395 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
| 4398 | 4396 |
| 4399 if (TryInline(expr)) return; | 4397 if (TryInline(expr)) return; |
| 4400 call = PreProcessCall( | 4398 call = PreProcessCall( |
| 4401 new(zone()) HCallConstantFunction(expr->target(), | 4399 new(zone()) HCallConstantFunction(expr->target(), |
| 4402 argument_count)); | 4400 argument_count)); |
| 4403 } | 4401 } |
| 4404 } else if (types != NULL && types->length() > 1) { | 4402 } else if (types != NULL && types->length() > 1) { |
| 4405 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 4403 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
| 4406 HandlePolymorphicCallNamed(expr, receiver, types, name); | 4404 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 4407 return; | 4405 return; |
| 4408 | 4406 |
| 4409 } else { | 4407 } else { |
| 4410 HContext* context = new(zone()) HContext; | 4408 HValue* context = environment()->LookupContext(); |
| 4411 AddInstruction(context); | |
| 4412 call = PreProcessCall( | 4409 call = PreProcessCall( |
| 4413 new(zone()) HCallNamed(context, name, argument_count)); | 4410 new(zone()) HCallNamed(context, name, argument_count)); |
| 4414 } | 4411 } |
| 4415 | 4412 |
| 4416 } else { | 4413 } else { |
| 4417 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4414 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 4418 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); | 4415 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); |
| 4419 | 4416 |
| 4420 if (!global_call) { | 4417 if (!global_call) { |
| 4421 ++argument_count; | 4418 ++argument_count; |
| 4422 CHECK_ALIVE(VisitForValue(expr->expression())); | 4419 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 4423 } | 4420 } |
| 4424 | 4421 |
| 4425 if (global_call) { | 4422 if (global_call) { |
| 4426 bool known_global_function = false; | 4423 bool known_global_function = false; |
| 4427 // If there is a global property cell for the name at compile time and | 4424 // If there is a global property cell for the name at compile time and |
| 4428 // access check is not enabled we assume that the function will not change | 4425 // access check is not enabled we assume that the function will not change |
| 4429 // and generate optimized code for calling the function. | 4426 // and generate optimized code for calling the function. |
| 4430 LookupResult lookup; | 4427 LookupResult lookup; |
| 4431 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 4428 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 4432 if (type == kUseCell && | 4429 if (type == kUseCell && |
| 4433 !info()->global_object()->IsAccessCheckNeeded()) { | 4430 !info()->global_object()->IsAccessCheckNeeded()) { |
| 4434 Handle<GlobalObject> global(info()->global_object()); | 4431 Handle<GlobalObject> global(info()->global_object()); |
| 4435 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 4432 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 4436 } | 4433 } |
| 4437 if (known_global_function) { | 4434 if (known_global_function) { |
| 4438 // Push the global object instead of the global receiver because | 4435 // Push the global object instead of the global receiver because |
| 4439 // code generated by the full code generator expects it. | 4436 // code generated by the full code generator expects it. |
| 4440 HContext* context = new(zone()) HContext; | 4437 HValue* context = environment()->LookupContext(); |
| 4441 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4438 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 4442 AddInstruction(context); | |
| 4443 PushAndAdd(global_object); | 4439 PushAndAdd(global_object); |
| 4444 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4440 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4445 | 4441 |
| 4446 CHECK_ALIVE(VisitForValue(expr->expression())); | 4442 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 4447 HValue* function = Pop(); | 4443 HValue* function = Pop(); |
| 4448 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); | 4444 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); |
| 4449 | 4445 |
| 4450 // Replace the global object with the global receiver. | 4446 // Replace the global object with the global receiver. |
| 4451 HGlobalReceiver* global_receiver = | 4447 HGlobalReceiver* global_receiver = |
| 4452 new(zone()) HGlobalReceiver(global_object); | 4448 new(zone()) HGlobalReceiver(global_object); |
| 4453 // Index of the receiver from the top of the expression stack. | 4449 // Index of the receiver from the top of the expression stack. |
| 4454 const int receiver_index = argument_count - 1; | 4450 const int receiver_index = argument_count - 1; |
| 4455 AddInstruction(global_receiver); | 4451 AddInstruction(global_receiver); |
| 4456 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4452 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
| 4457 IsGlobalObject()); | 4453 IsGlobalObject()); |
| 4458 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4454 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
| 4459 | 4455 |
| 4460 if (TryInline(expr)) return; | 4456 if (TryInline(expr)) return; |
| 4461 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), | 4457 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 4462 argument_count)); | 4458 argument_count)); |
| 4463 } else { | 4459 } else { |
| 4464 HContext* context = new(zone()) HContext; | 4460 HValue* context = environment()->LookupContext(); |
| 4465 AddInstruction(context); | |
| 4466 PushAndAdd(new(zone()) HGlobalObject(context)); | 4461 PushAndAdd(new(zone()) HGlobalObject(context)); |
| 4467 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4462 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4468 | 4463 |
| 4469 call = PreProcessCall(new(zone()) HCallGlobal(context, | 4464 call = PreProcessCall(new(zone()) HCallGlobal(context, |
| 4470 var->name(), | 4465 var->name(), |
| 4471 argument_count)); | 4466 argument_count)); |
| 4472 } | 4467 } |
| 4473 | 4468 |
| 4474 } else { | 4469 } else { |
| 4475 HContext* context = new(zone()) HContext; | 4470 HValue* context = environment()->LookupContext(); |
| 4476 HGlobalObject* global_object = new(zone()) HGlobalObject(context); | 4471 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 4477 AddInstruction(context); | |
| 4478 AddInstruction(global_object); | 4472 AddInstruction(global_object); |
| 4479 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); | 4473 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); |
| 4480 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4474 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4481 | 4475 |
| 4482 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); | 4476 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); |
| 4483 } | 4477 } |
| 4484 } | 4478 } |
| 4485 | 4479 |
| 4486 call->set_position(expr->position()); | 4480 call->set_position(expr->position()); |
| 4487 ast_context()->ReturnInstruction(call, expr->id()); | 4481 ast_context()->ReturnInstruction(call, expr->id()); |
| 4488 } | 4482 } |
| 4489 | 4483 |
| 4490 | 4484 |
| 4491 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 4485 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
| 4492 ASSERT(!HasStackOverflow()); | 4486 ASSERT(!HasStackOverflow()); |
| 4493 ASSERT(current_block() != NULL); | 4487 ASSERT(current_block() != NULL); |
| 4494 ASSERT(current_block()->HasPredecessor()); | 4488 ASSERT(current_block()->HasPredecessor()); |
| 4495 // The constructor function is also used as the receiver argument to the | 4489 // The constructor function is also used as the receiver argument to the |
| 4496 // JS construct call builtin. | 4490 // JS construct call builtin. |
| 4497 CHECK_ALIVE(VisitForValue(expr->expression())); | 4491 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 4498 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4492 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4499 | 4493 |
| 4500 HContext* context = new(zone()) HContext; | 4494 HValue* context = environment()->LookupContext(); |
| 4501 AddInstruction(context); | |
| 4502 | 4495 |
| 4503 // The constructor is both an operand to the instruction and an argument | 4496 // The constructor is both an operand to the instruction and an argument |
| 4504 // to the construct call. | 4497 // to the construct call. |
| 4505 int arg_count = expr->arguments()->length() + 1; // Plus constructor. | 4498 int arg_count = expr->arguments()->length() + 1; // Plus constructor. |
| 4506 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); | 4499 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); |
| 4507 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); | 4500 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); |
| 4508 call->set_position(expr->position()); | 4501 call->set_position(expr->position()); |
| 4509 PreProcessCall(call); | 4502 PreProcessCall(call); |
| 4510 ast_context()->ReturnInstruction(call, expr->id()); | 4503 ast_context()->ReturnInstruction(call, expr->id()); |
| 4511 } | 4504 } |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5114 // change and thus prefer the general IC code. | 5107 // change and thus prefer the general IC code. |
| 5115 if (!isolate()->heap()->InNewSpace(*candidate)) { | 5108 if (!isolate()->heap()->InNewSpace(*candidate)) { |
| 5116 target = candidate; | 5109 target = candidate; |
| 5117 } | 5110 } |
| 5118 } | 5111 } |
| 5119 } | 5112 } |
| 5120 | 5113 |
| 5121 // If the target is not null we have found a known global function that is | 5114 // If the target is not null we have found a known global function that is |
| 5122 // assumed to stay the same for this instanceof. | 5115 // assumed to stay the same for this instanceof. |
| 5123 if (target.is_null()) { | 5116 if (target.is_null()) { |
| 5124 HContext* context = new(zone()) HContext; | 5117 HValue* context = environment()->LookupContext(); |
| 5125 AddInstruction(context); | |
| 5126 instr = new(zone()) HInstanceOf(context, left, right); | 5118 instr = new(zone()) HInstanceOf(context, left, right); |
| 5127 } else { | 5119 } else { |
| 5128 AddInstruction(new(zone()) HCheckFunction(right, target)); | 5120 AddInstruction(new(zone()) HCheckFunction(right, target)); |
| 5129 instr = new(zone()) HInstanceOfKnownGlobal(left, target); | 5121 instr = new(zone()) HInstanceOfKnownGlobal(left, target); |
| 5130 } | 5122 } |
| 5131 } else if (op == Token::IN) { | 5123 } else if (op == Token::IN) { |
| 5132 instr = new(zone()) HIn(left, right); | 5124 instr = new(zone()) HIn(left, right); |
| 5133 } else if (type_info.IsNonPrimitive()) { | 5125 } else if (type_info.IsNonPrimitive()) { |
| 5134 switch (op) { | 5126 switch (op) { |
| 5135 case Token::EQ: | 5127 case Token::EQ: |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5391 // Fast support for Math.random(). | 5383 // Fast support for Math.random(). |
| 5392 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 5384 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
| 5393 return Bailout("inlined runtime function: RandomHeapNumber"); | 5385 return Bailout("inlined runtime function: RandomHeapNumber"); |
| 5394 } | 5386 } |
| 5395 | 5387 |
| 5396 | 5388 |
| 5397 // Fast support for StringAdd. | 5389 // Fast support for StringAdd. |
| 5398 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 5390 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 5399 ASSERT_EQ(2, call->arguments()->length()); | 5391 ASSERT_EQ(2, call->arguments()->length()); |
| 5400 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5392 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5401 HContext* context = new(zone()) HContext; | 5393 HValue* context = environment()->LookupContext(); |
| 5402 AddInstruction(context); | |
| 5403 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); | 5394 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
| 5404 Drop(2); | 5395 Drop(2); |
| 5405 ast_context()->ReturnInstruction(result, call->id()); | 5396 ast_context()->ReturnInstruction(result, call->id()); |
| 5406 } | 5397 } |
| 5407 | 5398 |
| 5408 | 5399 |
| 5409 // Fast support for SubString. | 5400 // Fast support for SubString. |
| 5410 void HGraphBuilder::GenerateSubString(CallRuntime* call) { | 5401 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 5411 ASSERT_EQ(3, call->arguments()->length()); | 5402 ASSERT_EQ(3, call->arguments()->length()); |
| 5412 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5403 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5413 HContext* context = new(zone()) HContext; | 5404 HValue* context = environment()->LookupContext(); |
| 5414 AddInstruction(context); | |
| 5415 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); | 5405 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| 5416 Drop(3); | 5406 Drop(3); |
| 5417 ast_context()->ReturnInstruction(result, call->id()); | 5407 ast_context()->ReturnInstruction(result, call->id()); |
| 5418 } | 5408 } |
| 5419 | 5409 |
| 5420 | 5410 |
| 5421 // Fast support for StringCompare. | 5411 // Fast support for StringCompare. |
| 5422 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 5412 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| 5423 ASSERT_EQ(2, call->arguments()->length()); | 5413 ASSERT_EQ(2, call->arguments()->length()); |
| 5424 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5414 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5425 HContext* context = new(zone()) HContext; | 5415 HValue* context = environment()->LookupContext(); |
| 5426 AddInstruction(context); | |
| 5427 HCallStub* result = | 5416 HCallStub* result = |
| 5428 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); | 5417 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
| 5429 Drop(2); | 5418 Drop(2); |
| 5430 ast_context()->ReturnInstruction(result, call->id()); | 5419 ast_context()->ReturnInstruction(result, call->id()); |
| 5431 } | 5420 } |
| 5432 | 5421 |
| 5433 | 5422 |
| 5434 // Support for direct calls from JavaScript to native RegExp code. | 5423 // Support for direct calls from JavaScript to native RegExp code. |
| 5435 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 5424 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| 5436 ASSERT_EQ(4, call->arguments()->length()); | 5425 ASSERT_EQ(4, call->arguments()->length()); |
| 5437 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5426 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5438 HContext* context = new(zone()) HContext; | 5427 HValue* context = environment()->LookupContext(); |
| 5439 AddInstruction(context); | |
| 5440 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); | 5428 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
| 5441 Drop(4); | 5429 Drop(4); |
| 5442 ast_context()->ReturnInstruction(result, call->id()); | 5430 ast_context()->ReturnInstruction(result, call->id()); |
| 5443 } | 5431 } |
| 5444 | 5432 |
| 5445 | 5433 |
| 5446 // Construct a RegExp exec result with two in-object properties. | 5434 // Construct a RegExp exec result with two in-object properties. |
| 5447 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 5435 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| 5448 ASSERT_EQ(3, call->arguments()->length()); | 5436 ASSERT_EQ(3, call->arguments()->length()); |
| 5449 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5437 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5450 HContext* context = new(zone()) HContext; | 5438 HValue* context = environment()->LookupContext(); |
| 5451 AddInstruction(context); | |
| 5452 HCallStub* result = | 5439 HCallStub* result = |
| 5453 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); | 5440 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
| 5454 Drop(3); | 5441 Drop(3); |
| 5455 ast_context()->ReturnInstruction(result, call->id()); | 5442 ast_context()->ReturnInstruction(result, call->id()); |
| 5456 } | 5443 } |
| 5457 | 5444 |
| 5458 | 5445 |
| 5459 // Support for fast native caches. | 5446 // Support for fast native caches. |
| 5460 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 5447 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 5461 return Bailout("inlined runtime function: GetFromCache"); | 5448 return Bailout("inlined runtime function: GetFromCache"); |
| 5462 } | 5449 } |
| 5463 | 5450 |
| 5464 | 5451 |
| 5465 // Fast support for number to string. | 5452 // Fast support for number to string. |
| 5466 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 5453 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 5467 ASSERT_EQ(1, call->arguments()->length()); | 5454 ASSERT_EQ(1, call->arguments()->length()); |
| 5468 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5455 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5469 HContext* context = new(zone()) HContext; | 5456 HValue* context = environment()->LookupContext(); |
| 5470 AddInstruction(context); | |
| 5471 HCallStub* result = | 5457 HCallStub* result = |
| 5472 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); | 5458 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
| 5473 Drop(1); | 5459 Drop(1); |
| 5474 ast_context()->ReturnInstruction(result, call->id()); | 5460 ast_context()->ReturnInstruction(result, call->id()); |
| 5475 } | 5461 } |
| 5476 | 5462 |
| 5477 | 5463 |
| 5478 // Fast swapping of elements. Takes three expressions, the object and two | 5464 // Fast swapping of elements. Takes three expressions, the object and two |
| 5479 // indices. This should only be used if the indices are known to be | 5465 // indices. This should only be used if the indices are known to be |
| 5480 // non-negative and within bounds of the elements array at the call site. | 5466 // non-negative and within bounds of the elements array at the call site. |
| 5481 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { | 5467 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { |
| 5482 return Bailout("inlined runtime function: SwapElements"); | 5468 return Bailout("inlined runtime function: SwapElements"); |
| 5483 } | 5469 } |
| 5484 | 5470 |
| 5485 | 5471 |
| 5486 // Fast call for custom callbacks. | 5472 // Fast call for custom callbacks. |
| 5487 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 5473 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 5488 // 1 ~ The function to call is not itself an argument to the call. | 5474 // 1 ~ The function to call is not itself an argument to the call. |
| 5489 int arg_count = call->arguments()->length() - 1; | 5475 int arg_count = call->arguments()->length() - 1; |
| 5490 ASSERT(arg_count >= 1); // There's always at least a receiver. | 5476 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 5491 | 5477 |
| 5492 for (int i = 0; i < arg_count; ++i) { | 5478 for (int i = 0; i < arg_count; ++i) { |
| 5493 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); | 5479 CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); |
| 5494 } | 5480 } |
| 5495 CHECK_ALIVE(VisitForValue(call->arguments()->last())); | 5481 CHECK_ALIVE(VisitForValue(call->arguments()->last())); |
| 5496 HValue* function = Pop(); | 5482 HValue* function = Pop(); |
| 5497 HContext* context = new HContext; | 5483 HValue* context = environment()->LookupContext(); |
| 5498 AddInstruction(context); | |
| 5499 HInvokeFunction* result = | 5484 HInvokeFunction* result = |
| 5500 new(zone()) HInvokeFunction(context, function, arg_count); | 5485 new(zone()) HInvokeFunction(context, function, arg_count); |
| 5501 Drop(arg_count); | 5486 Drop(arg_count); |
| 5502 ast_context()->ReturnInstruction(result, call->id()); | 5487 ast_context()->ReturnInstruction(result, call->id()); |
| 5503 } | 5488 } |
| 5504 | 5489 |
| 5505 | 5490 |
| 5506 // Fast call to math functions. | 5491 // Fast call to math functions. |
| 5507 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { | 5492 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| 5508 ASSERT_EQ(2, call->arguments()->length()); | 5493 ASSERT_EQ(2, call->arguments()->length()); |
| 5509 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 5494 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 5510 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 5495 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
| 5511 HValue* right = Pop(); | 5496 HValue* right = Pop(); |
| 5512 HValue* left = Pop(); | 5497 HValue* left = Pop(); |
| 5513 HPower* result = new(zone()) HPower(left, right); | 5498 HPower* result = new(zone()) HPower(left, right); |
| 5514 ast_context()->ReturnInstruction(result, call->id()); | 5499 ast_context()->ReturnInstruction(result, call->id()); |
| 5515 } | 5500 } |
| 5516 | 5501 |
| 5517 | 5502 |
| 5518 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { | 5503 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| 5519 ASSERT_EQ(1, call->arguments()->length()); | 5504 ASSERT_EQ(1, call->arguments()->length()); |
| 5520 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5505 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5521 HContext* context = new(zone()) HContext; | 5506 HValue* context = environment()->LookupContext(); |
| 5522 AddInstruction(context); | |
| 5523 HCallStub* result = | 5507 HCallStub* result = |
| 5524 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 5508 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 5525 result->set_transcendental_type(TranscendentalCache::SIN); | 5509 result->set_transcendental_type(TranscendentalCache::SIN); |
| 5526 Drop(1); | 5510 Drop(1); |
| 5527 ast_context()->ReturnInstruction(result, call->id()); | 5511 ast_context()->ReturnInstruction(result, call->id()); |
| 5528 } | 5512 } |
| 5529 | 5513 |
| 5530 | 5514 |
| 5531 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { | 5515 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| 5532 ASSERT_EQ(1, call->arguments()->length()); | 5516 ASSERT_EQ(1, call->arguments()->length()); |
| 5533 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5517 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5534 HContext* context = new(zone()) HContext; | 5518 HValue* context = environment()->LookupContext(); |
| 5535 AddInstruction(context); | |
| 5536 HCallStub* result = | 5519 HCallStub* result = |
| 5537 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 5520 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 5538 result->set_transcendental_type(TranscendentalCache::COS); | 5521 result->set_transcendental_type(TranscendentalCache::COS); |
| 5539 Drop(1); | 5522 Drop(1); |
| 5540 ast_context()->ReturnInstruction(result, call->id()); | 5523 ast_context()->ReturnInstruction(result, call->id()); |
| 5541 } | 5524 } |
| 5542 | 5525 |
| 5543 | 5526 |
| 5544 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { | 5527 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| 5545 ASSERT_EQ(1, call->arguments()->length()); | 5528 ASSERT_EQ(1, call->arguments()->length()); |
| 5546 CHECK_ALIVE(VisitArgumentList(call->arguments())); | 5529 CHECK_ALIVE(VisitArgumentList(call->arguments())); |
| 5547 HContext* context = new(zone()) HContext; | 5530 HValue* context = environment()->LookupContext(); |
| 5548 AddInstruction(context); | |
| 5549 HCallStub* result = | 5531 HCallStub* result = |
| 5550 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); | 5532 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 5551 result->set_transcendental_type(TranscendentalCache::LOG); | 5533 result->set_transcendental_type(TranscendentalCache::LOG); |
| 5552 Drop(1); | 5534 Drop(1); |
| 5553 ast_context()->ReturnInstruction(result, call->id()); | 5535 ast_context()->ReturnInstruction(result, call->id()); |
| 5554 } | 5536 } |
| 5555 | 5537 |
| 5556 | 5538 |
| 5557 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 5539 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 5558 return Bailout("inlined runtime function: MathSqrt"); | 5540 return Bailout("inlined runtime function: MathSqrt"); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 5583 #undef CHECK_ALIVE | 5565 #undef CHECK_ALIVE |
| 5584 | 5566 |
| 5585 | 5567 |
| 5586 HEnvironment::HEnvironment(HEnvironment* outer, | 5568 HEnvironment::HEnvironment(HEnvironment* outer, |
| 5587 Scope* scope, | 5569 Scope* scope, |
| 5588 Handle<JSFunction> closure) | 5570 Handle<JSFunction> closure) |
| 5589 : closure_(closure), | 5571 : closure_(closure), |
| 5590 values_(0), | 5572 values_(0), |
| 5591 assigned_variables_(4), | 5573 assigned_variables_(4), |
| 5592 parameter_count_(0), | 5574 parameter_count_(0), |
| 5575 specials_count_(1), |
| 5593 local_count_(0), | 5576 local_count_(0), |
| 5594 outer_(outer), | 5577 outer_(outer), |
| 5595 pop_count_(0), | 5578 pop_count_(0), |
| 5596 push_count_(0), | 5579 push_count_(0), |
| 5597 ast_id_(AstNode::kNoNumber) { | 5580 ast_id_(AstNode::kNoNumber) { |
| 5598 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); | 5581 Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); |
| 5599 } | 5582 } |
| 5600 | 5583 |
| 5601 | 5584 |
| 5602 HEnvironment::HEnvironment(const HEnvironment* other) | 5585 HEnvironment::HEnvironment(const HEnvironment* other) |
| 5603 : values_(0), | 5586 : values_(0), |
| 5604 assigned_variables_(0), | 5587 assigned_variables_(0), |
| 5605 parameter_count_(0), | 5588 parameter_count_(0), |
| 5589 specials_count_(1), |
| 5606 local_count_(0), | 5590 local_count_(0), |
| 5607 outer_(NULL), | 5591 outer_(NULL), |
| 5608 pop_count_(0), | 5592 pop_count_(0), |
| 5609 push_count_(0), | 5593 push_count_(0), |
| 5610 ast_id_(other->ast_id()) { | 5594 ast_id_(other->ast_id()) { |
| 5611 Initialize(other); | 5595 Initialize(other); |
| 5612 } | 5596 } |
| 5613 | 5597 |
| 5614 | 5598 |
| 5615 void HEnvironment::Initialize(int parameter_count, | 5599 void HEnvironment::Initialize(int parameter_count, |
| 5616 int local_count, | 5600 int local_count, |
| 5617 int stack_height) { | 5601 int stack_height) { |
| 5618 parameter_count_ = parameter_count; | 5602 parameter_count_ = parameter_count; |
| 5619 local_count_ = local_count; | 5603 local_count_ = local_count; |
| 5620 | 5604 |
| 5621 // Avoid reallocating the temporaries' backing store on the first Push. | 5605 // Avoid reallocating the temporaries' backing store on the first Push. |
| 5622 int total = parameter_count + local_count + stack_height; | 5606 int total = parameter_count + specials_count_ + local_count + stack_height; |
| 5623 values_.Initialize(total + 4); | 5607 values_.Initialize(total + 4); |
| 5624 for (int i = 0; i < total; ++i) values_.Add(NULL); | 5608 for (int i = 0; i < total; ++i) values_.Add(NULL); |
| 5625 } | 5609 } |
| 5626 | 5610 |
| 5627 | 5611 |
| 5628 void HEnvironment::Initialize(const HEnvironment* other) { | 5612 void HEnvironment::Initialize(const HEnvironment* other) { |
| 5629 closure_ = other->closure(); | 5613 closure_ = other->closure(); |
| 5630 values_.AddAll(other->values_); | 5614 values_.AddAll(other->values_); |
| 5631 assigned_variables_.AddAll(other->assigned_variables_); | 5615 assigned_variables_.AddAll(other->assigned_variables_); |
| 5632 parameter_count_ = other->parameter_count_; | 5616 parameter_count_ = other->parameter_count_; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5671 void HEnvironment::Bind(int index, HValue* value) { | 5655 void HEnvironment::Bind(int index, HValue* value) { |
| 5672 ASSERT(value != NULL); | 5656 ASSERT(value != NULL); |
| 5673 if (!assigned_variables_.Contains(index)) { | 5657 if (!assigned_variables_.Contains(index)) { |
| 5674 assigned_variables_.Add(index); | 5658 assigned_variables_.Add(index); |
| 5675 } | 5659 } |
| 5676 values_[index] = value; | 5660 values_[index] = value; |
| 5677 } | 5661 } |
| 5678 | 5662 |
| 5679 | 5663 |
| 5680 bool HEnvironment::HasExpressionAt(int index) const { | 5664 bool HEnvironment::HasExpressionAt(int index) const { |
| 5681 return index >= parameter_count_ + local_count_; | 5665 return index >= parameter_count_ + specials_count_ + local_count_; |
| 5682 } | 5666 } |
| 5683 | 5667 |
| 5684 | 5668 |
| 5685 bool HEnvironment::ExpressionStackIsEmpty() const { | 5669 bool HEnvironment::ExpressionStackIsEmpty() const { |
| 5686 int first_expression = parameter_count() + local_count(); | 5670 int first_expression = parameter_count() + specials_count() + local_count(); |
| 5687 ASSERT(length() >= first_expression); | 5671 ASSERT(length() >= first_expression); |
| 5688 return length() == first_expression; | 5672 return length() == first_expression; |
| 5689 } | 5673 } |
| 5690 | 5674 |
| 5691 | 5675 |
| 5692 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { | 5676 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { |
| 5693 int count = index_from_top + 1; | 5677 int count = index_from_top + 1; |
| 5694 int index = values_.length() - count; | 5678 int index = values_.length() - count; |
| 5695 ASSERT(HasExpressionAt(index)); | 5679 ASSERT(HasExpressionAt(index)); |
| 5696 // The push count must include at least the element in question or else | 5680 // The push count must include at least the element in question or else |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5754 HValue* push = ExpressionStackAt(arity - i); | 5738 HValue* push = ExpressionStackAt(arity - i); |
| 5755 inner->SetValueAt(i, push); | 5739 inner->SetValueAt(i, push); |
| 5756 } | 5740 } |
| 5757 } else { | 5741 } else { |
| 5758 ASSERT(compilation_phase == LITHIUM); | 5742 ASSERT(compilation_phase == LITHIUM); |
| 5759 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5743 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 5760 HValue* push = ExpressionStackAt(arity - i); | 5744 HValue* push = ExpressionStackAt(arity - i); |
| 5761 inner->SetValueAt(i, push); | 5745 inner->SetValueAt(i, push); |
| 5762 } | 5746 } |
| 5763 } | 5747 } |
| 5764 | 5748 inner->SetValueAt(arity + 1, outer->LookupContext()); |
| 5765 // Initialize the stack-allocated locals to undefined. | 5749 for (int i = arity + 2; i < inner->length(); ++i) { |
| 5766 int local_base = arity + 1; | 5750 inner->SetValueAt(i, undefined); |
| 5767 int local_count = function->scope()->num_stack_slots(); | |
| 5768 for (int i = 0; i < local_count; ++i) { | |
| 5769 inner->SetValueAt(local_base + i, undefined); | |
| 5770 } | 5751 } |
| 5771 | 5752 |
| 5772 inner->set_ast_id(AstNode::kFunctionEntryId); | 5753 inner->set_ast_id(AstNode::kFunctionEntryId); |
| 5773 return inner; | 5754 return inner; |
| 5774 } | 5755 } |
| 5775 | 5756 |
| 5776 | 5757 |
| 5777 void HEnvironment::PrintTo(StringStream* stream) { | 5758 void HEnvironment::PrintTo(StringStream* stream) { |
| 5778 for (int i = 0; i < length(); i++) { | 5759 for (int i = 0; i < length(); i++) { |
| 5779 if (i == 0) stream->Add("parameters\n"); | 5760 if (i == 0) stream->Add("parameters\n"); |
| 5780 if (i == parameter_count()) stream->Add("locals\n"); | 5761 if (i == parameter_count()) stream->Add("specials\n"); |
| 5781 if (i == parameter_count() + local_count()) stream->Add("expressions"); | 5762 if (i == parameter_count() + specials_count()) stream->Add("locals\n"); |
| 5763 if (i == parameter_count() + specials_count() + local_count()) { |
| 5764 stream->Add("expressions"); |
| 5765 } |
| 5782 HValue* val = values_.at(i); | 5766 HValue* val = values_.at(i); |
| 5783 stream->Add("%d: ", i); | 5767 stream->Add("%d: ", i); |
| 5784 if (val != NULL) { | 5768 if (val != NULL) { |
| 5785 val->PrintNameTo(stream); | 5769 val->PrintNameTo(stream); |
| 5786 } else { | 5770 } else { |
| 5787 stream->Add("NULL"); | 5771 stream->Add("NULL"); |
| 5788 } | 5772 } |
| 5789 stream->Add("\n"); | 5773 stream->Add("\n"); |
| 5790 } | 5774 } |
| 5791 } | 5775 } |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6097 } | 6081 } |
| 6098 } | 6082 } |
| 6099 | 6083 |
| 6100 #ifdef DEBUG | 6084 #ifdef DEBUG |
| 6101 if (graph_ != NULL) graph_->Verify(); | 6085 if (graph_ != NULL) graph_->Verify(); |
| 6102 if (allocator_ != NULL) allocator_->Verify(); | 6086 if (allocator_ != NULL) allocator_->Verify(); |
| 6103 #endif | 6087 #endif |
| 6104 } | 6088 } |
| 6105 | 6089 |
| 6106 } } // namespace v8::internal | 6090 } } // namespace v8::internal |
| OLD | NEW |