| 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 |