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 1286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1297 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { | 1297 HConstant::cast(function)->handle(isolate())->IsJSFunction()) { |
1298 Handle<JSFunction> f = Handle<JSFunction>::cast( | 1298 Handle<JSFunction> f = Handle<JSFunction>::cast( |
1299 HConstant::cast(function)->handle(isolate())); | 1299 HConstant::cast(function)->handle(isolate())); |
1300 SharedFunctionInfo* shared = f->shared(); | 1300 SharedFunctionInfo* shared = f->shared(); |
1301 if (!shared->is_classic_mode() || shared->native()) return object; | 1301 if (!shared->is_classic_mode() || shared->native()) return object; |
1302 } | 1302 } |
1303 return Add<HWrapReceiver>(object, function); | 1303 return Add<HWrapReceiver>(object, function); |
1304 } | 1304 } |
1305 | 1305 |
1306 | 1306 |
1307 HValue* HGraphBuilder::BuildCheckForCapacityGrow(HValue* object, | 1307 HValue* HGraphBuilder::BuildCheckForCapacityGrow( |
1308 HValue* elements, | 1308 HValue* object, |
1309 ElementsKind kind, | 1309 HValue* elements, |
1310 HValue* length, | 1310 ElementsKind kind, |
1311 HValue* key, | 1311 HValue* length, |
1312 bool is_js_array, | 1312 HValue* key, |
1313 bool is_store) { | 1313 bool is_js_array, |
| 1314 PropertyAccessType access_type) { |
1314 IfBuilder length_checker(this); | 1315 IfBuilder length_checker(this); |
1315 | 1316 |
1316 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; | 1317 Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ; |
1317 length_checker.If<HCompareNumericAndBranch>(key, length, token); | 1318 length_checker.If<HCompareNumericAndBranch>(key, length, token); |
1318 | 1319 |
1319 length_checker.Then(); | 1320 length_checker.Then(); |
1320 | 1321 |
1321 HValue* current_capacity = AddLoadFixedArrayLength(elements); | 1322 HValue* current_capacity = AddLoadFixedArrayLength(elements); |
1322 | 1323 |
1323 IfBuilder capacity_checker(this); | 1324 IfBuilder capacity_checker(this); |
(...skipping 22 matching lines...) Expand all Loading... |
1346 capacity_checker.End(); | 1347 capacity_checker.End(); |
1347 | 1348 |
1348 if (is_js_array) { | 1349 if (is_js_array) { |
1349 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); | 1350 HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1()); |
1350 new_length->ClearFlag(HValue::kCanOverflow); | 1351 new_length->ClearFlag(HValue::kCanOverflow); |
1351 | 1352 |
1352 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), | 1353 Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind), |
1353 new_length); | 1354 new_length); |
1354 } | 1355 } |
1355 | 1356 |
1356 if (is_store && kind == FAST_SMI_ELEMENTS) { | 1357 if (access_type == STORE && kind == FAST_SMI_ELEMENTS) { |
1357 HValue* checked_elements = environment()->Top(); | 1358 HValue* checked_elements = environment()->Top(); |
1358 | 1359 |
1359 // Write zero to ensure that the new element is initialized with some smi. | 1360 // Write zero to ensure that the new element is initialized with some smi. |
1360 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind); | 1361 Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind); |
1361 } | 1362 } |
1362 | 1363 |
1363 length_checker.Else(); | 1364 length_checker.Else(); |
1364 Add<HBoundsCheck>(key, length); | 1365 Add<HBoundsCheck>(key, length); |
1365 | 1366 |
1366 environment()->Push(elements); | 1367 environment()->Push(elements); |
(...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2152 return Pop(); | 2153 return Pop(); |
2153 } | 2154 } |
2154 | 2155 |
2155 | 2156 |
2156 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( | 2157 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( |
2157 HValue* checked_object, | 2158 HValue* checked_object, |
2158 HValue* key, | 2159 HValue* key, |
2159 HValue* val, | 2160 HValue* val, |
2160 bool is_js_array, | 2161 bool is_js_array, |
2161 ElementsKind elements_kind, | 2162 ElementsKind elements_kind, |
2162 bool is_store, | 2163 PropertyAccessType access_type, |
2163 LoadKeyedHoleMode load_mode, | 2164 LoadKeyedHoleMode load_mode, |
2164 KeyedAccessStoreMode store_mode) { | 2165 KeyedAccessStoreMode store_mode) { |
2165 ASSERT((!IsExternalArrayElementsKind(elements_kind) && | 2166 ASSERT((!IsExternalArrayElementsKind(elements_kind) && |
2166 !IsFixedTypedArrayElementsKind(elements_kind)) || | 2167 !IsFixedTypedArrayElementsKind(elements_kind)) || |
2167 !is_js_array); | 2168 !is_js_array); |
2168 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency | 2169 // No GVNFlag is necessary for ElementsKind if there is an explicit dependency |
2169 // on a HElementsTransition instruction. The flag can also be removed if the | 2170 // on a HElementsTransition instruction. The flag can also be removed if the |
2170 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further | 2171 // map to check has FAST_HOLEY_ELEMENTS, since there can be no further |
2171 // ElementsKind transitions. Finally, the dependency can be removed for stores | 2172 // ElementsKind transitions. Finally, the dependency can be removed for stores |
2172 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the | 2173 // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the |
2173 // generated store code. | 2174 // generated store code. |
2174 if ((elements_kind == FAST_HOLEY_ELEMENTS) || | 2175 if ((elements_kind == FAST_HOLEY_ELEMENTS) || |
2175 (elements_kind == FAST_ELEMENTS && is_store)) { | 2176 (elements_kind == FAST_ELEMENTS && access_type == STORE)) { |
2176 checked_object->ClearGVNFlag(kDependsOnElementsKind); | 2177 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
2177 } | 2178 } |
2178 | 2179 |
2179 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); | 2180 bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind); |
2180 bool fast_elements = IsFastObjectElementsKind(elements_kind); | 2181 bool fast_elements = IsFastObjectElementsKind(elements_kind); |
2181 HValue* elements = AddLoadElements(checked_object); | 2182 HValue* elements = AddLoadElements(checked_object); |
2182 if (is_store && (fast_elements || fast_smi_only_elements) && | 2183 if (access_type == STORE && (fast_elements || fast_smi_only_elements) && |
2183 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { | 2184 store_mode != STORE_NO_TRANSITION_HANDLE_COW) { |
2184 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2185 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
2185 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2186 elements, isolate()->factory()->fixed_array_map(), top_info()); |
2186 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 2187 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
2187 } | 2188 } |
2188 HInstruction* length = NULL; | 2189 HInstruction* length = NULL; |
2189 if (is_js_array) { | 2190 if (is_js_array) { |
2190 length = Add<HLoadNamedField>( | 2191 length = Add<HLoadNamedField>( |
2191 checked_object, static_cast<HValue*>(NULL), | 2192 checked_object, static_cast<HValue*>(NULL), |
2192 HObjectAccess::ForArrayLength(elements_kind)); | 2193 HObjectAccess::ForArrayLength(elements_kind)); |
(...skipping 15 matching lines...) Expand all Loading... |
2208 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 2209 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
2209 NoObservableSideEffectsScope no_effects(this); | 2210 NoObservableSideEffectsScope no_effects(this); |
2210 IfBuilder length_checker(this); | 2211 IfBuilder length_checker(this); |
2211 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2212 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
2212 length_checker.Then(); | 2213 length_checker.Then(); |
2213 IfBuilder negative_checker(this); | 2214 IfBuilder negative_checker(this); |
2214 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2215 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
2215 key, graph()->GetConstant0(), Token::GTE); | 2216 key, graph()->GetConstant0(), Token::GTE); |
2216 negative_checker.Then(); | 2217 negative_checker.Then(); |
2217 HInstruction* result = AddElementAccess( | 2218 HInstruction* result = AddElementAccess( |
2218 backing_store, key, val, bounds_check, elements_kind, is_store); | 2219 backing_store, key, val, bounds_check, elements_kind, access_type); |
2219 negative_checker.ElseDeopt("Negative key encountered"); | 2220 negative_checker.ElseDeopt("Negative key encountered"); |
2220 negative_checker.End(); | 2221 negative_checker.End(); |
2221 length_checker.End(); | 2222 length_checker.End(); |
2222 return result; | 2223 return result; |
2223 } else { | 2224 } else { |
2224 ASSERT(store_mode == STANDARD_STORE); | 2225 ASSERT(store_mode == STANDARD_STORE); |
2225 checked_key = Add<HBoundsCheck>(key, length); | 2226 checked_key = Add<HBoundsCheck>(key, length); |
2226 return AddElementAccess( | 2227 return AddElementAccess( |
2227 backing_store, checked_key, val, | 2228 backing_store, checked_key, val, |
2228 checked_object, elements_kind, is_store); | 2229 checked_object, elements_kind, access_type); |
2229 } | 2230 } |
2230 } | 2231 } |
2231 ASSERT(fast_smi_only_elements || | 2232 ASSERT(fast_smi_only_elements || |
2232 fast_elements || | 2233 fast_elements || |
2233 IsFastDoubleElementsKind(elements_kind)); | 2234 IsFastDoubleElementsKind(elements_kind)); |
2234 | 2235 |
2235 // In case val is stored into a fast smi array, assure that the value is a smi | 2236 // In case val is stored into a fast smi array, assure that the value is a smi |
2236 // before manipulating the backing store. Otherwise the actual store may | 2237 // before manipulating the backing store. Otherwise the actual store may |
2237 // deopt, leaving the backing store in an invalid state. | 2238 // deopt, leaving the backing store in an invalid state. |
2238 if (is_store && IsFastSmiElementsKind(elements_kind) && | 2239 if (access_type == STORE && IsFastSmiElementsKind(elements_kind) && |
2239 !val->type().IsSmi()) { | 2240 !val->type().IsSmi()) { |
2240 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); | 2241 val = AddUncasted<HForceRepresentation>(val, Representation::Smi()); |
2241 } | 2242 } |
2242 | 2243 |
2243 if (IsGrowStoreMode(store_mode)) { | 2244 if (IsGrowStoreMode(store_mode)) { |
2244 NoObservableSideEffectsScope no_effects(this); | 2245 NoObservableSideEffectsScope no_effects(this); |
2245 elements = BuildCheckForCapacityGrow(checked_object, elements, | 2246 elements = BuildCheckForCapacityGrow(checked_object, elements, |
2246 elements_kind, length, key, | 2247 elements_kind, length, key, |
2247 is_js_array, is_store); | 2248 is_js_array, access_type); |
2248 checked_key = key; | 2249 checked_key = key; |
2249 } else { | 2250 } else { |
2250 checked_key = Add<HBoundsCheck>(key, length); | 2251 checked_key = Add<HBoundsCheck>(key, length); |
2251 | 2252 |
2252 if (is_store && (fast_elements || fast_smi_only_elements)) { | 2253 if (access_type == STORE && (fast_elements || fast_smi_only_elements)) { |
2253 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { | 2254 if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) { |
2254 NoObservableSideEffectsScope no_effects(this); | 2255 NoObservableSideEffectsScope no_effects(this); |
2255 elements = BuildCopyElementsOnWrite(checked_object, elements, | 2256 elements = BuildCopyElementsOnWrite(checked_object, elements, |
2256 elements_kind, length); | 2257 elements_kind, length); |
2257 } else { | 2258 } else { |
2258 HCheckMaps* check_cow_map = Add<HCheckMaps>( | 2259 HCheckMaps* check_cow_map = Add<HCheckMaps>( |
2259 elements, isolate()->factory()->fixed_array_map(), top_info()); | 2260 elements, isolate()->factory()->fixed_array_map(), top_info()); |
2260 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); | 2261 check_cow_map->ClearGVNFlag(kDependsOnElementsKind); |
2261 } | 2262 } |
2262 } | 2263 } |
2263 } | 2264 } |
2264 return AddElementAccess(elements, checked_key, val, checked_object, | 2265 return AddElementAccess(elements, checked_key, val, checked_object, |
2265 elements_kind, is_store, load_mode); | 2266 elements_kind, access_type, load_mode); |
2266 } | 2267 } |
2267 | 2268 |
2268 | 2269 |
2269 | 2270 |
2270 HValue* HGraphBuilder::BuildAllocateArrayFromLength( | 2271 HValue* HGraphBuilder::BuildAllocateArrayFromLength( |
2271 JSArrayBuilder* array_builder, | 2272 JSArrayBuilder* array_builder, |
2272 HValue* length_argument) { | 2273 HValue* length_argument) { |
2273 if (length_argument->IsConstant() && | 2274 if (length_argument->IsConstant() && |
2274 HConstant::cast(length_argument)->HasSmiValue()) { | 2275 HConstant::cast(length_argument)->HasSmiValue()) { |
2275 int array_length = HConstant::cast(length_argument)->Integer32Value(); | 2276 int array_length = HConstant::cast(length_argument)->Integer32Value(); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2397 return elements; | 2398 return elements; |
2398 } | 2399 } |
2399 | 2400 |
2400 | 2401 |
2401 HInstruction* HGraphBuilder::AddElementAccess( | 2402 HInstruction* HGraphBuilder::AddElementAccess( |
2402 HValue* elements, | 2403 HValue* elements, |
2403 HValue* checked_key, | 2404 HValue* checked_key, |
2404 HValue* val, | 2405 HValue* val, |
2405 HValue* dependency, | 2406 HValue* dependency, |
2406 ElementsKind elements_kind, | 2407 ElementsKind elements_kind, |
2407 bool is_store, | 2408 PropertyAccessType access_type, |
2408 LoadKeyedHoleMode load_mode) { | 2409 LoadKeyedHoleMode load_mode) { |
2409 if (is_store) { | 2410 if (access_type == STORE) { |
2410 ASSERT(val != NULL); | 2411 ASSERT(val != NULL); |
2411 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || | 2412 if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || |
2412 elements_kind == UINT8_CLAMPED_ELEMENTS) { | 2413 elements_kind == UINT8_CLAMPED_ELEMENTS) { |
2413 val = Add<HClampToUint8>(val); | 2414 val = Add<HClampToUint8>(val); |
2414 } | 2415 } |
2415 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, | 2416 return Add<HStoreKeyed>(elements, checked_key, val, elements_kind, |
2416 elements_kind == FAST_SMI_ELEMENTS | 2417 elements_kind == FAST_SMI_ELEMENTS |
2417 ? STORE_TO_INITIALIZED_ENTRY | 2418 ? STORE_TO_INITIALIZED_ENTRY |
2418 : INITIALIZING_STORE); | 2419 : INITIALIZING_STORE); |
2419 } | 2420 } |
2420 | 2421 |
2421 ASSERT(!is_store); | 2422 ASSERT(access_type == LOAD); |
2422 ASSERT(val == NULL); | 2423 ASSERT(val == NULL); |
2423 HLoadKeyed* load = Add<HLoadKeyed>( | 2424 HLoadKeyed* load = Add<HLoadKeyed>( |
2424 elements, checked_key, dependency, elements_kind, load_mode); | 2425 elements, checked_key, dependency, elements_kind, load_mode); |
2425 if (FLAG_opt_safe_uint32_operations && | 2426 if (FLAG_opt_safe_uint32_operations && |
2426 (elements_kind == EXTERNAL_UINT32_ELEMENTS || | 2427 (elements_kind == EXTERNAL_UINT32_ELEMENTS || |
2427 elements_kind == UINT32_ELEMENTS)) { | 2428 elements_kind == UINT32_ELEMENTS)) { |
2428 graph()->RecordUint32Instruction(load); | 2429 graph()->RecordUint32Instruction(load); |
2429 } | 2430 } |
2430 return load; | 2431 return load; |
2431 } | 2432 } |
(...skipping 2343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4775 set_current_block(join); | 4776 set_current_block(join); |
4776 if (join != NULL && !ast_context()->IsEffect()) { | 4777 if (join != NULL && !ast_context()->IsEffect()) { |
4777 return ast_context()->ReturnValue(Pop()); | 4778 return ast_context()->ReturnValue(Pop()); |
4778 } | 4779 } |
4779 } | 4780 } |
4780 } | 4781 } |
4781 | 4782 |
4782 | 4783 |
4783 HOptimizedGraphBuilder::GlobalPropertyAccess | 4784 HOptimizedGraphBuilder::GlobalPropertyAccess |
4784 HOptimizedGraphBuilder::LookupGlobalProperty( | 4785 HOptimizedGraphBuilder::LookupGlobalProperty( |
4785 Variable* var, LookupResult* lookup, bool is_store) { | 4786 Variable* var, LookupResult* lookup, PropertyAccessType access_type) { |
4786 if (var->is_this() || !current_info()->has_global_object()) { | 4787 if (var->is_this() || !current_info()->has_global_object()) { |
4787 return kUseGeneric; | 4788 return kUseGeneric; |
4788 } | 4789 } |
4789 Handle<GlobalObject> global(current_info()->global_object()); | 4790 Handle<GlobalObject> global(current_info()->global_object()); |
4790 global->Lookup(*var->name(), lookup); | 4791 global->Lookup(*var->name(), lookup); |
4791 if (!lookup->IsNormal() || | 4792 if (!lookup->IsNormal() || |
4792 (is_store && lookup->IsReadOnly()) || | 4793 (access_type == STORE && lookup->IsReadOnly()) || |
4793 lookup->holder() != *global) { | 4794 lookup->holder() != *global) { |
4794 return kUseGeneric; | 4795 return kUseGeneric; |
4795 } | 4796 } |
4796 | 4797 |
4797 return kUseCell; | 4798 return kUseCell; |
4798 } | 4799 } |
4799 | 4800 |
4800 | 4801 |
4801 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { | 4802 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) { |
4802 ASSERT(var->IsContextSlot()); | 4803 ASSERT(var->IsContextSlot()); |
(...skipping 25 matching lines...) Expand all Loading... |
4828 // Handle known global constants like 'undefined' specially to avoid a | 4829 // Handle known global constants like 'undefined' specially to avoid a |
4829 // load from a global cell for them. | 4830 // load from a global cell for them. |
4830 Handle<Object> constant_value = | 4831 Handle<Object> constant_value = |
4831 isolate()->factory()->GlobalConstantFor(variable->name()); | 4832 isolate()->factory()->GlobalConstantFor(variable->name()); |
4832 if (!constant_value.is_null()) { | 4833 if (!constant_value.is_null()) { |
4833 HConstant* instr = New<HConstant>(constant_value); | 4834 HConstant* instr = New<HConstant>(constant_value); |
4834 return ast_context()->ReturnInstruction(instr, expr->id()); | 4835 return ast_context()->ReturnInstruction(instr, expr->id()); |
4835 } | 4836 } |
4836 | 4837 |
4837 LookupResult lookup(isolate()); | 4838 LookupResult lookup(isolate()); |
4838 GlobalPropertyAccess type = | 4839 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, LOAD); |
4839 LookupGlobalProperty(variable, &lookup, false); | |
4840 | 4840 |
4841 if (type == kUseCell && | 4841 if (type == kUseCell && |
4842 current_info()->global_object()->IsAccessCheckNeeded()) { | 4842 current_info()->global_object()->IsAccessCheckNeeded()) { |
4843 type = kUseGeneric; | 4843 type = kUseGeneric; |
4844 } | 4844 } |
4845 | 4845 |
4846 if (type == kUseCell) { | 4846 if (type == kUseCell) { |
4847 Handle<GlobalObject> global(current_info()->global_object()); | 4847 Handle<GlobalObject> global(current_info()->global_object()); |
4848 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 4848 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
4849 if (cell->type()->IsConstant()) { | 4849 if (cell->type()->IsConstant()) { |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5744 BailoutId ast_id, | 5744 BailoutId ast_id, |
5745 BailoutId return_id, | 5745 BailoutId return_id, |
5746 bool is_uninitialized) { | 5746 bool is_uninitialized) { |
5747 if (!prop->key()->IsPropertyName()) { | 5747 if (!prop->key()->IsPropertyName()) { |
5748 // Keyed store. | 5748 // Keyed store. |
5749 HValue* value = environment()->ExpressionStackAt(0); | 5749 HValue* value = environment()->ExpressionStackAt(0); |
5750 HValue* key = environment()->ExpressionStackAt(1); | 5750 HValue* key = environment()->ExpressionStackAt(1); |
5751 HValue* object = environment()->ExpressionStackAt(2); | 5751 HValue* object = environment()->ExpressionStackAt(2); |
5752 bool has_side_effects = false; | 5752 bool has_side_effects = false; |
5753 HandleKeyedElementAccess(object, key, value, expr, | 5753 HandleKeyedElementAccess(object, key, value, expr, |
5754 true, // is_store | 5754 STORE, &has_side_effects); |
5755 &has_side_effects); | |
5756 Drop(3); | 5755 Drop(3); |
5757 Push(value); | 5756 Push(value); |
5758 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); | 5757 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
5759 return ast_context()->ReturnValue(Pop()); | 5758 return ast_context()->ReturnValue(Pop()); |
5760 } | 5759 } |
5761 | 5760 |
5762 // Named store. | 5761 // Named store. |
5763 HValue* value = Pop(); | 5762 HValue* value = Pop(); |
5764 HValue* object = Pop(); | 5763 HValue* object = Pop(); |
5765 | 5764 |
(...skipping 29 matching lines...) Expand all Loading... |
5795 | 5794 |
5796 | 5795 |
5797 // Because not every expression has a position and there is not common | 5796 // Because not every expression has a position and there is not common |
5798 // superclass of Assignment and CountOperation, we cannot just pass the | 5797 // superclass of Assignment and CountOperation, we cannot just pass the |
5799 // owning expression instead of position and ast_id separately. | 5798 // owning expression instead of position and ast_id separately. |
5800 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | 5799 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
5801 Variable* var, | 5800 Variable* var, |
5802 HValue* value, | 5801 HValue* value, |
5803 BailoutId ast_id) { | 5802 BailoutId ast_id) { |
5804 LookupResult lookup(isolate()); | 5803 LookupResult lookup(isolate()); |
5805 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 5804 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE); |
5806 if (type == kUseCell) { | 5805 if (type == kUseCell) { |
5807 Handle<GlobalObject> global(current_info()->global_object()); | 5806 Handle<GlobalObject> global(current_info()->global_object()); |
5808 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | 5807 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
5809 if (cell->type()->IsConstant()) { | 5808 if (cell->type()->IsConstant()) { |
5810 IfBuilder builder(this); | 5809 IfBuilder builder(this); |
5811 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | 5810 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
5812 if (cell->type()->AsConstant()->IsNumber()) { | 5811 if (cell->type()->AsConstant()->IsNumber()) { |
5813 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | 5812 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
5814 } else { | 5813 } else { |
5815 builder.If<HCompareObjectEqAndBranch>(value, constant); | 5814 builder.If<HCompareObjectEqAndBranch>(value, constant); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6189 return load_mode; | 6188 return load_mode; |
6190 } | 6189 } |
6191 | 6190 |
6192 | 6191 |
6193 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( | 6192 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess( |
6194 HValue* object, | 6193 HValue* object, |
6195 HValue* key, | 6194 HValue* key, |
6196 HValue* val, | 6195 HValue* val, |
6197 HValue* dependency, | 6196 HValue* dependency, |
6198 Handle<Map> map, | 6197 Handle<Map> map, |
6199 bool is_store, | 6198 PropertyAccessType access_type, |
6200 KeyedAccessStoreMode store_mode) { | 6199 KeyedAccessStoreMode store_mode) { |
6201 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), | 6200 HCheckMaps* checked_object = Add<HCheckMaps>(object, map, top_info(), |
6202 dependency); | 6201 dependency); |
6203 if (dependency) { | 6202 if (dependency) { |
6204 checked_object->ClearGVNFlag(kDependsOnElementsKind); | 6203 checked_object->ClearGVNFlag(kDependsOnElementsKind); |
6205 } | 6204 } |
6206 | 6205 |
6207 if (is_store && map->prototype()->IsJSObject()) { | 6206 if (access_type == STORE && map->prototype()->IsJSObject()) { |
6208 // monomorphic stores need a prototype chain check because shape | 6207 // monomorphic stores need a prototype chain check because shape |
6209 // changes could allow callbacks on elements in the chain that | 6208 // changes could allow callbacks on elements in the chain that |
6210 // aren't compatible with monomorphic keyed stores. | 6209 // aren't compatible with monomorphic keyed stores. |
6211 Handle<JSObject> prototype(JSObject::cast(map->prototype())); | 6210 Handle<JSObject> prototype(JSObject::cast(map->prototype())); |
6212 Object* holder = map->prototype(); | 6211 Object* holder = map->prototype(); |
6213 while (holder->GetPrototype(isolate())->IsJSObject()) { | 6212 while (holder->GetPrototype(isolate())->IsJSObject()) { |
6214 holder = holder->GetPrototype(isolate()); | 6213 holder = holder->GetPrototype(isolate()); |
6215 } | 6214 } |
6216 ASSERT(holder->GetPrototype(isolate())->IsNull()); | 6215 ASSERT(holder->GetPrototype(isolate())->IsNull()); |
6217 | 6216 |
6218 BuildCheckPrototypeMaps(prototype, | 6217 BuildCheckPrototypeMaps(prototype, |
6219 Handle<JSObject>(JSObject::cast(holder))); | 6218 Handle<JSObject>(JSObject::cast(holder))); |
6220 } | 6219 } |
6221 | 6220 |
6222 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 6221 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
6223 return BuildUncheckedMonomorphicElementAccess( | 6222 return BuildUncheckedMonomorphicElementAccess( |
6224 checked_object, key, val, | 6223 checked_object, key, val, |
6225 map->instance_type() == JS_ARRAY_TYPE, | 6224 map->instance_type() == JS_ARRAY_TYPE, |
6226 map->elements_kind(), is_store, | 6225 map->elements_kind(), access_type, |
6227 load_mode, store_mode); | 6226 load_mode, store_mode); |
6228 } | 6227 } |
6229 | 6228 |
6230 | 6229 |
6231 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( | 6230 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad( |
6232 HValue* object, | 6231 HValue* object, |
6233 HValue* key, | 6232 HValue* key, |
6234 HValue* val, | 6233 HValue* val, |
6235 SmallMapList* maps) { | 6234 SmallMapList* maps) { |
6236 // For polymorphic loads of similar elements kinds (i.e. all tagged or all | 6235 // For polymorphic loads of similar elements kinds (i.e. all tagged or all |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6282 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps); | 6281 HCheckMaps* checked_object = Add<HCheckMaps>(object, maps); |
6283 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. | 6282 // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS. |
6284 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. | 6283 // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS. |
6285 ElementsKind consolidated_elements_kind = has_seen_holey_elements | 6284 ElementsKind consolidated_elements_kind = has_seen_holey_elements |
6286 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) | 6285 ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind()) |
6287 : most_general_consolidated_map->elements_kind(); | 6286 : most_general_consolidated_map->elements_kind(); |
6288 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( | 6287 HInstruction* instr = BuildUncheckedMonomorphicElementAccess( |
6289 checked_object, key, val, | 6288 checked_object, key, val, |
6290 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, | 6289 most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE, |
6291 consolidated_elements_kind, | 6290 consolidated_elements_kind, |
6292 false, NEVER_RETURN_HOLE, STANDARD_STORE); | 6291 LOAD, NEVER_RETURN_HOLE, STANDARD_STORE); |
6293 return instr; | 6292 return instr; |
6294 } | 6293 } |
6295 | 6294 |
6296 | 6295 |
6297 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( | 6296 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess( |
6298 HValue* object, | 6297 HValue* object, |
6299 HValue* key, | 6298 HValue* key, |
6300 HValue* val, | 6299 HValue* val, |
6301 SmallMapList* maps, | 6300 SmallMapList* maps, |
6302 bool is_store, | 6301 PropertyAccessType access_type, |
6303 KeyedAccessStoreMode store_mode, | 6302 KeyedAccessStoreMode store_mode, |
6304 bool* has_side_effects) { | 6303 bool* has_side_effects) { |
6305 *has_side_effects = false; | 6304 *has_side_effects = false; |
6306 BuildCheckHeapObject(object); | 6305 BuildCheckHeapObject(object); |
6307 | 6306 |
6308 if (!is_store) { | 6307 if (access_type == LOAD) { |
6309 HInstruction* consolidated_load = | 6308 HInstruction* consolidated_load = |
6310 TryBuildConsolidatedElementLoad(object, key, val, maps); | 6309 TryBuildConsolidatedElementLoad(object, key, val, maps); |
6311 if (consolidated_load != NULL) { | 6310 if (consolidated_load != NULL) { |
6312 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 6311 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
6313 return consolidated_load; | 6312 return consolidated_load; |
6314 } | 6313 } |
6315 } | 6314 } |
6316 | 6315 |
6317 // Elements_kind transition support. | 6316 // Elements_kind transition support. |
6318 MapHandleList transition_target(maps->length()); | 6317 MapHandleList transition_target(maps->length()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6351 } | 6350 } |
6352 | 6351 |
6353 // If only one map is left after transitioning, handle this case | 6352 // If only one map is left after transitioning, handle this case |
6354 // monomorphically. | 6353 // monomorphically. |
6355 ASSERT(untransitionable_maps.length() >= 1); | 6354 ASSERT(untransitionable_maps.length() >= 1); |
6356 if (untransitionable_maps.length() == 1) { | 6355 if (untransitionable_maps.length() == 1) { |
6357 Handle<Map> untransitionable_map = untransitionable_maps[0]; | 6356 Handle<Map> untransitionable_map = untransitionable_maps[0]; |
6358 HInstruction* instr = NULL; | 6357 HInstruction* instr = NULL; |
6359 if (untransitionable_map->has_slow_elements_kind() || | 6358 if (untransitionable_map->has_slow_elements_kind() || |
6360 !untransitionable_map->IsJSObjectMap()) { | 6359 !untransitionable_map->IsJSObjectMap()) { |
6361 instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) | 6360 instr = AddInstruction(access_type == STORE |
6362 : BuildLoadKeyedGeneric(object, key)); | 6361 ? BuildStoreKeyedGeneric(object, key, val) |
| 6362 : BuildLoadKeyedGeneric(object, key)); |
6363 } else { | 6363 } else { |
6364 instr = BuildMonomorphicElementAccess( | 6364 instr = BuildMonomorphicElementAccess( |
6365 object, key, val, transition, untransitionable_map, is_store, | 6365 object, key, val, transition, untransitionable_map, access_type, |
6366 store_mode); | 6366 store_mode); |
6367 } | 6367 } |
6368 *has_side_effects |= instr->HasObservableSideEffects(); | 6368 *has_side_effects |= instr->HasObservableSideEffects(); |
6369 return is_store ? NULL : instr; | 6369 return access_type == STORE ? NULL : instr; |
6370 } | 6370 } |
6371 | 6371 |
6372 HBasicBlock* join = graph()->CreateBasicBlock(); | 6372 HBasicBlock* join = graph()->CreateBasicBlock(); |
6373 | 6373 |
6374 for (int i = 0; i < untransitionable_maps.length(); ++i) { | 6374 for (int i = 0; i < untransitionable_maps.length(); ++i) { |
6375 Handle<Map> map = untransitionable_maps[i]; | 6375 Handle<Map> map = untransitionable_maps[i]; |
6376 if (!map->IsJSObjectMap()) continue; | 6376 if (!map->IsJSObjectMap()) continue; |
6377 ElementsKind elements_kind = map->elements_kind(); | 6377 ElementsKind elements_kind = map->elements_kind(); |
6378 HBasicBlock* this_map = graph()->CreateBasicBlock(); | 6378 HBasicBlock* this_map = graph()->CreateBasicBlock(); |
6379 HBasicBlock* other_map = graph()->CreateBasicBlock(); | 6379 HBasicBlock* other_map = graph()->CreateBasicBlock(); |
6380 HCompareMap* mapcompare = | 6380 HCompareMap* mapcompare = |
6381 New<HCompareMap>(object, map, this_map, other_map); | 6381 New<HCompareMap>(object, map, this_map, other_map); |
6382 FinishCurrentBlock(mapcompare); | 6382 FinishCurrentBlock(mapcompare); |
6383 | 6383 |
6384 set_current_block(this_map); | 6384 set_current_block(this_map); |
6385 HInstruction* access = NULL; | 6385 HInstruction* access = NULL; |
6386 if (IsDictionaryElementsKind(elements_kind)) { | 6386 if (IsDictionaryElementsKind(elements_kind)) { |
6387 access = is_store | 6387 access = access_type == STORE |
6388 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) | 6388 ? AddInstruction(BuildStoreKeyedGeneric(object, key, val)) |
6389 : AddInstruction(BuildLoadKeyedGeneric(object, key)); | 6389 : AddInstruction(BuildLoadKeyedGeneric(object, key)); |
6390 } else { | 6390 } else { |
6391 ASSERT(IsFastElementsKind(elements_kind) || | 6391 ASSERT(IsFastElementsKind(elements_kind) || |
6392 IsExternalArrayElementsKind(elements_kind)); | 6392 IsExternalArrayElementsKind(elements_kind)); |
6393 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); | 6393 LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map); |
6394 // Happily, mapcompare is a checked object. | 6394 // Happily, mapcompare is a checked object. |
6395 access = BuildUncheckedMonomorphicElementAccess( | 6395 access = BuildUncheckedMonomorphicElementAccess( |
6396 mapcompare, key, val, | 6396 mapcompare, key, val, |
6397 map->instance_type() == JS_ARRAY_TYPE, | 6397 map->instance_type() == JS_ARRAY_TYPE, |
6398 elements_kind, is_store, | 6398 elements_kind, access_type, |
6399 load_mode, | 6399 load_mode, |
6400 store_mode); | 6400 store_mode); |
6401 } | 6401 } |
6402 *has_side_effects |= access->HasObservableSideEffects(); | 6402 *has_side_effects |= access->HasObservableSideEffects(); |
6403 // The caller will use has_side_effects and add a correct Simulate. | 6403 // The caller will use has_side_effects and add a correct Simulate. |
6404 access->SetFlag(HValue::kHasNoObservableSideEffects); | 6404 access->SetFlag(HValue::kHasNoObservableSideEffects); |
6405 if (!is_store) { | 6405 if (access_type == LOAD) { |
6406 Push(access); | 6406 Push(access); |
6407 } | 6407 } |
6408 NoObservableSideEffectsScope scope(this); | 6408 NoObservableSideEffectsScope scope(this); |
6409 GotoNoSimulate(join); | 6409 GotoNoSimulate(join); |
6410 set_current_block(other_map); | 6410 set_current_block(other_map); |
6411 } | 6411 } |
6412 | 6412 |
6413 // Deopt if none of the cases matched. | 6413 // Deopt if none of the cases matched. |
6414 NoObservableSideEffectsScope scope(this); | 6414 NoObservableSideEffectsScope scope(this); |
6415 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", | 6415 FinishExitWithHardDeoptimization("Unknown map in polymorphic element access", |
6416 join); | 6416 join); |
6417 set_current_block(join); | 6417 set_current_block(join); |
6418 return is_store ? NULL : Pop(); | 6418 return access_type == STORE ? NULL : Pop(); |
6419 } | 6419 } |
6420 | 6420 |
6421 | 6421 |
6422 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 6422 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
6423 HValue* obj, | 6423 HValue* obj, |
6424 HValue* key, | 6424 HValue* key, |
6425 HValue* val, | 6425 HValue* val, |
6426 Expression* expr, | 6426 Expression* expr, |
6427 bool is_store, | 6427 PropertyAccessType access_type, |
6428 bool* has_side_effects) { | 6428 bool* has_side_effects) { |
6429 ASSERT(!expr->IsPropertyName()); | 6429 ASSERT(!expr->IsPropertyName()); |
6430 HInstruction* instr = NULL; | 6430 HInstruction* instr = NULL; |
6431 | 6431 |
6432 SmallMapList* types; | 6432 SmallMapList* types; |
6433 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); | 6433 bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone()); |
6434 | 6434 |
6435 bool force_generic = false; | 6435 bool force_generic = false; |
6436 if (is_store && (monomorphic || (types != NULL && !types->is_empty()))) { | 6436 if (access_type == STORE && |
| 6437 (monomorphic || (types != NULL && !types->is_empty()))) { |
6437 // Stores can't be mono/polymorphic if their prototype chain has dictionary | 6438 // Stores can't be mono/polymorphic if their prototype chain has dictionary |
6438 // elements. However a receiver map that has dictionary elements itself | 6439 // elements. However a receiver map that has dictionary elements itself |
6439 // should be left to normal mono/poly behavior (the other maps may benefit | 6440 // should be left to normal mono/poly behavior (the other maps may benefit |
6440 // from highly optimized stores). | 6441 // from highly optimized stores). |
6441 for (int i = 0; i < types->length(); i++) { | 6442 for (int i = 0; i < types->length(); i++) { |
6442 Handle<Map> current_map = types->at(i); | 6443 Handle<Map> current_map = types->at(i); |
6443 if (current_map->DictionaryElementsInPrototypeChainOnly()) { | 6444 if (current_map->DictionaryElementsInPrototypeChainOnly()) { |
6444 force_generic = true; | 6445 force_generic = true; |
6445 monomorphic = false; | 6446 monomorphic = false; |
6446 break; | 6447 break; |
6447 } | 6448 } |
6448 } | 6449 } |
6449 } | 6450 } |
6450 | 6451 |
6451 if (monomorphic) { | 6452 if (monomorphic) { |
6452 Handle<Map> map = types->first(); | 6453 Handle<Map> map = types->first(); |
6453 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { | 6454 if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) { |
6454 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 6455 instr = access_type == STORE |
6455 : BuildLoadKeyedGeneric(obj, key); | 6456 ? BuildStoreKeyedGeneric(obj, key, val) |
| 6457 : BuildLoadKeyedGeneric(obj, key); |
6456 AddInstruction(instr); | 6458 AddInstruction(instr); |
6457 } else { | 6459 } else { |
6458 BuildCheckHeapObject(obj); | 6460 BuildCheckHeapObject(obj); |
6459 instr = BuildMonomorphicElementAccess( | 6461 instr = BuildMonomorphicElementAccess( |
6460 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 6462 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
6461 } | 6463 } |
6462 } else if (!force_generic && (types != NULL && !types->is_empty())) { | 6464 } else if (!force_generic && (types != NULL && !types->is_empty())) { |
6463 return HandlePolymorphicElementAccess( | 6465 return HandlePolymorphicElementAccess( |
6464 obj, key, val, types, is_store, | 6466 obj, key, val, types, access_type, |
6465 expr->GetStoreMode(), has_side_effects); | 6467 expr->GetStoreMode(), has_side_effects); |
6466 } else { | 6468 } else { |
6467 if (is_store) { | 6469 if (access_type == STORE) { |
6468 if (expr->IsAssignment() && | 6470 if (expr->IsAssignment() && |
6469 expr->AsAssignment()->HasNoTypeInformation()) { | 6471 expr->AsAssignment()->HasNoTypeInformation()) { |
6470 Add<HDeoptimize>("Insufficient type feedback for keyed store", | 6472 Add<HDeoptimize>("Insufficient type feedback for keyed store", |
6471 Deoptimizer::SOFT); | 6473 Deoptimizer::SOFT); |
6472 } | 6474 } |
6473 instr = BuildStoreKeyedGeneric(obj, key, val); | 6475 instr = BuildStoreKeyedGeneric(obj, key, val); |
6474 } else { | 6476 } else { |
6475 if (expr->AsProperty()->HasNoTypeInformation()) { | 6477 if (expr->AsProperty()->HasNoTypeInformation()) { |
6476 Add<HDeoptimize>("Insufficient type feedback for keyed load", | 6478 Add<HDeoptimize>("Insufficient type feedback for keyed load", |
6477 Deoptimizer::SOFT); | 6479 Deoptimizer::SOFT); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6646 object, name, NULL, expr->IsUninitialized()); | 6648 object, name, NULL, expr->IsUninitialized()); |
6647 if (instr == NULL) return; | 6649 if (instr == NULL) return; |
6648 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 6650 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
6649 | 6651 |
6650 } else { | 6652 } else { |
6651 HValue* key = Pop(); | 6653 HValue* key = Pop(); |
6652 HValue* obj = Pop(); | 6654 HValue* obj = Pop(); |
6653 | 6655 |
6654 bool has_side_effects = false; | 6656 bool has_side_effects = false; |
6655 HValue* load = HandleKeyedElementAccess( | 6657 HValue* load = HandleKeyedElementAccess( |
6656 obj, key, NULL, expr, | 6658 obj, key, NULL, expr, LOAD, &has_side_effects); |
6657 false, // is_store | |
6658 &has_side_effects); | |
6659 if (has_side_effects) { | 6659 if (has_side_effects) { |
6660 if (ast_context()->IsEffect()) { | 6660 if (ast_context()->IsEffect()) { |
6661 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6661 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6662 } else { | 6662 } else { |
6663 Push(load); | 6663 Push(load); |
6664 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6664 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
6665 Drop(1); | 6665 Drop(1); |
6666 } | 6666 } |
6667 } | 6667 } |
6668 return ast_context()->ReturnValue(load); | 6668 return ast_context()->ReturnValue(load); |
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7577 | 7577 |
7578 length_checker.Else(); | 7578 length_checker.Else(); |
7579 HValue* elements = AddLoadElements(checked_object); | 7579 HValue* elements = AddLoadElements(checked_object); |
7580 // Ensure that we aren't popping from a copy-on-write array. | 7580 // Ensure that we aren't popping from a copy-on-write array. |
7581 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 7581 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
7582 elements = BuildCopyElementsOnWrite(checked_object, elements, | 7582 elements = BuildCopyElementsOnWrite(checked_object, elements, |
7583 elements_kind, length); | 7583 elements_kind, length); |
7584 } | 7584 } |
7585 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1()); | 7585 reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1()); |
7586 result = AddElementAccess(elements, reduced_length, NULL, | 7586 result = AddElementAccess(elements, reduced_length, NULL, |
7587 bounds_check, elements_kind, false); | 7587 bounds_check, elements_kind, LOAD); |
7588 Factory* factory = isolate()->factory(); | 7588 Factory* factory = isolate()->factory(); |
7589 double nan_double = FixedDoubleArray::hole_nan_as_double(); | 7589 double nan_double = FixedDoubleArray::hole_nan_as_double(); |
7590 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) | 7590 HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind) |
7591 ? Add<HConstant>(factory->the_hole_value()) | 7591 ? Add<HConstant>(factory->the_hole_value()) |
7592 : Add<HConstant>(nan_double); | 7592 : Add<HConstant>(nan_double); |
7593 if (IsFastSmiOrObjectElementsKind(elements_kind)) { | 7593 if (IsFastSmiOrObjectElementsKind(elements_kind)) { |
7594 elements_kind = FAST_HOLEY_ELEMENTS; | 7594 elements_kind = FAST_HOLEY_ELEMENTS; |
7595 } | 7595 } |
7596 AddElementAccess( | 7596 AddElementAccess( |
7597 elements, reduced_length, hole, bounds_check, elements_kind, true); | 7597 elements, reduced_length, hole, bounds_check, elements_kind, STORE); |
7598 Add<HStoreNamedField>( | 7598 Add<HStoreNamedField>( |
7599 checked_object, HObjectAccess::ForArrayLength(elements_kind), | 7599 checked_object, HObjectAccess::ForArrayLength(elements_kind), |
7600 reduced_length, STORE_TO_INITIALIZED_ENTRY); | 7600 reduced_length, STORE_TO_INITIALIZED_ENTRY); |
7601 | 7601 |
7602 if (!ast_context()->IsEffect()) Push(result); | 7602 if (!ast_context()->IsEffect()) Push(result); |
7603 | 7603 |
7604 length_checker.End(); | 7604 length_checker.End(); |
7605 } | 7605 } |
7606 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 7606 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
7607 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 7607 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8003 } | 8003 } |
8004 | 8004 |
8005 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 8005 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
8006 if (global_call) { | 8006 if (global_call) { |
8007 Variable* var = proxy->var(); | 8007 Variable* var = proxy->var(); |
8008 bool known_global_function = false; | 8008 bool known_global_function = false; |
8009 // If there is a global property cell for the name at compile time and | 8009 // If there is a global property cell for the name at compile time and |
8010 // access check is not enabled we assume that the function will not change | 8010 // access check is not enabled we assume that the function will not change |
8011 // and generate optimized code for calling the function. | 8011 // and generate optimized code for calling the function. |
8012 LookupResult lookup(isolate()); | 8012 LookupResult lookup(isolate()); |
8013 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 8013 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD); |
8014 if (type == kUseCell && | 8014 if (type == kUseCell && |
8015 !current_info()->global_object()->IsAccessCheckNeeded()) { | 8015 !current_info()->global_object()->IsAccessCheckNeeded()) { |
8016 Handle<GlobalObject> global(current_info()->global_object()); | 8016 Handle<GlobalObject> global(current_info()->global_object()); |
8017 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 8017 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
8018 } | 8018 } |
8019 CHECK_ALIVE(VisitForValue(expr->expression())); | 8019 CHECK_ALIVE(VisitForValue(expr->expression())); |
8020 HValue* function = Top(); | 8020 HValue* function = Top(); |
8021 if (known_global_function) { | 8021 if (known_global_function) { |
8022 Add<HCheckValue>(function, expr->target()); | 8022 Add<HCheckValue>(function, expr->target()); |
8023 | 8023 |
(...skipping 3184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11208 if (ShouldProduceTraceOutput()) { | 11208 if (ShouldProduceTraceOutput()) { |
11209 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11209 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11210 } | 11210 } |
11211 | 11211 |
11212 #ifdef DEBUG | 11212 #ifdef DEBUG |
11213 graph_->Verify(false); // No full verify. | 11213 graph_->Verify(false); // No full verify. |
11214 #endif | 11214 #endif |
11215 } | 11215 } |
11216 | 11216 |
11217 } } // namespace v8::internal | 11217 } } // namespace v8::internal |
OLD | NEW |