| 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 2307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2318 } | 2318 } |
| 2319 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); | 2319 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); |
| 2320 if (!graph()->CollectPhis()) { | 2320 if (!graph()->CollectPhis()) { |
| 2321 Bailout("Unsupported phi use of uninitialized constant"); | 2321 Bailout("Unsupported phi use of uninitialized constant"); |
| 2322 return NULL; | 2322 return NULL; |
| 2323 } | 2323 } |
| 2324 | 2324 |
| 2325 HInferRepresentation rep(graph()); | 2325 HInferRepresentation rep(graph()); |
| 2326 rep.Analyze(); | 2326 rep.Analyze(); |
| 2327 | 2327 |
| 2328 if (FLAG_use_range) { | 2328 graph()->MarkDeoptimizeOnUndefined(); |
| 2329 HRangeAnalysis rangeAnalysis(graph()); | 2329 graph()->InsertRepresentationChanges(); |
| 2330 rangeAnalysis.Analyze(); | |
| 2331 } | |
| 2332 | 2330 |
| 2333 graph()->InitializeInferredTypes(); | 2331 graph()->InitializeInferredTypes(); |
| 2334 graph()->Canonicalize(); | 2332 graph()->Canonicalize(); |
| 2335 graph()->MarkDeoptimizeOnUndefined(); | |
| 2336 graph()->InsertRepresentationChanges(); | |
| 2337 graph()->ComputeMinusZeroChecks(); | |
| 2338 | |
| 2339 // Eliminate redundant stack checks on backwards branches. | |
| 2340 HStackCheckEliminator sce(graph()); | |
| 2341 sce.Process(); | |
| 2342 | 2333 |
| 2343 // Perform common subexpression elimination and loop-invariant code motion. | 2334 // Perform common subexpression elimination and loop-invariant code motion. |
| 2344 if (FLAG_use_gvn) { | 2335 if (FLAG_use_gvn) { |
| 2345 HPhase phase("Global value numbering", graph()); | 2336 HPhase phase("Global value numbering", graph()); |
| 2346 HGlobalValueNumberer gvn(graph(), info()); | 2337 HGlobalValueNumberer gvn(graph(), info()); |
| 2347 gvn.Analyze(); | 2338 gvn.Analyze(); |
| 2348 } | 2339 } |
| 2349 | 2340 |
| 2341 if (FLAG_use_range) { |
| 2342 HRangeAnalysis rangeAnalysis(graph()); |
| 2343 rangeAnalysis.Analyze(); |
| 2344 } |
| 2345 graph()->ComputeMinusZeroChecks(); |
| 2346 |
| 2347 // Eliminate redundant stack checks on backwards branches. |
| 2348 HStackCheckEliminator sce(graph()); |
| 2349 sce.Process(); |
| 2350 |
| 2350 // Replace the results of check instructions with the original value, if the | 2351 // Replace the results of check instructions with the original value, if the |
| 2351 // result is used. This is safe now, since we don't do code motion after this | 2352 // result is used. This is safe now, since we don't do code motion after this |
| 2352 // point. It enables better register allocation since the value produced by | 2353 // point. It enables better register allocation since the value produced by |
| 2353 // check instructions is really a copy of the original value. | 2354 // check instructions is really a copy of the original value. |
| 2354 graph()->ReplaceCheckedValues(); | 2355 graph()->ReplaceCheckedValues(); |
| 2355 | 2356 |
| 2356 return graph(); | 2357 return graph(); |
| 2357 } | 2358 } |
| 2358 | 2359 |
| 2359 | 2360 |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2473 header->SetInitialEnvironment(entry_env); | 2474 header->SetInitialEnvironment(entry_env); |
| 2474 header->AttachLoopInformation(); | 2475 header->AttachLoopInformation(); |
| 2475 return header; | 2476 return header; |
| 2476 } | 2477 } |
| 2477 | 2478 |
| 2478 | 2479 |
| 2479 void HGraphBuilder::VisitBlock(Block* stmt) { | 2480 void HGraphBuilder::VisitBlock(Block* stmt) { |
| 2480 ASSERT(!HasStackOverflow()); | 2481 ASSERT(!HasStackOverflow()); |
| 2481 ASSERT(current_block() != NULL); | 2482 ASSERT(current_block() != NULL); |
| 2482 ASSERT(current_block()->HasPredecessor()); | 2483 ASSERT(current_block()->HasPredecessor()); |
| 2484 if (stmt->block_scope() != NULL) { |
| 2485 return Bailout("ScopedBlock"); |
| 2486 } |
| 2483 BreakAndContinueInfo break_info(stmt); | 2487 BreakAndContinueInfo break_info(stmt); |
| 2484 { BreakAndContinueScope push(&break_info, this); | 2488 { BreakAndContinueScope push(&break_info, this); |
| 2485 CHECK_BAILOUT(VisitStatements(stmt->statements())); | 2489 CHECK_BAILOUT(VisitStatements(stmt->statements())); |
| 2486 } | 2490 } |
| 2487 HBasicBlock* break_block = break_info.break_block(); | 2491 HBasicBlock* break_block = break_info.break_block(); |
| 2488 if (break_block != NULL) { | 2492 if (break_block != NULL) { |
| 2489 if (current_block() != NULL) current_block()->Goto(break_block); | 2493 if (current_block() != NULL) current_block()->Goto(break_block); |
| 2490 break_block->SetJoinId(stmt->ExitId()); | 2494 break_block->SetJoinId(stmt->ExitId()); |
| 2491 set_current_block(break_block); | 2495 set_current_block(break_block); |
| 2492 } | 2496 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2624 ASSERT(context->IsValue()); | 2628 ASSERT(context->IsValue()); |
| 2625 CHECK_ALIVE(VisitForValue(stmt->expression())); | 2629 CHECK_ALIVE(VisitForValue(stmt->expression())); |
| 2626 HValue* return_value = environment()->Pop(); | 2630 HValue* return_value = environment()->Pop(); |
| 2627 current_block()->AddLeaveInlined(return_value, function_return()); | 2631 current_block()->AddLeaveInlined(return_value, function_return()); |
| 2628 } | 2632 } |
| 2629 set_current_block(NULL); | 2633 set_current_block(NULL); |
| 2630 } | 2634 } |
| 2631 } | 2635 } |
| 2632 | 2636 |
| 2633 | 2637 |
| 2634 void HGraphBuilder::VisitEnterWithContextStatement( | 2638 void HGraphBuilder::VisitWithStatement(WithStatement* stmt) { |
| 2635 EnterWithContextStatement* stmt) { | |
| 2636 ASSERT(!HasStackOverflow()); | 2639 ASSERT(!HasStackOverflow()); |
| 2637 ASSERT(current_block() != NULL); | 2640 ASSERT(current_block() != NULL); |
| 2638 ASSERT(current_block()->HasPredecessor()); | 2641 ASSERT(current_block()->HasPredecessor()); |
| 2639 return Bailout("EnterWithContextStatement"); | 2642 return Bailout("WithStatement"); |
| 2640 } | 2643 } |
| 2641 | 2644 |
| 2642 | 2645 |
| 2643 void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) { | 2646 void HGraphBuilder::VisitExitContextStatement(ExitContextStatement* stmt) { |
| 2644 ASSERT(!HasStackOverflow()); | 2647 ASSERT(!HasStackOverflow()); |
| 2645 ASSERT(current_block() != NULL); | 2648 ASSERT(current_block() != NULL); |
| 2646 ASSERT(current_block()->HasPredecessor()); | 2649 ASSERT(current_block()->HasPredecessor()); |
| 2647 return Bailout("ExitContextStatement"); | 2650 return Bailout("ExitContextStatement"); |
| 2648 } | 2651 } |
| 2649 | 2652 |
| (...skipping 736 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3386 HValue* value, | 3389 HValue* value, |
| 3387 Expression* expr) { | 3390 Expression* expr) { |
| 3388 Property* prop = (expr->AsProperty() != NULL) | 3391 Property* prop = (expr->AsProperty() != NULL) |
| 3389 ? expr->AsProperty() | 3392 ? expr->AsProperty() |
| 3390 : expr->AsAssignment()->target()->AsProperty(); | 3393 : expr->AsAssignment()->target()->AsProperty(); |
| 3391 Literal* key = prop->key()->AsLiteral(); | 3394 Literal* key = prop->key()->AsLiteral(); |
| 3392 Handle<String> name = Handle<String>::cast(key->handle()); | 3395 Handle<String> name = Handle<String>::cast(key->handle()); |
| 3393 ASSERT(!name.is_null()); | 3396 ASSERT(!name.is_null()); |
| 3394 | 3397 |
| 3395 LookupResult lookup; | 3398 LookupResult lookup; |
| 3396 ZoneMapList* types = expr->GetReceiverTypes(); | 3399 SmallMapList* types = expr->GetReceiverTypes(); |
| 3397 bool is_monomorphic = expr->IsMonomorphic() && | 3400 bool is_monomorphic = expr->IsMonomorphic() && |
| 3398 ComputeStoredField(types->first(), name, &lookup); | 3401 ComputeStoredField(types->first(), name, &lookup); |
| 3399 | 3402 |
| 3400 return is_monomorphic | 3403 return is_monomorphic |
| 3401 ? BuildStoreNamedField(object, name, value, types->first(), &lookup, | 3404 ? BuildStoreNamedField(object, name, value, types->first(), &lookup, |
| 3402 true) // Needs smi and map check. | 3405 true) // Needs smi and map check. |
| 3403 : BuildStoreNamedGeneric(object, name, value); | 3406 : BuildStoreNamedGeneric(object, name, value); |
| 3404 } | 3407 } |
| 3405 | 3408 |
| 3406 | 3409 |
| 3407 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, | 3410 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, |
| 3408 HValue* object, | 3411 HValue* object, |
| 3409 HValue* value, | 3412 HValue* value, |
| 3410 ZoneMapList* types, | 3413 SmallMapList* types, |
| 3411 Handle<String> name) { | 3414 Handle<String> name) { |
| 3412 // TODO(ager): We should recognize when the prototype chains for different | 3415 // TODO(ager): We should recognize when the prototype chains for different |
| 3413 // maps are identical. In that case we can avoid repeatedly generating the | 3416 // maps are identical. In that case we can avoid repeatedly generating the |
| 3414 // same prototype map checks. | 3417 // same prototype map checks. |
| 3415 int count = 0; | 3418 int count = 0; |
| 3416 HBasicBlock* join = NULL; | 3419 HBasicBlock* join = NULL; |
| 3417 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 3420 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 3418 Handle<Map> map = types->at(i); | 3421 Handle<Map> map = types->at(i); |
| 3419 LookupResult lookup; | 3422 LookupResult lookup; |
| 3420 if (ComputeStoredField(map, name, &lookup)) { | 3423 if (ComputeStoredField(map, name, &lookup)) { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3491 if (prop->key()->IsPropertyName()) { | 3494 if (prop->key()->IsPropertyName()) { |
| 3492 // Named store. | 3495 // Named store. |
| 3493 CHECK_ALIVE(VisitForValue(expr->value())); | 3496 CHECK_ALIVE(VisitForValue(expr->value())); |
| 3494 value = Pop(); | 3497 value = Pop(); |
| 3495 HValue* object = Pop(); | 3498 HValue* object = Pop(); |
| 3496 | 3499 |
| 3497 Literal* key = prop->key()->AsLiteral(); | 3500 Literal* key = prop->key()->AsLiteral(); |
| 3498 Handle<String> name = Handle<String>::cast(key->handle()); | 3501 Handle<String> name = Handle<String>::cast(key->handle()); |
| 3499 ASSERT(!name.is_null()); | 3502 ASSERT(!name.is_null()); |
| 3500 | 3503 |
| 3501 ZoneMapList* types = expr->GetReceiverTypes(); | 3504 SmallMapList* types = expr->GetReceiverTypes(); |
| 3502 LookupResult lookup; | 3505 LookupResult lookup; |
| 3503 | 3506 |
| 3504 if (expr->IsMonomorphic()) { | 3507 if (expr->IsMonomorphic()) { |
| 3505 instr = BuildStoreNamed(object, value, expr); | 3508 instr = BuildStoreNamed(object, value, expr); |
| 3506 | 3509 |
| 3507 } else if (types != NULL && types->length() > 1) { | 3510 } else if (types != NULL && types->length() > 1) { |
| 3508 HandlePolymorphicStoreNamedField(expr, object, value, types, name); | 3511 HandlePolymorphicStoreNamedField(expr, object, value, types, name); |
| 3509 return; | 3512 return; |
| 3510 | 3513 |
| 3511 } else { | 3514 } else { |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3933 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); | 3936 HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3934 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); | 3937 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
| 3935 bool fast_double_elements = map->has_fast_double_elements(); | 3938 bool fast_double_elements = map->has_fast_double_elements(); |
| 3936 if (is_store && map->has_fast_elements()) { | 3939 if (is_store && map->has_fast_elements()) { |
| 3937 AddInstruction(new(zone()) HCheckMap( | 3940 AddInstruction(new(zone()) HCheckMap( |
| 3938 elements, isolate()->factory()->fixed_array_map())); | 3941 elements, isolate()->factory()->fixed_array_map())); |
| 3939 } | 3942 } |
| 3940 HInstruction* length = NULL; | 3943 HInstruction* length = NULL; |
| 3941 HInstruction* checked_key = NULL; | 3944 HInstruction* checked_key = NULL; |
| 3942 if (map->has_external_array_elements()) { | 3945 if (map->has_external_array_elements()) { |
| 3943 length = AddInstruction(new(zone()) HExternalArrayLength(elements)); | 3946 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 3944 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3947 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3945 HLoadExternalArrayPointer* external_elements = | 3948 HLoadExternalArrayPointer* external_elements = |
| 3946 new(zone()) HLoadExternalArrayPointer(elements); | 3949 new(zone()) HLoadExternalArrayPointer(elements); |
| 3947 AddInstruction(external_elements); | 3950 AddInstruction(external_elements); |
| 3948 return BuildExternalArrayElementAccess(external_elements, checked_key, | 3951 return BuildExternalArrayElementAccess(external_elements, checked_key, |
| 3949 val, map->elements_kind(), is_store); | 3952 val, map->elements_kind(), is_store); |
| 3950 } | 3953 } |
| 3951 ASSERT(map->has_fast_elements() || fast_double_elements); | 3954 ASSERT(map->has_fast_elements() || fast_double_elements); |
| 3952 if (map->instance_type() == JS_ARRAY_TYPE) { | 3955 if (map->instance_type() == JS_ARRAY_TYPE) { |
| 3953 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); | 3956 length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); |
| 3954 } else { | 3957 } else { |
| 3955 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 3958 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 3956 } | 3959 } |
| 3957 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 3960 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3958 if (is_store) { | 3961 if (is_store) { |
| 3959 if (fast_double_elements) { | 3962 if (fast_double_elements) { |
| 3960 return new(zone()) HStoreKeyedFastDoubleElement(elements, | 3963 return new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 3961 checked_key, | 3964 checked_key, |
| 3962 val); | 3965 val); |
| 3963 } else { | 3966 } else { |
| 3964 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); | 3967 return new(zone()) HStoreKeyedFastElement(elements, checked_key, val); |
| 3965 } | 3968 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3977 HValue* key, | 3980 HValue* key, |
| 3978 HValue* val, | 3981 HValue* val, |
| 3979 Expression* prop, | 3982 Expression* prop, |
| 3980 int ast_id, | 3983 int ast_id, |
| 3981 int position, | 3984 int position, |
| 3982 bool is_store, | 3985 bool is_store, |
| 3983 bool* has_side_effects) { | 3986 bool* has_side_effects) { |
| 3984 *has_side_effects = false; | 3987 *has_side_effects = false; |
| 3985 AddInstruction(new(zone()) HCheckNonSmi(object)); | 3988 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3986 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); | 3989 AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); |
| 3987 ZoneMapList* maps = prop->GetReceiverTypes(); | 3990 SmallMapList* maps = prop->GetReceiverTypes(); |
| 3988 bool todo_external_array = false; | 3991 bool todo_external_array = false; |
| 3989 | 3992 |
| 3990 static const int kNumElementTypes = JSObject::kElementsKindCount; | 3993 static const int kNumElementTypes = JSObject::kElementsKindCount; |
| 3991 bool type_todo[kNumElementTypes]; | 3994 bool type_todo[kNumElementTypes]; |
| 3992 for (int i = 0; i < kNumElementTypes; ++i) { | 3995 for (int i = 0; i < kNumElementTypes; ++i) { |
| 3993 type_todo[i] = false; | 3996 type_todo[i] = false; |
| 3994 } | 3997 } |
| 3995 | 3998 |
| 3996 for (int i = 0; i < maps->length(); ++i) { | 3999 for (int i = 0; i < maps->length(); ++i) { |
| 3997 ASSERT(maps->at(i)->IsMap()); | 4000 ASSERT(maps->at(i)->IsMap()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4017 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; | 4020 for (JSObject::ElementsKind elements_kind = JSObject::FAST_ELEMENTS; |
| 4018 elements_kind <= JSObject::LAST_ELEMENTS_KIND; | 4021 elements_kind <= JSObject::LAST_ELEMENTS_KIND; |
| 4019 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { | 4022 elements_kind = JSObject::ElementsKind(elements_kind + 1)) { |
| 4020 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we | 4023 // After having handled FAST_ELEMENTS and DICTIONARY_ELEMENTS, we |
| 4021 // need to add some code that's executed for all external array cases. | 4024 // need to add some code that's executed for all external array cases. |
| 4022 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == | 4025 STATIC_ASSERT(JSObject::LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == |
| 4023 JSObject::LAST_ELEMENTS_KIND); | 4026 JSObject::LAST_ELEMENTS_KIND); |
| 4024 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND | 4027 if (elements_kind == JSObject::FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND |
| 4025 && todo_external_array) { | 4028 && todo_external_array) { |
| 4026 HInstruction* length = | 4029 HInstruction* length = |
| 4027 AddInstruction(new(zone()) HExternalArrayLength(elements)); | 4030 AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 4028 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4031 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 4029 external_elements = new(zone()) HLoadExternalArrayPointer(elements); | 4032 external_elements = new(zone()) HLoadExternalArrayPointer(elements); |
| 4030 AddInstruction(external_elements); | 4033 AddInstruction(external_elements); |
| 4031 } | 4034 } |
| 4032 if (type_todo[elements_kind]) { | 4035 if (type_todo[elements_kind]) { |
| 4033 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 4036 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 4034 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 4037 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 4035 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( | 4038 elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( |
| 4036 elements_kind_instr, elements_kind, Token::EQ_STRICT); | 4039 elements_kind_instr, elements_kind, Token::EQ_STRICT); |
| 4037 elements_kind_branch->SetSuccessorAt(0, if_true); | 4040 elements_kind_branch->SetSuccessorAt(0, if_true); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4081 } | 4084 } |
| 4082 Push(access); | 4085 Push(access); |
| 4083 } | 4086 } |
| 4084 *has_side_effects |= access->HasSideEffects(); | 4087 *has_side_effects |= access->HasSideEffects(); |
| 4085 if (position != -1) { | 4088 if (position != -1) { |
| 4086 access->set_position(position); | 4089 access->set_position(position); |
| 4087 } | 4090 } |
| 4088 if_jsarray->Goto(join); | 4091 if_jsarray->Goto(join); |
| 4089 | 4092 |
| 4090 set_current_block(if_fastobject); | 4093 set_current_block(if_fastobject); |
| 4091 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); | 4094 length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); |
| 4092 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); | 4095 checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 4093 if (is_store) { | 4096 if (is_store) { |
| 4094 if (fast_double_elements) { | 4097 if (fast_double_elements) { |
| 4095 access = AddInstruction( | 4098 access = AddInstruction( |
| 4096 new(zone()) HStoreKeyedFastDoubleElement(elements, | 4099 new(zone()) HStoreKeyedFastDoubleElement(elements, |
| 4097 checked_key, | 4100 checked_key, |
| 4098 val)); | 4101 val)); |
| 4099 } else { | 4102 } else { |
| 4100 access = AddInstruction( | 4103 access = AddInstruction( |
| 4101 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); | 4104 new(zone()) HStoreKeyedFastElement(elements, checked_key, val)); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4251 AddInstruction(char_code); | 4254 AddInstruction(char_code); |
| 4252 instr = new(zone()) HStringCharFromCode(context, char_code); | 4255 instr = new(zone()) HStringCharFromCode(context, char_code); |
| 4253 | 4256 |
| 4254 } else if (expr->IsFunctionPrototype()) { | 4257 } else if (expr->IsFunctionPrototype()) { |
| 4255 HValue* function = Pop(); | 4258 HValue* function = Pop(); |
| 4256 AddInstruction(new(zone()) HCheckNonSmi(function)); | 4259 AddInstruction(new(zone()) HCheckNonSmi(function)); |
| 4257 instr = new(zone()) HLoadFunctionPrototype(function); | 4260 instr = new(zone()) HLoadFunctionPrototype(function); |
| 4258 | 4261 |
| 4259 } else if (expr->key()->IsPropertyName()) { | 4262 } else if (expr->key()->IsPropertyName()) { |
| 4260 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 4263 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 4261 ZoneMapList* types = expr->GetReceiverTypes(); | 4264 SmallMapList* types = expr->GetReceiverTypes(); |
| 4262 | 4265 |
| 4263 HValue* obj = Pop(); | 4266 HValue* obj = Pop(); |
| 4264 if (expr->IsMonomorphic()) { | 4267 if (expr->IsMonomorphic()) { |
| 4265 instr = BuildLoadNamed(obj, expr, types->first(), name); | 4268 instr = BuildLoadNamed(obj, expr, types->first(), name); |
| 4266 } else if (types != NULL && types->length() > 1) { | 4269 } else if (types != NULL && types->length() > 1) { |
| 4267 AddInstruction(new(zone()) HCheckNonSmi(obj)); | 4270 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 4268 HValue* context = environment()->LookupContext(); | 4271 HValue* context = environment()->LookupContext(); |
| 4269 instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name); | 4272 instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name); |
| 4270 } else { | 4273 } else { |
| 4271 instr = BuildLoadNamedGeneric(obj, expr); | 4274 instr = BuildLoadNamedGeneric(obj, expr); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4312 if (!expr->holder().is_null()) { | 4315 if (!expr->holder().is_null()) { |
| 4313 AddInstruction(new(zone()) HCheckPrototypeMaps( | 4316 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 4314 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), | 4317 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), |
| 4315 expr->holder())); | 4318 expr->holder())); |
| 4316 } | 4319 } |
| 4317 } | 4320 } |
| 4318 | 4321 |
| 4319 | 4322 |
| 4320 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, | 4323 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
| 4321 HValue* receiver, | 4324 HValue* receiver, |
| 4322 ZoneMapList* types, | 4325 SmallMapList* types, |
| 4323 Handle<String> name) { | 4326 Handle<String> name) { |
| 4324 // TODO(ager): We should recognize when the prototype chains for different | 4327 // TODO(ager): We should recognize when the prototype chains for different |
| 4325 // maps are identical. In that case we can avoid repeatedly generating the | 4328 // maps are identical. In that case we can avoid repeatedly generating the |
| 4326 // same prototype map checks. | 4329 // same prototype map checks. |
| 4327 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 4330 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 4328 int count = 0; | 4331 int count = 0; |
| 4329 HBasicBlock* join = NULL; | 4332 HBasicBlock* join = NULL; |
| 4330 for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) { | 4333 for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) { |
| 4331 Handle<Map> map = types->at(i); | 4334 Handle<Map> map = types->at(i); |
| 4332 if (expr->ComputeTarget(map, name)) { | 4335 if (expr->ComputeTarget(map, name)) { |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4755 } | 4758 } |
| 4756 return false; | 4759 return false; |
| 4757 } | 4760 } |
| 4758 | 4761 |
| 4759 | 4762 |
| 4760 bool HGraphBuilder::TryCallApply(Call* expr) { | 4763 bool HGraphBuilder::TryCallApply(Call* expr) { |
| 4761 Expression* callee = expr->expression(); | 4764 Expression* callee = expr->expression(); |
| 4762 Property* prop = callee->AsProperty(); | 4765 Property* prop = callee->AsProperty(); |
| 4763 ASSERT(prop != NULL); | 4766 ASSERT(prop != NULL); |
| 4764 | 4767 |
| 4768 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 4769 return false; |
| 4770 } |
| 4771 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 4772 if (function_map->instance_type() != JS_FUNCTION_TYPE || |
| 4773 !expr->target()->shared()->HasBuiltinFunctionId() || |
| 4774 expr->target()->shared()->builtin_function_id() != kFunctionApply) { |
| 4775 return false; |
| 4776 } |
| 4777 |
| 4765 if (info()->scope()->arguments() == NULL) return false; | 4778 if (info()->scope()->arguments() == NULL) return false; |
| 4766 | 4779 |
| 4767 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | |
| 4768 if (!name->IsEqualTo(CStrVector("apply"))) return false; | |
| 4769 | |
| 4770 ZoneList<Expression*>* args = expr->arguments(); | 4780 ZoneList<Expression*>* args = expr->arguments(); |
| 4771 if (args->length() != 2) return false; | 4781 if (args->length() != 2) return false; |
| 4772 | 4782 |
| 4773 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); | 4783 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); |
| 4774 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; | 4784 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; |
| 4775 HValue* arg_two_value = environment()->Lookup(arg_two->var()); | 4785 HValue* arg_two_value = environment()->Lookup(arg_two->var()); |
| 4776 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; | 4786 if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; |
| 4777 | 4787 |
| 4778 if (!expr->IsMonomorphic() || | |
| 4779 expr->check_type() != RECEIVER_MAP_CHECK) return false; | |
| 4780 | |
| 4781 // Our implementation of arguments (based on this stack frame or an | 4788 // Our implementation of arguments (based on this stack frame or an |
| 4782 // adapter below it) does not work for inlined functions. | 4789 // adapter below it) does not work for inlined functions. |
| 4783 if (function_state()->outer() != NULL) { | 4790 if (function_state()->outer() != NULL) { |
| 4784 Bailout("Function.prototype.apply optimization in inlined function"); | 4791 Bailout("Function.prototype.apply optimization in inlined function"); |
| 4785 return true; | 4792 return true; |
| 4786 } | 4793 } |
| 4787 | 4794 |
| 4788 // Found pattern f.apply(receiver, arguments). | 4795 // Found pattern f.apply(receiver, arguments). |
| 4789 VisitForValue(prop->obj()); | 4796 VisitForValue(prop->obj()); |
| 4790 if (HasStackOverflow() || current_block() == NULL) return true; | 4797 if (HasStackOverflow() || current_block() == NULL) return true; |
| 4791 HValue* function = Pop(); | 4798 HValue* function = Pop(); |
| 4792 VisitForValue(args->at(0)); | 4799 VisitForValue(args->at(0)); |
| 4793 if (HasStackOverflow() || current_block() == NULL) return true; | 4800 if (HasStackOverflow() || current_block() == NULL) return true; |
| 4794 HValue* receiver = Pop(); | 4801 HValue* receiver = Pop(); |
| 4795 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); | 4802 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 4796 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); | 4803 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| 4797 AddCheckConstantFunction(expr, | 4804 AddCheckConstantFunction(expr, function, function_map, true); |
| 4798 function, | |
| 4799 expr->GetReceiverTypes()->first(), | |
| 4800 true); | |
| 4801 HInstruction* result = | 4805 HInstruction* result = |
| 4802 new(zone()) HApplyArguments(function, receiver, length, elements); | 4806 new(zone()) HApplyArguments(function, receiver, length, elements); |
| 4803 result->set_position(expr->position()); | 4807 result->set_position(expr->position()); |
| 4804 ast_context()->ReturnInstruction(result, expr->id()); | 4808 ast_context()->ReturnInstruction(result, expr->id()); |
| 4805 return true; | 4809 return true; |
| 4806 } | 4810 } |
| 4807 | 4811 |
| 4808 | 4812 |
| 4809 void HGraphBuilder::VisitCall(Call* expr) { | 4813 void HGraphBuilder::VisitCall(Call* expr) { |
| 4810 ASSERT(!HasStackOverflow()); | 4814 ASSERT(!HasStackOverflow()); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4839 // Named function call. | 4843 // Named function call. |
| 4840 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); | 4844 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); |
| 4841 | 4845 |
| 4842 if (TryCallApply(expr)) return; | 4846 if (TryCallApply(expr)) return; |
| 4843 | 4847 |
| 4844 CHECK_ALIVE(VisitForValue(prop->obj())); | 4848 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 4845 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 4849 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 4846 | 4850 |
| 4847 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 4851 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| 4848 | 4852 |
| 4849 ZoneMapList* types = expr->GetReceiverTypes(); | 4853 SmallMapList* types = expr->GetReceiverTypes(); |
| 4850 | 4854 |
| 4851 HValue* receiver = | 4855 HValue* receiver = |
| 4852 environment()->ExpressionStackAt(expr->arguments()->length()); | 4856 environment()->ExpressionStackAt(expr->arguments()->length()); |
| 4853 if (expr->IsMonomorphic()) { | 4857 if (expr->IsMonomorphic()) { |
| 4854 Handle<Map> receiver_map = | 4858 Handle<Map> receiver_map = (types == NULL || types->is_empty()) |
| 4855 (types == NULL) ? Handle<Map>::null() : types->first(); | 4859 ? Handle<Map>::null() |
| 4860 : types->first(); |
| 4856 if (TryInlineBuiltinFunction(expr, | 4861 if (TryInlineBuiltinFunction(expr, |
| 4857 receiver, | 4862 receiver, |
| 4858 receiver_map, | 4863 receiver_map, |
| 4859 expr->check_type())) { | 4864 expr->check_type())) { |
| 4860 return; | 4865 return; |
| 4861 } | 4866 } |
| 4862 | 4867 |
| 4863 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || | 4868 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || |
| 4864 expr->check_type() != RECEIVER_MAP_CHECK) { | 4869 expr->check_type() != RECEIVER_MAP_CHECK) { |
| 4865 // When the target has a custom call IC generator, use the IC, | 4870 // When the target has a custom call IC generator, use the IC, |
| (...skipping 1880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6746 } | 6751 } |
| 6747 } | 6752 } |
| 6748 | 6753 |
| 6749 #ifdef DEBUG | 6754 #ifdef DEBUG |
| 6750 if (graph_ != NULL) graph_->Verify(); | 6755 if (graph_ != NULL) graph_->Verify(); |
| 6751 if (allocator_ != NULL) allocator_->Verify(); | 6756 if (allocator_ != NULL) allocator_->Verify(); |
| 6752 #endif | 6757 #endif |
| 6753 } | 6758 } |
| 6754 | 6759 |
| 6755 } } // namespace v8::internal | 6760 } } // namespace v8::internal |
| OLD | NEW |