| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 1541 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1552 | 1552 |
| 1553 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); | 1553 HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1()); |
| 1554 mask->ChangeRepresentation(Representation::Integer32()); | 1554 mask->ChangeRepresentation(Representation::Integer32()); |
| 1555 mask->ClearFlag(HValue::kCanOverflow); | 1555 mask->ClearFlag(HValue::kCanOverflow); |
| 1556 | 1556 |
| 1557 return BuildUncheckedDictionaryElementLoadHelper(elements, key, | 1557 return BuildUncheckedDictionaryElementLoadHelper(elements, key, |
| 1558 hash, mask, 0); | 1558 hash, mask, 0); |
| 1559 } | 1559 } |
| 1560 | 1560 |
| 1561 | 1561 |
| 1562 HValue* HGraphBuilder::BuildNumberToString(HValue* object, | 1562 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) { |
| 1563 Handle<Type> type) { | |
| 1564 NoObservableSideEffectsScope scope(this); | 1563 NoObservableSideEffectsScope scope(this); |
| 1565 | 1564 |
| 1566 // Convert constant numbers at compile time. | 1565 // Convert constant numbers at compile time. |
| 1567 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) { | 1566 if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) { |
| 1568 Handle<Object> number = HConstant::cast(object)->handle(isolate()); | 1567 Handle<Object> number = HConstant::cast(object)->handle(isolate()); |
| 1569 Handle<String> result = isolate()->factory()->NumberToString(number); | 1568 Handle<String> result = isolate()->factory()->NumberToString(number); |
| 1570 return Add<HConstant>(result); | 1569 return Add<HConstant>(result); |
| 1571 } | 1570 } |
| 1572 | 1571 |
| 1573 // Create a joinable continuation. | 1572 // Create a joinable continuation. |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2073 | 2072 |
| 2074 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 2073 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
| 2075 HValue* checked_object, | 2074 HValue* checked_object, |
| 2076 HValue* key, | 2075 HValue* key, |
| 2077 HValue* val, | 2076 HValue* val, |
| 2078 bool is_js_array, | 2077 bool is_js_array, |
| 2079 ElementsKind elements_kind, | 2078 ElementsKind elements_kind, |
| 2080 bool is_store, | 2079 bool is_store, |
| 2081 LoadKeyedHoleMode load_mode, | 2080 LoadKeyedHoleMode load_mode, |
| 2082 KeyedAccessStoreMode store_mode) { | 2081 KeyedAccessStoreMode store_mode) { |
| 2083 ASSERT(!IsExternalArrayElementsKind(elements_kind) || !is_js_array); | 2082 ASSERT((!IsExternalArrayElementsKind(elements_kind) && |
| 2083 !IsFixedTypedArrayElementsKind(elements_kind)) || |
| 2084 !is_js_array); |
| 2084 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 2085 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
| 2085 // on a HElementsTransition instruction. The flag can also be removed if the | 2086 // on a HElementsTransition instruction. The flag can also be removed if the |
| 2086 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 2087 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
| 2087 // ElementsKind transitions. Finally, the dependency can be removed for stores | 2088 // ElementsKind transitions. Finally, the dependency can be removed for stores |
| 2088 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 2089 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
| 2089 // generated store code. | 2090 // generated store code. |
| 2090 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 2091 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
| 2091 (elements_kind == FAST_ELEMENTS && is_store)) { | 2092 (elements_kind == FAST_ELEMENTS && is_store)) { |
| 2092 checked_object->ClearGVNFlag(kDependsOnElementsKind); | 2093 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
| 2093 } | 2094 } |
| 2094 | 2095 |
| 2095 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 2096 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
| 2096 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 2097 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
| 2097 HValue* elements = AddLoadElements(checked_object); | 2098 HValue* elements = AddLoadElements(checked_object); |
| 2098 if (is_store && (fast_elements || fast_smi_only_elements) && | 2099 if (is_store && (fast_elements || fast_smi_only_elements) && |
| 2099 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 2100 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
| 2100 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2101 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
| 2101 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2102 elements, isolate()->factory()->fixed_array_map(), top_info()); |
| 2102 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 2103 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
| 2103 } | 2104 } |
| 2104 HInstruction* length = NULL; | 2105 HInstruction* length = NULL; |
| 2105 if (is_js_array) { | 2106 if (is_js_array) { |
| 2106 length = Add<HLoadNamedField>( | 2107 length = Add<HLoadNamedField>( |
| 2107 checked_object, HObjectAccess::ForArrayLength(elements_kind)); | 2108 checked_object, HObjectAccess::ForArrayLength(elements_kind)); |
| 2108 } else { | 2109 } else { |
| 2109 length = AddLoadFixedArrayLength(elements); | 2110 length = AddLoadFixedArrayLength(elements); |
| 2110 } | 2111 } |
| 2111 length->set_type(HType::Smi()); | 2112 length->set_type(HType::Smi()); |
| 2112 HValue* checked_key = NULL; | 2113 HValue* checked_key = NULL; |
| 2113 if (IsExternalArrayElementsKind(elements_kind)) { | 2114 if (IsExternalArrayElementsKind(elements_kind) || |
| 2115 IsFixedTypedArrayElementsKind(elements_kind)) { |
| 2116 HValue* backing_store; |
| 2117 if (IsExternalArrayElementsKind(elements_kind)) { |
| 2118 backing_store = |
| 2119 Add<HLoadExternalArrayPointer>(elements); |
| 2120 } else { |
| 2121 backing_store = elements; |
| 2122 } |
| 2114 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 2123 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 2115 NoObservableSideEffectsScope no_effects(this); | 2124 NoObservableSideEffectsScope no_effects(this); |
| 2116 HLoadExternalArrayPointer* external_elements = | |
| 2117 Add<HLoadExternalArrayPointer>(elements); | |
| 2118 IfBuilder length_checker(this); | 2125 IfBuilder length_checker(this); |
| 2119 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2126 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 2120 length_checker.Then(); | 2127 length_checker.Then(); |
| 2121 IfBuilder negative_checker(this); | 2128 IfBuilder negative_checker(this); |
| 2122 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2129 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 2123 key, graph()->GetConstant0(), Token::GTE); | 2130 key, graph()->GetConstant0(), Token::GTE); |
| 2124 negative_checker.Then(); | 2131 negative_checker.Then(); |
| 2125 HInstruction* result = AddElementAccess( | 2132 HInstruction* result = AddElementAccess( |
| 2126 external_elements, key, val, bounds_check, elements_kind, is_store); | 2133 backing_store, key, val, bounds_check, elements_kind, is_store); |
| 2127 negative_checker.ElseDeopt("Negative key encountered"); | 2134 negative_checker.ElseDeopt("Negative key encountered"); |
| 2128 negative_checker.End(); | 2135 negative_checker.End(); |
| 2129 length_checker.End(); | 2136 length_checker.End(); |
| 2130 return result; | 2137 return result; |
| 2131 } else { | 2138 } else { |
| 2132 ASSERT(store_mode == STANDARD_STORE); | 2139 ASSERT(store_mode == STANDARD_STORE); |
| 2133 checked_key = Add<HBoundsCheck>(key, length); | 2140 checked_key = Add<HBoundsCheck>(key, length); |
| 2134 HLoadExternalArrayPointer* external_elements = | |
| 2135 Add<HLoadExternalArrayPointer>(elements); | |
| 2136 return AddElementAccess( | 2141 return AddElementAccess( |
| 2137 external_elements, checked_key, val, | 2142 backing_store, checked_key, val, |
| 2138 checked_object, elements_kind, is_store); | 2143 checked_object, elements_kind, is_store); |
| 2139 } | 2144 } |
| 2140 } | 2145 } |
| 2141 ASSERT(fast_smi_only_elements || | 2146 ASSERT(fast_smi_only_elements || |
| 2142 fast_elements || | 2147 fast_elements || |
| 2143 IsFastDoubleElementsKind(elements_kind)); | 2148 IsFastDoubleElementsKind(elements_kind)); |
| 2144 | 2149 |
| 2145 // In case val is stored into a fast smi array, assure that the value is a smi | 2150 // In case val is stored into a fast smi array, assure that the value is a smi |
| 2146 // before manipulating the backing store. Otherwise the actual store may | 2151 // before manipulating the backing store. Otherwise the actual store may |
| 2147 // deopt, leaving the backing store in an invalid state. | 2152 // deopt, leaving the backing store in an invalid state. |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 HInstruction* HGraphBuilder::AddElementAccess( | 2313 HInstruction* HGraphBuilder::AddElementAccess( |
| 2309 HValue* elements, | 2314 HValue* elements, |
| 2310 HValue* checked_key, | 2315 HValue* checked_key, |
| 2311 HValue* val, | 2316 HValue* val, |
| 2312 HValue* dependency, | 2317 HValue* dependency, |
| 2313 ElementsKind elements_kind, | 2318 ElementsKind elements_kind, |
| 2314 bool is_store, | 2319 bool is_store, |
| 2315 LoadKeyedHoleMode load_mode) { | 2320 LoadKeyedHoleMode load_mode) { |
| 2316 if (is_store) { | 2321 if (is_store) { |
| 2317 ASSERT(val != NULL); | 2322 ASSERT(val != NULL); |
| 2318 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { | 2323 if (elements_kind == EXTERNAL_PIXEL_ELEMENTS || |
| 2324 elements_kind == UINT8_CLAMPED_ELEMENTS) { |
| 2319 val = Add<HClampToUint8>(val); | 2325 val = Add<HClampToUint8>(val); |
| 2320 } | 2326 } |
| 2321 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, | 2327 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, |
| 2322 elements_kind == FAST_SMI_ELEMENTS | 2328 elements_kind == FAST_SMI_ELEMENTS |
| 2323 ? STORE_TO_INITIALIZED_ENTRY | 2329 ? STORE_TO_INITIALIZED_ENTRY |
| 2324 : INITIALIZING_STORE); | 2330 : INITIALIZING_STORE); |
| 2325 } | 2331 } |
| 2326 | 2332 |
| 2327 ASSERT(!is_store); | 2333 ASSERT(!is_store); |
| 2328 ASSERT(val == NULL); | 2334 ASSERT(val == NULL); |
| 2329 HLoadKeyed* load = Add<HLoadKeyed>( | 2335 HLoadKeyed* load = Add<HLoadKeyed>( |
| 2330 elements, checked_key, dependency, elements_kind, load_mode); | 2336 elements, checked_key, dependency, elements_kind, load_mode); |
| 2331 if (FLAG_opt_safe_uint32_operations && | 2337 if (FLAG_opt_safe_uint32_operations && |
| 2332 elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { | 2338 (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS || |
| 2339 elements_kind == UINT32_ELEMENTS)) { |
| 2333 graph()->RecordUint32Instruction(load); | 2340 graph()->RecordUint32Instruction(load); |
| 2334 } | 2341 } |
| 2335 return load; | 2342 return load; |
| 2336 } | 2343 } |
| 2337 | 2344 |
| 2338 | 2345 |
| 2339 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { | 2346 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object) { |
| 2340 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer()); | 2347 return Add<HLoadNamedField>(object, HObjectAccess::ForElementsPointer()); |
| 2341 } | 2348 } |
| 2342 | 2349 |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2571 Add<HStoreKeyed>(object_elements, key_constant, value, kind); | 2578 Add<HStoreKeyed>(object_elements, key_constant, value, kind); |
| 2572 } | 2579 } |
| 2573 } | 2580 } |
| 2574 | 2581 |
| 2575 return object; | 2582 return object; |
| 2576 } | 2583 } |
| 2577 | 2584 |
| 2578 | 2585 |
| 2579 void HGraphBuilder::BuildCompareNil( | 2586 void HGraphBuilder::BuildCompareNil( |
| 2580 HValue* value, | 2587 HValue* value, |
| 2581 Handle<Type> type, | 2588 Type* type, |
| 2582 HIfContinuation* continuation) { | 2589 HIfContinuation* continuation) { |
| 2583 IfBuilder if_nil(this); | 2590 IfBuilder if_nil(this); |
| 2584 bool some_case_handled = false; | 2591 bool some_case_handled = false; |
| 2585 bool some_case_missing = false; | 2592 bool some_case_missing = false; |
| 2586 | 2593 |
| 2587 if (type->Maybe(Type::Null())) { | 2594 if (type->Maybe(Type::Null())) { |
| 2588 if (some_case_handled) if_nil.Or(); | 2595 if (some_case_handled) if_nil.Or(); |
| 2589 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); | 2596 if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
| 2590 some_case_handled = true; | 2597 some_case_handled = true; |
| 2591 } else { | 2598 } else { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2691 | 2698 |
| 2692 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 2699 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 2693 ElementsKind kind, | 2700 ElementsKind kind, |
| 2694 HValue* allocation_site_payload, | 2701 HValue* allocation_site_payload, |
| 2695 HValue* constructor_function, | 2702 HValue* constructor_function, |
| 2696 AllocationSiteOverrideMode override_mode) : | 2703 AllocationSiteOverrideMode override_mode) : |
| 2697 builder_(builder), | 2704 builder_(builder), |
| 2698 kind_(kind), | 2705 kind_(kind), |
| 2699 allocation_site_payload_(allocation_site_payload), | 2706 allocation_site_payload_(allocation_site_payload), |
| 2700 constructor_function_(constructor_function) { | 2707 constructor_function_(constructor_function) { |
| 2708 ASSERT(!allocation_site_payload->IsConstant() || |
| 2709 HConstant::cast(allocation_site_payload)->handle( |
| 2710 builder_->isolate())->IsAllocationSite()); |
| 2701 mode_ = override_mode == DISABLE_ALLOCATION_SITES | 2711 mode_ = override_mode == DISABLE_ALLOCATION_SITES |
| 2702 ? DONT_TRACK_ALLOCATION_SITE | 2712 ? DONT_TRACK_ALLOCATION_SITE |
| 2703 : AllocationSite::GetMode(kind); | 2713 : AllocationSite::GetMode(kind); |
| 2704 } | 2714 } |
| 2705 | 2715 |
| 2706 | 2716 |
| 2707 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 2717 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 2708 ElementsKind kind, | 2718 ElementsKind kind, |
| 2709 HValue* constructor_function) : | 2719 HValue* constructor_function) : |
| 2710 builder_(builder), | 2720 builder_(builder), |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2886 ast_context_(NULL), | 2896 ast_context_(NULL), |
| 2887 break_scope_(NULL), | 2897 break_scope_(NULL), |
| 2888 inlined_count_(0), | 2898 inlined_count_(0), |
| 2889 globals_(10, info->zone()), | 2899 globals_(10, info->zone()), |
| 2890 inline_bailout_(false), | 2900 inline_bailout_(false), |
| 2891 osr_(new(info->zone()) HOsrBuilder(this)) { | 2901 osr_(new(info->zone()) HOsrBuilder(this)) { |
| 2892 // This is not initialized in the initializer list because the | 2902 // This is not initialized in the initializer list because the |
| 2893 // constructor for the initial state relies on function_state_ == NULL | 2903 // constructor for the initial state relies on function_state_ == NULL |
| 2894 // to know it's the initial state. | 2904 // to know it's the initial state. |
| 2895 function_state_= &initial_function_state_; | 2905 function_state_= &initial_function_state_; |
| 2896 InitializeAstVisitor(info->isolate()); | 2906 InitializeAstVisitor(info->zone()); |
| 2897 if (FLAG_emit_opt_code_positions) { | 2907 if (FLAG_emit_opt_code_positions) { |
| 2898 SetSourcePosition(info->shared_info()->start_position()); | 2908 SetSourcePosition(info->shared_info()->start_position()); |
| 2899 } | 2909 } |
| 2900 } | 2910 } |
| 2901 | 2911 |
| 2902 | 2912 |
| 2903 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, | 2913 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first, |
| 2904 HBasicBlock* second, | 2914 HBasicBlock* second, |
| 2905 BailoutId join_id) { | 2915 BailoutId join_id) { |
| 2906 if (first == NULL) { | 2916 if (first == NULL) { |
| (...skipping 1310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4217 ZoneList<CaseClause*>* clauses = stmt->cases(); | 4227 ZoneList<CaseClause*>* clauses = stmt->cases(); |
| 4218 int clause_count = clauses->length(); | 4228 int clause_count = clauses->length(); |
| 4219 ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); | 4229 ZoneList<HBasicBlock*> body_blocks(clause_count, zone()); |
| 4220 if (clause_count > kCaseClauseLimit) { | 4230 if (clause_count > kCaseClauseLimit) { |
| 4221 return Bailout(kSwitchStatementTooManyClauses); | 4231 return Bailout(kSwitchStatementTooManyClauses); |
| 4222 } | 4232 } |
| 4223 | 4233 |
| 4224 CHECK_ALIVE(VisitForValue(stmt->tag())); | 4234 CHECK_ALIVE(VisitForValue(stmt->tag())); |
| 4225 Add<HSimulate>(stmt->EntryId()); | 4235 Add<HSimulate>(stmt->EntryId()); |
| 4226 HValue* tag_value = Top(); | 4236 HValue* tag_value = Top(); |
| 4227 Handle<Type> tag_type = stmt->tag()->bounds().lower; | 4237 Type* tag_type = stmt->tag()->bounds().lower; |
| 4228 | 4238 |
| 4229 // 1. Build all the tests, with dangling true branches | 4239 // 1. Build all the tests, with dangling true branches |
| 4230 BailoutId default_id = BailoutId::None(); | 4240 BailoutId default_id = BailoutId::None(); |
| 4231 for (int i = 0; i < clause_count; ++i) { | 4241 for (int i = 0; i < clause_count; ++i) { |
| 4232 CaseClause* clause = clauses->at(i); | 4242 CaseClause* clause = clauses->at(i); |
| 4233 if (clause->is_default()) { | 4243 if (clause->is_default()) { |
| 4234 body_blocks.Add(NULL, zone()); | 4244 body_blocks.Add(NULL, zone()); |
| 4235 if (default_id.IsNone()) default_id = clause->EntryId(); | 4245 if (default_id.IsNone()) default_id = clause->EntryId(); |
| 4236 continue; | 4246 continue; |
| 4237 } | 4247 } |
| 4238 | 4248 |
| 4239 // Generate a compare and branch. | 4249 // Generate a compare and branch. |
| 4240 CHECK_ALIVE(VisitForValue(clause->label())); | 4250 CHECK_ALIVE(VisitForValue(clause->label())); |
| 4241 HValue* label_value = Pop(); | 4251 HValue* label_value = Pop(); |
| 4242 | 4252 |
| 4243 Handle<Type> label_type = clause->label()->bounds().lower; | 4253 Type* label_type = clause->label()->bounds().lower; |
| 4244 Handle<Type> combined_type = clause->compare_type(); | 4254 Type* combined_type = clause->compare_type(); |
| 4245 HControlInstruction* compare = BuildCompareInstruction( | 4255 HControlInstruction* compare = BuildCompareInstruction( |
| 4246 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type, | 4256 Token::EQ_STRICT, tag_value, label_value, tag_type, label_type, |
| 4247 combined_type, stmt->tag()->position(), clause->label()->position(), | 4257 combined_type, stmt->tag()->position(), clause->label()->position(), |
| 4248 clause->id()); | 4258 clause->id()); |
| 4249 | 4259 |
| 4250 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 4260 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 4251 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 4261 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 4252 body_blocks.Add(body_block, zone()); | 4262 body_blocks.Add(body_block, zone()); |
| 4253 compare->SetSuccessorAt(0, body_block); | 4263 compare->SetSuccessorAt(0, body_block); |
| 4254 compare->SetSuccessorAt(1, next_test_block); | 4264 compare->SetSuccessorAt(1, next_test_block); |
| (...skipping 1600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5855 Deoptimizer::EAGER); | 5865 Deoptimizer::EAGER); |
| 5856 builder.End(); | 5866 builder.End(); |
| 5857 } | 5867 } |
| 5858 HInstruction* instr = | 5868 HInstruction* instr = |
| 5859 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | 5869 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 5860 if (instr->HasObservableSideEffects()) { | 5870 if (instr->HasObservableSideEffects()) { |
| 5861 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5871 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5862 } | 5872 } |
| 5863 } else { | 5873 } else { |
| 5864 HGlobalObject* global_object = Add<HGlobalObject>(); | 5874 HGlobalObject* global_object = Add<HGlobalObject>(); |
| 5865 HStoreGlobalGeneric* instr = | 5875 HStoreNamedGeneric* instr = |
| 5866 Add<HStoreGlobalGeneric>(global_object, var->name(), | 5876 Add<HStoreNamedGeneric>(global_object, var->name(), |
| 5867 value, function_strict_mode_flag()); | 5877 value, function_strict_mode_flag()); |
| 5868 USE(instr); | 5878 USE(instr); |
| 5869 ASSERT(instr->HasObservableSideEffects()); | 5879 ASSERT(instr->HasObservableSideEffects()); |
| 5870 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5880 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5871 } | 5881 } |
| 5872 } | 5882 } |
| 5873 | 5883 |
| 5874 | 5884 |
| 5875 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5885 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 5876 Expression* target = expr->target(); | 5886 Expression* target = expr->target(); |
| (...skipping 1738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7615 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 7625 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 7616 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); | 7626 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7617 HValue* right = Pop(); | 7627 HValue* right = Pop(); |
| 7618 HValue* left = Pop(); | 7628 HValue* left = Pop(); |
| 7619 Drop(1); // Receiver. | 7629 Drop(1); // Receiver. |
| 7620 HInstruction* result = HMul::NewImul(zone(), context(), left, right); | 7630 HInstruction* result = HMul::NewImul(zone(), context(), left, right); |
| 7621 ast_context()->ReturnInstruction(result, expr->id()); | 7631 ast_context()->ReturnInstruction(result, expr->id()); |
| 7622 return true; | 7632 return true; |
| 7623 } | 7633 } |
| 7624 break; | 7634 break; |
| 7635 case kArrayPop: { |
| 7636 if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { |
| 7637 return false; |
| 7638 } |
| 7639 if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false; |
| 7640 ElementsKind elements_kind = receiver_map->elements_kind(); |
| 7641 if (!IsFastElementsKind(elements_kind)) return false; |
| 7642 AddCheckConstantFunction(expr->holder(), receiver, receiver_map); |
| 7643 |
| 7644 Drop(expr->arguments()->length()); |
| 7645 HValue* result; |
| 7646 HValue* checked_object; |
| 7647 HValue* reduced_length; |
| 7648 HValue* receiver = Pop(); |
| 7649 { NoObservableSideEffectsScope scope(this); |
| 7650 checked_object = AddCheckMap(receiver, receiver_map); |
| 7651 HValue* elements = AddLoadElements(checked_object); |
| 7652 // Ensure that we aren't popping from a copy-on-write array. |
| 7653 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 7654 Add<HCheckMaps>( |
| 7655 elements, isolate()->factory()->fixed_array_map(), top_info()); |
| 7656 } |
| 7657 HValue* length = Add<HLoadNamedField>( |
| 7658 checked_object, HObjectAccess::ForArrayLength(elements_kind)); |
| 7659 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1()); |
| 7660 HValue* bounds_check = Add<HBoundsCheck>( |
| 7661 graph()->GetConstant0(), length); |
| 7662 result = AddElementAccess(elements, reduced_length, NULL, |
| 7663 bounds_check, elements_kind, false); |
| 7664 Factory* factory = isolate()->factory(); |
| 7665 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
| 7666 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
| 7667 ? Add<HConstant>(factory->the_hole_value()) |
| 7668 : Add<HConstant>(nan_double); |
| 7669 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
| 7670 elements_kind = FAST_HOLEY_ELEMENTS; |
| 7671 } |
| 7672 AddElementAccess( |
| 7673 elements, reduced_length, hole, bounds_check, elements_kind, true); |
| 7674 } |
| 7675 Add<HStoreNamedField>( |
| 7676 checked_object, HObjectAccess::ForArrayLength(elements_kind), |
| 7677 reduced_length); |
| 7678 ast_context()->ReturnValue(result); |
| 7679 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 7680 return true; |
| 7681 } |
| 7625 default: | 7682 default: |
| 7626 // Not yet supported for inlining. | 7683 // Not yet supported for inlining. |
| 7627 break; | 7684 break; |
| 7628 } | 7685 } |
| 7629 return false; | 7686 return false; |
| 7630 } | 7687 } |
| 7631 | 7688 |
| 7632 | 7689 |
| 7633 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { | 7690 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) { |
| 7634 Expression* callee = expr->expression(); | 7691 Expression* callee = expr->expression(); |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7945 | 8002 |
| 7946 | 8003 |
| 7947 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { | 8004 void HOptimizedGraphBuilder::BuildInlinedCallNewArray(CallNew* expr) { |
| 7948 NoObservableSideEffectsScope no_effects(this); | 8005 NoObservableSideEffectsScope no_effects(this); |
| 7949 | 8006 |
| 7950 int argument_count = expr->arguments()->length(); | 8007 int argument_count = expr->arguments()->length(); |
| 7951 // We should at least have the constructor on the expression stack. | 8008 // We should at least have the constructor on the expression stack. |
| 7952 HValue* constructor = environment()->ExpressionStackAt(argument_count); | 8009 HValue* constructor = environment()->ExpressionStackAt(argument_count); |
| 7953 | 8010 |
| 7954 ElementsKind kind = expr->elements_kind(); | 8011 ElementsKind kind = expr->elements_kind(); |
| 7955 Handle<Cell> cell = expr->allocation_info_cell(); | 8012 Handle<AllocationSite> site = expr->allocation_site(); |
| 7956 Handle<AllocationSite> site(AllocationSite::cast(cell->value())); | 8013 ASSERT(!site.is_null()); |
| 7957 | 8014 |
| 7958 // Register on the site for deoptimization if the cell value changes. | 8015 // Register on the site for deoptimization if the transition feedback changes. |
| 7959 AllocationSite::AddDependentCompilationInfo( | 8016 AllocationSite::AddDependentCompilationInfo( |
| 7960 site, AllocationSite::TRANSITIONS, top_info()); | 8017 site, AllocationSite::TRANSITIONS, top_info()); |
| 7961 HInstruction* cell_instruction = Add<HConstant>(cell); | 8018 HInstruction* site_instruction = Add<HConstant>(site); |
| 7962 | 8019 |
| 7963 // In the single constant argument case, we may have to adjust elements kind | 8020 // In the single constant argument case, we may have to adjust elements kind |
| 7964 // to avoid creating a packed non-empty array. | 8021 // to avoid creating a packed non-empty array. |
| 7965 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { | 8022 if (argument_count == 1 && !IsHoleyElementsKind(kind)) { |
| 7966 HValue* argument = environment()->Top(); | 8023 HValue* argument = environment()->Top(); |
| 7967 if (argument->IsConstant()) { | 8024 if (argument->IsConstant()) { |
| 7968 HConstant* constant_argument = HConstant::cast(argument); | 8025 HConstant* constant_argument = HConstant::cast(argument); |
| 7969 ASSERT(constant_argument->HasSmiValue()); | 8026 ASSERT(constant_argument->HasSmiValue()); |
| 7970 int constant_array_size = constant_argument->Integer32Value(); | 8027 int constant_array_size = constant_argument->Integer32Value(); |
| 7971 if (constant_array_size != 0) { | 8028 if (constant_array_size != 0) { |
| 7972 kind = GetHoleyElementsKind(kind); | 8029 kind = GetHoleyElementsKind(kind); |
| 7973 } | 8030 } |
| 7974 } | 8031 } |
| 7975 } | 8032 } |
| 7976 | 8033 |
| 7977 // Build the array. | 8034 // Build the array. |
| 7978 JSArrayBuilder array_builder(this, | 8035 JSArrayBuilder array_builder(this, |
| 7979 kind, | 8036 kind, |
| 7980 cell_instruction, | 8037 site_instruction, |
| 7981 constructor, | 8038 constructor, |
| 7982 DISABLE_ALLOCATION_SITES); | 8039 DISABLE_ALLOCATION_SITES); |
| 7983 HValue* new_object; | 8040 HValue* new_object; |
| 7984 if (argument_count == 0) { | 8041 if (argument_count == 0) { |
| 7985 new_object = array_builder.AllocateEmptyArray(); | 8042 new_object = array_builder.AllocateEmptyArray(); |
| 7986 } else if (argument_count == 1) { | 8043 } else if (argument_count == 1) { |
| 7987 HValue* argument = environment()->Top(); | 8044 HValue* argument = environment()->Top(); |
| 7988 new_object = BuildAllocateArrayFromLength(&array_builder, argument); | 8045 new_object = BuildAllocateArrayFromLength(&array_builder, argument); |
| 7989 } else { | 8046 } else { |
| 7990 HValue* length = Add<HConstant>(argument_count); | 8047 HValue* length = Add<HConstant>(argument_count); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 8020 | 8077 |
| 8021 | 8078 |
| 8022 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) { | 8079 bool HOptimizedGraphBuilder::IsCallNewArrayInlineable(CallNew* expr) { |
| 8023 bool inline_ok = false; | 8080 bool inline_ok = false; |
| 8024 Handle<JSFunction> caller = current_info()->closure(); | 8081 Handle<JSFunction> caller = current_info()->closure(); |
| 8025 Handle<JSFunction> target(isolate()->global_context()->array_function(), | 8082 Handle<JSFunction> target(isolate()->global_context()->array_function(), |
| 8026 isolate()); | 8083 isolate()); |
| 8027 int argument_count = expr->arguments()->length(); | 8084 int argument_count = expr->arguments()->length(); |
| 8028 // We should have the function plus array arguments on the environment stack. | 8085 // We should have the function plus array arguments on the environment stack. |
| 8029 ASSERT(environment()->length() >= (argument_count + 1)); | 8086 ASSERT(environment()->length() >= (argument_count + 1)); |
| 8030 Handle<Cell> cell = expr->allocation_info_cell(); | 8087 Handle<AllocationSite> site = expr->allocation_site(); |
| 8031 AllocationSite* site = AllocationSite::cast(cell->value()); | 8088 ASSERT(!site.is_null()); |
| 8089 |
| 8032 if (site->CanInlineCall()) { | 8090 if (site->CanInlineCall()) { |
| 8033 // We also want to avoid inlining in certain 1 argument scenarios. | 8091 // We also want to avoid inlining in certain 1 argument scenarios. |
| 8034 if (argument_count == 1) { | 8092 if (argument_count == 1) { |
| 8035 HValue* argument = Top(); | 8093 HValue* argument = Top(); |
| 8036 if (argument->IsConstant()) { | 8094 if (argument->IsConstant()) { |
| 8037 // Do not inline if the constant length argument is not a smi or | 8095 // Do not inline if the constant length argument is not a smi or |
| 8038 // outside the valid range for a fast array. | 8096 // outside the valid range for a fast array. |
| 8039 HConstant* constant_argument = HConstant::cast(argument); | 8097 HConstant* constant_argument = HConstant::cast(argument); |
| 8040 if (constant_argument->HasSmiValue()) { | 8098 if (constant_argument->HasSmiValue()) { |
| 8041 int value = constant_argument->Integer32Value(); | 8099 int value = constant_argument->Integer32Value(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8160 environment()->SetExpressionStackAt(receiver_index, function); | 8218 environment()->SetExpressionStackAt(receiver_index, function); |
| 8161 HInstruction* call = | 8219 HInstruction* call = |
| 8162 PreProcessCall(New<HCallNew>(function, argument_count)); | 8220 PreProcessCall(New<HCallNew>(function, argument_count)); |
| 8163 return ast_context()->ReturnInstruction(call, expr->id()); | 8221 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8164 } else { | 8222 } else { |
| 8165 // The constructor function is both an operand to the instruction and an | 8223 // The constructor function is both an operand to the instruction and an |
| 8166 // argument to the construct call. | 8224 // argument to the construct call. |
| 8167 Handle<JSFunction> array_function( | 8225 Handle<JSFunction> array_function( |
| 8168 isolate()->global_context()->array_function(), isolate()); | 8226 isolate()->global_context()->array_function(), isolate()); |
| 8169 bool use_call_new_array = expr->target().is_identical_to(array_function); | 8227 bool use_call_new_array = expr->target().is_identical_to(array_function); |
| 8170 Handle<Cell> cell = expr->allocation_info_cell(); | |
| 8171 if (use_call_new_array && IsCallNewArrayInlineable(expr)) { | 8228 if (use_call_new_array && IsCallNewArrayInlineable(expr)) { |
| 8172 // Verify we are still calling the array function for our native context. | 8229 // Verify we are still calling the array function for our native context. |
| 8173 Add<HCheckValue>(function, array_function); | 8230 Add<HCheckValue>(function, array_function); |
| 8174 BuildInlinedCallNewArray(expr); | 8231 BuildInlinedCallNewArray(expr); |
| 8175 return; | 8232 return; |
| 8176 } | 8233 } |
| 8177 | 8234 |
| 8178 HBinaryCall* call; | 8235 HBinaryCall* call; |
| 8179 if (use_call_new_array) { | 8236 if (use_call_new_array) { |
| 8180 Add<HCheckValue>(function, array_function); | 8237 Add<HCheckValue>(function, array_function); |
| 8181 call = New<HCallNewArray>(function, argument_count, cell, | 8238 call = New<HCallNewArray>(function, argument_count, |
| 8182 expr->elements_kind()); | 8239 expr->elements_kind()); |
| 8183 } else { | 8240 } else { |
| 8184 call = New<HCallNew>(function, argument_count); | 8241 call = New<HCallNew>(function, argument_count); |
| 8185 } | 8242 } |
| 8186 PreProcessCall(call); | 8243 PreProcessCall(call); |
| 8187 return ast_context()->ReturnInstruction(call, expr->id()); | 8244 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8188 } | 8245 } |
| 8189 } | 8246 } |
| 8190 | 8247 |
| 8191 | 8248 |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8544 CreateJoin(materialize_false, materialize_true, expr->id()); | 8601 CreateJoin(materialize_false, materialize_true, expr->id()); |
| 8545 set_current_block(join); | 8602 set_current_block(join); |
| 8546 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 8603 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| 8547 } | 8604 } |
| 8548 | 8605 |
| 8549 | 8606 |
| 8550 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 8607 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
| 8551 bool returns_original_input, | 8608 bool returns_original_input, |
| 8552 CountOperation* expr) { | 8609 CountOperation* expr) { |
| 8553 // The input to the count operation is on top of the expression stack. | 8610 // The input to the count operation is on top of the expression stack. |
| 8554 Handle<Type> info = expr->type(); | 8611 Representation rep = Representation::FromType(expr->type()); |
| 8555 Representation rep = Representation::FromType(info); | |
| 8556 if (rep.IsNone() || rep.IsTagged()) { | 8612 if (rep.IsNone() || rep.IsTagged()) { |
| 8557 rep = Representation::Smi(); | 8613 rep = Representation::Smi(); |
| 8558 } | 8614 } |
| 8559 | 8615 |
| 8560 if (returns_original_input) { | 8616 if (returns_original_input) { |
| 8561 // We need an explicit HValue representing ToNumber(input). The | 8617 // We need an explicit HValue representing ToNumber(input). The |
| 8562 // actual HChange instruction we need is (sometimes) added in a later | 8618 // actual HChange instruction we need is (sometimes) added in a later |
| 8563 // phase, so it is not available now to be used as an input to HAdd and | 8619 // phase, so it is not available now to be used as an input to HAdd and |
| 8564 // as the return value. | 8620 // as the return value. |
| 8565 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep); | 8621 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8796 if (right_const->HasInteger32Value() && | 8852 if (right_const->HasInteger32Value() && |
| 8797 (right_const->Integer32Value() & 0x1f) != 0) { | 8853 (right_const->Integer32Value() & 0x1f) != 0) { |
| 8798 return false; | 8854 return false; |
| 8799 } | 8855 } |
| 8800 } | 8856 } |
| 8801 return true; | 8857 return true; |
| 8802 } | 8858 } |
| 8803 | 8859 |
| 8804 | 8860 |
| 8805 HValue* HGraphBuilder::EnforceNumberType(HValue* number, | 8861 HValue* HGraphBuilder::EnforceNumberType(HValue* number, |
| 8806 Handle<Type> expected) { | 8862 Type* expected) { |
| 8807 if (expected->Is(Type::Smi())) { | 8863 if (expected->Is(Type::Smi())) { |
| 8808 return AddUncasted<HForceRepresentation>(number, Representation::Smi()); | 8864 return AddUncasted<HForceRepresentation>(number, Representation::Smi()); |
| 8809 } | 8865 } |
| 8810 if (expected->Is(Type::Signed32())) { | 8866 if (expected->Is(Type::Signed32())) { |
| 8811 return AddUncasted<HForceRepresentation>(number, | 8867 return AddUncasted<HForceRepresentation>(number, |
| 8812 Representation::Integer32()); | 8868 Representation::Integer32()); |
| 8813 } | 8869 } |
| 8814 return number; | 8870 return number; |
| 8815 } | 8871 } |
| 8816 | 8872 |
| 8817 | 8873 |
| 8818 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 8874 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) { |
| 8819 if (value->IsConstant()) { | 8875 if (value->IsConstant()) { |
| 8820 HConstant* constant = HConstant::cast(value); | 8876 HConstant* constant = HConstant::cast(value); |
| 8821 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 8877 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
| 8822 if (number.has_value) { | 8878 if (number.has_value) { |
| 8823 *expected = Type::Number(isolate()); | 8879 *expected = Type::Number(zone()); |
| 8824 return AddInstruction(number.value); | 8880 return AddInstruction(number.value); |
| 8825 } | 8881 } |
| 8826 } | 8882 } |
| 8827 | 8883 |
| 8828 // We put temporary values on the stack, which don't correspond to anything | 8884 // We put temporary values on the stack, which don't correspond to anything |
| 8829 // in baseline code. Since nothing is observable we avoid recording those | 8885 // in baseline code. Since nothing is observable we avoid recording those |
| 8830 // pushes with a NoObservableSideEffectsScope. | 8886 // pushes with a NoObservableSideEffectsScope. |
| 8831 NoObservableSideEffectsScope no_effects(this); | 8887 NoObservableSideEffectsScope no_effects(this); |
| 8832 | 8888 |
| 8833 Handle<Type> expected_type = *expected; | 8889 Type* expected_type = *expected; |
| 8834 | 8890 |
| 8835 // Separate the number type from the rest. | 8891 // Separate the number type from the rest. |
| 8836 Handle<Type> expected_obj = Type::Intersect( | 8892 Type* expected_obj = |
| 8837 expected_type, Type::NonNumber(isolate()), isolate()); | 8893 Type::Intersect(expected_type, Type::NonNumber(zone()), zone()); |
| 8838 Handle<Type> expected_number = Type::Intersect( | 8894 Type* expected_number = |
| 8839 expected_type, Type::Number(isolate()), isolate()); | 8895 Type::Intersect(expected_type, Type::Number(zone()), zone()); |
| 8840 | 8896 |
| 8841 // We expect to get a number. | 8897 // We expect to get a number. |
| 8842 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 8898 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| 8843 if (expected_obj->Is(Type::None())) { | 8899 if (expected_obj->Is(Type::None())) { |
| 8844 ASSERT(!expected_number->Is(Type::None())); | 8900 ASSERT(!expected_number->Is(Type::None(zone()))); |
| 8845 return value; | 8901 return value; |
| 8846 } | 8902 } |
| 8847 | 8903 |
| 8848 if (expected_obj->Is(Type::Undefined())) { | 8904 if (expected_obj->Is(Type::Undefined(zone()))) { |
| 8849 // This is already done by HChange. | 8905 // This is already done by HChange. |
| 8850 *expected = Type::Union( | 8906 *expected = Type::Union(expected_number, Type::Double(zone()), zone()); |
| 8851 expected_number, Type::Double(isolate()), isolate()); | |
| 8852 return value; | 8907 return value; |
| 8853 } | 8908 } |
| 8854 | 8909 |
| 8855 return value; | 8910 return value; |
| 8856 } | 8911 } |
| 8857 | 8912 |
| 8858 | 8913 |
| 8859 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 8914 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 8860 BinaryOperation* expr, | 8915 BinaryOperation* expr, |
| 8861 HValue* left, | 8916 HValue* left, |
| 8862 HValue* right) { | 8917 HValue* right) { |
| 8863 Handle<Type> left_type = expr->left()->bounds().lower; | 8918 Type* left_type = expr->left()->bounds().lower; |
| 8864 Handle<Type> right_type = expr->right()->bounds().lower; | 8919 Type* right_type = expr->right()->bounds().lower; |
| 8865 Handle<Type> result_type = expr->bounds().lower; | 8920 Type* result_type = expr->bounds().lower; |
| 8866 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 8921 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 8867 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 8922 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 8868 | 8923 |
| 8869 HAllocationMode allocation_mode = | 8924 HAllocationMode allocation_mode = |
| 8870 FLAG_allocation_site_pretenuring | 8925 FLAG_allocation_site_pretenuring |
| 8871 ? (allocation_site.is_null() | 8926 ? (allocation_site.is_null() |
| 8872 ? HAllocationMode(NOT_TENURED) | 8927 ? HAllocationMode(NOT_TENURED) |
| 8873 : HAllocationMode(allocation_site)) | 8928 : HAllocationMode(allocation_site)) |
| 8874 : HAllocationMode(isolate()->heap()->GetPretenureMode()); | 8929 : HAllocationMode(isolate()->heap()->GetPretenureMode()); |
| 8875 | 8930 |
| 8876 HValue* result = HGraphBuilder::BuildBinaryOperation( | 8931 HValue* result = HGraphBuilder::BuildBinaryOperation( |
| 8877 expr->op(), left, right, left_type, right_type, result_type, | 8932 expr->op(), left, right, left_type, right_type, result_type, |
| 8878 fixed_right_arg, allocation_mode); | 8933 fixed_right_arg, allocation_mode); |
| 8879 // Add a simulate after instructions with observable side effects, and | 8934 // Add a simulate after instructions with observable side effects, and |
| 8880 // after phis, which are the result of BuildBinaryOperation when we | 8935 // after phis, which are the result of BuildBinaryOperation when we |
| 8881 // inlined some complex subgraph. | 8936 // inlined some complex subgraph. |
| 8882 if (result->HasObservableSideEffects() || result->IsPhi()) { | 8937 if (result->HasObservableSideEffects() || result->IsPhi()) { |
| 8883 Push(result); | 8938 Push(result); |
| 8884 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 8939 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 8885 Drop(1); | 8940 Drop(1); |
| 8886 } | 8941 } |
| 8887 return result; | 8942 return result; |
| 8888 } | 8943 } |
| 8889 | 8944 |
| 8890 | 8945 |
| 8891 HValue* HGraphBuilder::BuildBinaryOperation( | 8946 HValue* HGraphBuilder::BuildBinaryOperation( |
| 8892 Token::Value op, | 8947 Token::Value op, |
| 8893 HValue* left, | 8948 HValue* left, |
| 8894 HValue* right, | 8949 HValue* right, |
| 8895 Handle<Type> left_type, | 8950 Type* left_type, |
| 8896 Handle<Type> right_type, | 8951 Type* right_type, |
| 8897 Handle<Type> result_type, | 8952 Type* result_type, |
| 8898 Maybe<int> fixed_right_arg, | 8953 Maybe<int> fixed_right_arg, |
| 8899 HAllocationMode allocation_mode) { | 8954 HAllocationMode allocation_mode) { |
| 8900 | 8955 |
| 8901 Representation left_rep = Representation::FromType(left_type); | 8956 Representation left_rep = Representation::FromType(left_type); |
| 8902 Representation right_rep = Representation::FromType(right_type); | 8957 Representation right_rep = Representation::FromType(right_type); |
| 8903 | 8958 |
| 8904 bool maybe_string_add = op == Token::ADD && | 8959 bool maybe_string_add = op == Token::ADD && |
| 8905 (left_type->Maybe(Type::String()) || | 8960 (left_type->Maybe(Type::String()) || |
| 8906 right_type->Maybe(Type::String())); | 8961 right_type->Maybe(Type::String())); |
| 8907 | 8962 |
| 8908 if (left_type->Is(Type::None())) { | 8963 if (left_type->Is(Type::None())) { |
| 8909 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8964 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| 8910 Deoptimizer::SOFT); | 8965 Deoptimizer::SOFT); |
| 8911 // TODO(rossberg): we should be able to get rid of non-continuous | 8966 // TODO(rossberg): we should be able to get rid of non-continuous |
| 8912 // defaults. | 8967 // defaults. |
| 8913 left_type = Type::Any(isolate()); | 8968 left_type = Type::Any(zone()); |
| 8914 } else { | 8969 } else { |
| 8915 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 8970 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
| 8916 left_rep = Representation::FromType(left_type); | 8971 left_rep = Representation::FromType(left_type); |
| 8917 } | 8972 } |
| 8918 | 8973 |
| 8919 if (right_type->Is(Type::None())) { | 8974 if (right_type->Is(Type::None())) { |
| 8920 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 8975 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
| 8921 Deoptimizer::SOFT); | 8976 Deoptimizer::SOFT); |
| 8922 right_type = Type::Any(isolate()); | 8977 right_type = Type::Any(zone()); |
| 8923 } else { | 8978 } else { |
| 8924 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 8979 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
| 8925 right_rep = Representation::FromType(right_type); | 8980 right_rep = Representation::FromType(right_type); |
| 8926 } | 8981 } |
| 8927 | 8982 |
| 8928 // Special case for string addition here. | 8983 // Special case for string addition here. |
| 8929 if (op == Token::ADD && | 8984 if (op == Token::ADD && |
| 8930 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 8985 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
| 8931 // Validate type feedback for left argument. | 8986 // Validate type feedback for left argument. |
| 8932 if (left_type->Is(Type::String())) { | 8987 if (left_type->Is(Type::String())) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 8955 ASSERT(left_type->Is(Type::String())); | 9010 ASSERT(left_type->Is(Type::String())); |
| 8956 right = BuildNumberToString(right, right_type); | 9011 right = BuildNumberToString(right, right_type); |
| 8957 } else if (!right_type->Is(Type::String())) { | 9012 } else if (!right_type->Is(Type::String())) { |
| 8958 ASSERT(left_type->Is(Type::String())); | 9013 ASSERT(left_type->Is(Type::String())); |
| 8959 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); | 9014 HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT); |
| 8960 Add<HPushArgument>(left); | 9015 Add<HPushArgument>(left); |
| 8961 Add<HPushArgument>(right); | 9016 Add<HPushArgument>(right); |
| 8962 return AddUncasted<HInvokeFunction>(function, 2); | 9017 return AddUncasted<HInvokeFunction>(function, 2); |
| 8963 } | 9018 } |
| 8964 | 9019 |
| 8965 // Inline the string addition into the stub when creating allocation | 9020 // Fast path for empty constant strings. |
| 8966 // mementos to gather allocation site feedback. | 9021 if (left->IsConstant() && |
| 8967 if (graph()->info()->IsStub() && | 9022 HConstant::cast(left)->HasStringValue() && |
| 8968 allocation_mode.CreateAllocationMementos()) { | 9023 HConstant::cast(left)->StringValue()->length() == 0) { |
| 8969 return BuildStringAdd(left, right, allocation_mode); | 9024 return right; |
| 9025 } |
| 9026 if (right->IsConstant() && |
| 9027 HConstant::cast(right)->HasStringValue() && |
| 9028 HConstant::cast(right)->StringValue()->length() == 0) { |
| 9029 return left; |
| 8970 } | 9030 } |
| 8971 | 9031 |
| 8972 // Register the dependent code with the allocation site. | 9032 // Register the dependent code with the allocation site. |
| 8973 if (!allocation_mode.feedback_site().is_null()) { | 9033 if (!allocation_mode.feedback_site().is_null()) { |
| 8974 ASSERT(!graph()->info()->IsStub()); | 9034 ASSERT(!graph()->info()->IsStub()); |
| 8975 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 9035 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
| 8976 AllocationSite::AddDependentCompilationInfo( | 9036 AllocationSite::AddDependentCompilationInfo( |
| 8977 site, AllocationSite::TENURING, top_info()); | 9037 site, AllocationSite::TENURING, top_info()); |
| 8978 } | 9038 } |
| 8979 | 9039 |
| 8980 // Inline string addition if we know that we'll create a cons string. | 9040 // Inline the string addition into the stub when creating allocation |
| 8981 if (left->IsConstant()) { | 9041 // mementos to gather allocation site feedback, or if we can statically |
| 8982 HConstant* c_left = HConstant::cast(left); | 9042 // infer that we're going to create a cons string. |
| 8983 if (c_left->HasStringValue()) { | 9043 if ((graph()->info()->IsStub() && |
| 8984 int c_left_length = c_left->StringValue()->length(); | 9044 allocation_mode.CreateAllocationMementos()) || |
| 8985 if (c_left_length == 0) { | 9045 (left->IsConstant() && |
| 8986 return right; | 9046 HConstant::cast(left)->HasStringValue() && |
| 8987 } else if (c_left_length + 1 >= ConsString::kMinLength) { | 9047 HConstant::cast(left)->StringValue()->length() + 1 >= |
| 8988 return BuildStringAdd(left, right, allocation_mode); | 9048 ConsString::kMinLength) || |
| 8989 } | 9049 (right->IsConstant() && |
| 8990 } | 9050 HConstant::cast(right)->HasStringValue() && |
| 8991 } | 9051 HConstant::cast(right)->StringValue()->length() + 1 >= |
| 8992 if (right->IsConstant()) { | 9052 ConsString::kMinLength)) { |
| 8993 HConstant* c_right = HConstant::cast(right); | 9053 return BuildStringAdd(left, right, allocation_mode); |
| 8994 if (c_right->HasStringValue()) { | |
| 8995 int c_right_length = c_right->StringValue()->length(); | |
| 8996 if (c_right_length == 0) { | |
| 8997 return left; | |
| 8998 } else if (c_right_length + 1 >= ConsString::kMinLength) { | |
| 8999 return BuildStringAdd(left, right, allocation_mode); | |
| 9000 } | |
| 9001 } | |
| 9002 } | 9054 } |
| 9003 | 9055 |
| 9004 // Fallback to using the string add stub. | 9056 // Fallback to using the string add stub. |
| 9005 return AddUncasted<HStringAdd>( | 9057 return AddUncasted<HStringAdd>( |
| 9006 left, right, allocation_mode.GetPretenureMode(), | 9058 left, right, allocation_mode.GetPretenureMode(), |
| 9007 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 9059 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
| 9008 } | 9060 } |
| 9009 | 9061 |
| 9010 if (graph()->info()->IsStub()) { | 9062 if (graph()->info()->IsStub()) { |
| 9011 left = EnforceNumberType(left, left_type); | 9063 left = EnforceNumberType(left, left_type); |
| (...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9320 CallRuntime* call = expr->left()->AsCallRuntime(); | 9372 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 9321 ASSERT(call->arguments()->length() == 1); | 9373 ASSERT(call->arguments()->length() == 1); |
| 9322 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9374 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9323 HValue* value = Pop(); | 9375 HValue* value = Pop(); |
| 9324 Literal* literal = expr->right()->AsLiteral(); | 9376 Literal* literal = expr->right()->AsLiteral(); |
| 9325 Handle<String> rhs = Handle<String>::cast(literal->value()); | 9377 Handle<String> rhs = Handle<String>::cast(literal->value()); |
| 9326 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); | 9378 HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs); |
| 9327 return ast_context()->ReturnControl(instr, expr->id()); | 9379 return ast_context()->ReturnControl(instr, expr->id()); |
| 9328 } | 9380 } |
| 9329 | 9381 |
| 9330 Handle<Type> left_type = expr->left()->bounds().lower; | 9382 Type* left_type = expr->left()->bounds().lower; |
| 9331 Handle<Type> right_type = expr->right()->bounds().lower; | 9383 Type* right_type = expr->right()->bounds().lower; |
| 9332 Handle<Type> combined_type = expr->combined_type(); | 9384 Type* combined_type = expr->combined_type(); |
| 9333 | 9385 |
| 9334 CHECK_ALIVE(VisitForValue(expr->left())); | 9386 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9335 CHECK_ALIVE(VisitForValue(expr->right())); | 9387 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9336 | 9388 |
| 9337 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); | 9389 if (FLAG_emit_opt_code_positions) SetSourcePosition(expr->position()); |
| 9338 | 9390 |
| 9339 HValue* right = Pop(); | 9391 HValue* right = Pop(); |
| 9340 HValue* left = Pop(); | 9392 HValue* left = Pop(); |
| 9341 Token::Value op = expr->op(); | 9393 Token::Value op = expr->op(); |
| 9342 | 9394 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9399 expr->left()->position(), expr->right()->position(), expr->id()); | 9451 expr->left()->position(), expr->right()->position(), expr->id()); |
| 9400 if (compare == NULL) return; // Bailed out. | 9452 if (compare == NULL) return; // Bailed out. |
| 9401 return ast_context()->ReturnControl(compare, expr->id()); | 9453 return ast_context()->ReturnControl(compare, expr->id()); |
| 9402 } | 9454 } |
| 9403 | 9455 |
| 9404 | 9456 |
| 9405 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( | 9457 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( |
| 9406 Token::Value op, | 9458 Token::Value op, |
| 9407 HValue* left, | 9459 HValue* left, |
| 9408 HValue* right, | 9460 HValue* right, |
| 9409 Handle<Type> left_type, | 9461 Type* left_type, |
| 9410 Handle<Type> right_type, | 9462 Type* right_type, |
| 9411 Handle<Type> combined_type, | 9463 Type* combined_type, |
| 9412 int left_position, | 9464 int left_position, |
| 9413 int right_position, | 9465 int right_position, |
| 9414 BailoutId bailout_id) { | 9466 BailoutId bailout_id) { |
| 9415 // Cases handled below depend on collected type feedback. They should | 9467 // Cases handled below depend on collected type feedback. They should |
| 9416 // soft deoptimize when there is no type feedback. | 9468 // soft deoptimize when there is no type feedback. |
| 9417 if (combined_type->Is(Type::None())) { | 9469 if (combined_type->Is(Type::None())) { |
| 9418 Add<HDeoptimize>("Insufficient type feedback for combined type " | 9470 Add<HDeoptimize>("Insufficient type feedback for combined type " |
| 9419 "of binary operation", | 9471 "of binary operation", |
| 9420 Deoptimizer::SOFT); | 9472 Deoptimizer::SOFT); |
| 9421 combined_type = left_type = right_type = Type::Any(isolate()); | 9473 combined_type = left_type = right_type = Type::Any(zone()); |
| 9422 } | 9474 } |
| 9423 | 9475 |
| 9424 Representation left_rep = Representation::FromType(left_type); | 9476 Representation left_rep = Representation::FromType(left_type); |
| 9425 Representation right_rep = Representation::FromType(right_type); | 9477 Representation right_rep = Representation::FromType(right_type); |
| 9426 Representation combined_rep = Representation::FromType(combined_type); | 9478 Representation combined_rep = Representation::FromType(combined_type); |
| 9427 | 9479 |
| 9428 if (combined_type->Is(Type::Receiver())) { | 9480 if (combined_type->Is(Type::Receiver())) { |
| 9429 if (Token::IsEqualityOp(op)) { | 9481 if (Token::IsEqualityOp(op)) { |
| 9430 // Can we get away with map check and not instance type check? | 9482 // Can we get away with map check and not instance type check? |
| 9431 HValue* operand_to_check = | 9483 HValue* operand_to_check = |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9507 HValue* value = Pop(); | 9559 HValue* value = Pop(); |
| 9508 if (expr->op() == Token::EQ_STRICT) { | 9560 if (expr->op() == Token::EQ_STRICT) { |
| 9509 HConstant* nil_constant = nil == kNullValue | 9561 HConstant* nil_constant = nil == kNullValue |
| 9510 ? graph()->GetConstantNull() | 9562 ? graph()->GetConstantNull() |
| 9511 : graph()->GetConstantUndefined(); | 9563 : graph()->GetConstantUndefined(); |
| 9512 HCompareObjectEqAndBranch* instr = | 9564 HCompareObjectEqAndBranch* instr = |
| 9513 New<HCompareObjectEqAndBranch>(value, nil_constant); | 9565 New<HCompareObjectEqAndBranch>(value, nil_constant); |
| 9514 return ast_context()->ReturnControl(instr, expr->id()); | 9566 return ast_context()->ReturnControl(instr, expr->id()); |
| 9515 } else { | 9567 } else { |
| 9516 ASSERT_EQ(Token::EQ, expr->op()); | 9568 ASSERT_EQ(Token::EQ, expr->op()); |
| 9517 Handle<Type> type = expr->combined_type()->Is(Type::None()) | 9569 Type* type = expr->combined_type()->Is(Type::None()) |
| 9518 ? Type::Any(isolate_) : expr->combined_type(); | 9570 ? Type::Any(zone()) : expr->combined_type(); |
| 9519 HIfContinuation continuation; | 9571 HIfContinuation continuation; |
| 9520 BuildCompareNil(value, type, &continuation); | 9572 BuildCompareNil(value, type, &continuation); |
| 9521 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9573 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9522 } | 9574 } |
| 9523 } | 9575 } |
| 9524 | 9576 |
| 9525 | 9577 |
| 9526 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9578 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 9527 // If we share optimized code between different closures, the | 9579 // If we share optimized code between different closures, the |
| 9528 // this-function is not a constant, except inside an inlined body. | 9580 // this-function is not a constant, except inside an inlined body. |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10278 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 10330 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 10279 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 10331 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
| 10280 } | 10332 } |
| 10281 | 10333 |
| 10282 | 10334 |
| 10283 // Fast support for number to string. | 10335 // Fast support for number to string. |
| 10284 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 10336 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 10285 ASSERT_EQ(1, call->arguments()->length()); | 10337 ASSERT_EQ(1, call->arguments()->length()); |
| 10286 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10338 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10287 HValue* number = Pop(); | 10339 HValue* number = Pop(); |
| 10288 HValue* result = BuildNumberToString(number, Type::Number(isolate())); | 10340 HValue* result = BuildNumberToString(number, Type::Any(zone())); |
| 10289 return ast_context()->ReturnValue(result); | 10341 return ast_context()->ReturnValue(result); |
| 10290 } | 10342 } |
| 10291 | 10343 |
| 10292 | 10344 |
| 10293 // Fast call for custom callbacks. | 10345 // Fast call for custom callbacks. |
| 10294 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 10346 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 10295 // 1 ~ The function to call is not itself an argument to the call. | 10347 // 1 ~ The function to call is not itself an argument to the call. |
| 10296 int arg_count = call->arguments()->length() - 1; | 10348 int arg_count = call->arguments()->length() - 1; |
| 10297 ASSERT(arg_count >= 1); // There's always at least a receiver. | 10349 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 10298 | 10350 |
| (...skipping 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11014 if (ShouldProduceTraceOutput()) { | 11066 if (ShouldProduceTraceOutput()) { |
| 11015 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11067 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11016 } | 11068 } |
| 11017 | 11069 |
| 11018 #ifdef DEBUG | 11070 #ifdef DEBUG |
| 11019 graph_->Verify(false); // No full verify. | 11071 graph_->Verify(false); // No full verify. |
| 11020 #endif | 11072 #endif |
| 11021 } | 11073 } |
| 11022 | 11074 |
| 11023 } } // namespace v8::internal | 11075 } } // namespace v8::internal |
| OLD | NEW |