| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/v8.h" | 9 #include "src/v8.h" |
| 10 | 10 |
| (...skipping 2416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2427 IsFixedTypedArrayElementsKind(elements_kind)) { | 2427 IsFixedTypedArrayElementsKind(elements_kind)) { |
| 2428 HValue* backing_store; | 2428 HValue* backing_store; |
| 2429 if (IsExternalArrayElementsKind(elements_kind)) { | 2429 if (IsExternalArrayElementsKind(elements_kind)) { |
| 2430 backing_store = Add<HLoadNamedField>( | 2430 backing_store = Add<HLoadNamedField>( |
| 2431 elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer()); | 2431 elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer()); |
| 2432 } else { | 2432 } else { |
| 2433 backing_store = elements; | 2433 backing_store = elements; |
| 2434 } | 2434 } |
| 2435 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 2435 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 2436 NoObservableSideEffectsScope no_effects(this); | 2436 NoObservableSideEffectsScope no_effects(this); |
| 2437 if (IsExternalArrayElementsKind(elements_kind)) { |
| 2438 HInstruction* buffer = |
| 2439 Add<HLoadNamedField>(checked_object, nullptr, |
| 2440 HObjectAccess::ForJSArrayBufferViewBuffer()); |
| 2441 HInstruction* flags = Add<HLoadNamedField>( |
| 2442 buffer, nullptr, HObjectAccess::ForJSArrayBufferFlag()); |
| 2443 HValue* was_neutered_mask = |
| 2444 Add<HConstant>(1 << JSArrayBuffer::kWasNeuteredBit); |
| 2445 HValue* was_neutered_test = |
| 2446 AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask); |
| 2447 |
| 2448 IfBuilder if_was_neutered(this); |
| 2449 if_was_neutered.If<HCompareNumericAndBranch>( |
| 2450 was_neutered_test, graph()->GetConstant0(), Token::NE); |
| 2451 if_was_neutered.ThenDeopt(Deoptimizer::kOutOfBounds); |
| 2452 if_was_neutered.End(); |
| 2453 } |
| 2437 IfBuilder length_checker(this); | 2454 IfBuilder length_checker(this); |
| 2438 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2455 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 2439 length_checker.Then(); | 2456 length_checker.Then(); |
| 2440 IfBuilder negative_checker(this); | 2457 IfBuilder negative_checker(this); |
| 2441 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2458 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
| 2442 key, graph()->GetConstant0(), Token::GTE); | 2459 key, graph()->GetConstant0(), Token::GTE); |
| 2443 negative_checker.Then(); | 2460 negative_checker.Then(); |
| 2444 HInstruction* result = AddElementAccess( | 2461 HInstruction* result = AddElementAccess( |
| 2445 backing_store, key, val, bounds_check, elements_kind, access_type); | 2462 backing_store, key, val, bounds_check, elements_kind, access_type); |
| 2446 negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered); | 2463 negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered); |
| 2447 negative_checker.End(); | 2464 negative_checker.End(); |
| 2448 length_checker.End(); | 2465 length_checker.End(); |
| 2449 return result; | 2466 return result; |
| 2450 } else { | 2467 } else { |
| 2468 if (IsExternalArrayElementsKind(elements_kind)) { |
| 2469 HInstruction* buffer = |
| 2470 Add<HLoadNamedField>(checked_object, nullptr, |
| 2471 HObjectAccess::ForJSArrayBufferViewBuffer()); |
| 2472 HInstruction* buffer_length = Add<HLoadNamedField>( |
| 2473 buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength()); |
| 2474 Add<HBoundsCheck>(graph()->GetConstant0(), buffer_length); |
| 2475 } |
| 2451 DCHECK(store_mode == STANDARD_STORE); | 2476 DCHECK(store_mode == STANDARD_STORE); |
| 2452 checked_key = Add<HBoundsCheck>(key, length); | 2477 checked_key = Add<HBoundsCheck>(key, length); |
| 2453 return AddElementAccess( | 2478 return AddElementAccess( |
| 2454 backing_store, checked_key, val, | 2479 backing_store, checked_key, val, |
| 2455 checked_object, elements_kind, access_type); | 2480 checked_object, elements_kind, access_type); |
| 2456 } | 2481 } |
| 2457 } | 2482 } |
| 2458 DCHECK(fast_smi_only_elements || | 2483 DCHECK(fast_smi_only_elements || |
| 2459 fast_elements || | 2484 fast_elements || |
| 2460 IsFastDoubleElementsKind(elements_kind)); | 2485 IsFastDoubleElementsKind(elements_kind)); |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3148 | 3173 |
| 3149 | 3174 |
| 3150 HInstruction* HGraphBuilder::BuildGetArrayFunction() { | 3175 HInstruction* HGraphBuilder::BuildGetArrayFunction() { |
| 3151 HInstruction* native_context = BuildGetNativeContext(); | 3176 HInstruction* native_context = BuildGetNativeContext(); |
| 3152 HInstruction* index = | 3177 HInstruction* index = |
| 3153 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); | 3178 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); |
| 3154 return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS); | 3179 return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS); |
| 3155 } | 3180 } |
| 3156 | 3181 |
| 3157 | 3182 |
| 3183 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object, |
| 3184 HValue* checked_object, |
| 3185 FieldIndex index) { |
| 3186 NoObservableSideEffectsScope scope(this); |
| 3187 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( |
| 3188 index.offset(), Representation::Tagged()); |
| 3189 HInstruction* buffer = Add<HLoadNamedField>( |
| 3190 object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer()); |
| 3191 HInstruction* field = Add<HLoadNamedField>(object, checked_object, access); |
| 3192 |
| 3193 IfBuilder if_has_buffer(this); |
| 3194 HValue* has_buffer = if_has_buffer.IfNot<HIsSmiAndBranch>(buffer); |
| 3195 if_has_buffer.Then(); |
| 3196 { |
| 3197 HInstruction* flags = Add<HLoadNamedField>( |
| 3198 buffer, has_buffer, HObjectAccess::ForJSArrayBufferFlag()); |
| 3199 HValue* was_neutered_mask = |
| 3200 Add<HConstant>(1 << JSArrayBuffer::kWasNeuteredBit); |
| 3201 HValue* was_neutered_test = |
| 3202 AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask); |
| 3203 |
| 3204 IfBuilder if_was_neutered(this); |
| 3205 if_was_neutered.If<HCompareNumericAndBranch>( |
| 3206 was_neutered_test, graph()->GetConstant0(), Token::NE); |
| 3207 if_was_neutered.Then(); |
| 3208 Push(graph()->GetConstant0()); |
| 3209 if_was_neutered.Else(); |
| 3210 Push(field); |
| 3211 if_was_neutered.End(); |
| 3212 } |
| 3213 if_has_buffer.Else(); |
| 3214 Push(field); |
| 3215 if_has_buffer.End(); |
| 3216 |
| 3217 return Pop(); |
| 3218 } |
| 3219 |
| 3220 |
| 3158 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 3221 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 3159 ElementsKind kind, | 3222 ElementsKind kind, |
| 3160 HValue* allocation_site_payload, | 3223 HValue* allocation_site_payload, |
| 3161 HValue* constructor_function, | 3224 HValue* constructor_function, |
| 3162 AllocationSiteOverrideMode override_mode) : | 3225 AllocationSiteOverrideMode override_mode) : |
| 3163 builder_(builder), | 3226 builder_(builder), |
| 3164 kind_(kind), | 3227 kind_(kind), |
| 3165 allocation_site_payload_(allocation_site_payload), | 3228 allocation_site_payload_(allocation_site_payload), |
| 3166 constructor_function_(constructor_function) { | 3229 constructor_function_(constructor_function) { |
| 3167 DCHECK(!allocation_site_payload->IsConstant() || | 3230 DCHECK(!allocation_site_payload->IsConstant() || |
| (...skipping 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5647 Handle<Symbol> sym = isolate()->factory()->home_object_symbol(); | 5710 Handle<Symbol> sym = isolate()->factory()->home_object_symbol(); |
| 5648 HInstruction* store_home = BuildKeyedGeneric( | 5711 HInstruction* store_home = BuildKeyedGeneric( |
| 5649 STORE, NULL, value, Add<HConstant>(sym), literal); | 5712 STORE, NULL, value, Add<HConstant>(sym), literal); |
| 5650 AddInstruction(store_home); | 5713 AddInstruction(store_home); |
| 5651 DCHECK(store_home->HasObservableSideEffects()); | 5714 DCHECK(store_home->HasObservableSideEffects()); |
| 5652 Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE); | 5715 Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE); |
| 5653 } | 5716 } |
| 5654 | 5717 |
| 5655 Handle<Map> map = property->GetReceiverType(); | 5718 Handle<Map> map = property->GetReceiverType(); |
| 5656 Handle<String> name = key->AsPropertyName(); | 5719 Handle<String> name = key->AsPropertyName(); |
| 5657 HInstruction* store; | 5720 HValue* store; |
| 5658 if (map.is_null()) { | 5721 if (map.is_null()) { |
| 5659 // If we don't know the monomorphic type, do a generic store. | 5722 // If we don't know the monomorphic type, do a generic store. |
| 5660 CHECK_ALIVE(store = BuildNamedGeneric( | 5723 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5661 STORE, NULL, literal, name, value)); | 5724 STORE, NULL, literal, name, value)); |
| 5662 } else { | 5725 } else { |
| 5663 PropertyAccessInfo info(this, STORE, map, name); | 5726 PropertyAccessInfo info(this, STORE, map, name); |
| 5664 if (info.CanAccessMonomorphic()) { | 5727 if (info.CanAccessMonomorphic()) { |
| 5665 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5728 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
| 5666 DCHECK(!info.IsAccessorConstant()); | 5729 DCHECK(!info.IsAccessorConstant()); |
| 5667 store = BuildMonomorphicAccess( | 5730 store = BuildMonomorphicAccess( |
| 5668 &info, literal, checked_literal, value, | 5731 &info, literal, checked_literal, value, |
| 5669 BailoutId::None(), BailoutId::None()); | 5732 BailoutId::None(), BailoutId::None()); |
| 5670 } else { | 5733 } else { |
| 5671 CHECK_ALIVE(store = BuildNamedGeneric( | 5734 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5672 STORE, NULL, literal, name, value)); | 5735 STORE, NULL, literal, name, value)); |
| 5673 } | 5736 } |
| 5674 } | 5737 } |
| 5675 AddInstruction(store); | 5738 if (store->IsInstruction()) { |
| 5739 AddInstruction(HInstruction::cast(store)); |
| 5740 } |
| 5676 DCHECK(store->HasObservableSideEffects()); | 5741 DCHECK(store->HasObservableSideEffects()); |
| 5677 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5742 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
| 5678 } else { | 5743 } else { |
| 5679 CHECK_ALIVE(VisitForEffect(value)); | 5744 CHECK_ALIVE(VisitForEffect(value)); |
| 5680 } | 5745 } |
| 5681 break; | 5746 break; |
| 5682 } | 5747 } |
| 5683 // Fall through. | 5748 // Fall through. |
| 5684 case ObjectLiteral::Property::PROTOTYPE: | 5749 case ObjectLiteral::Property::PROTOTYPE: |
| 5685 case ObjectLiteral::Property::SETTER: | 5750 case ObjectLiteral::Property::SETTER: |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6126 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() { | 6191 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() { |
| 6127 InstanceType instance_type = map_->instance_type(); | 6192 InstanceType instance_type = map_->instance_type(); |
| 6128 return instance_type == JS_TYPED_ARRAY_TYPE && | 6193 return instance_type == JS_TYPED_ARRAY_TYPE && |
| 6129 IsSpecialIndex(isolate()->unicode_cache(), *name_); | 6194 IsSpecialIndex(isolate()->unicode_cache(), *name_); |
| 6130 } | 6195 } |
| 6131 | 6196 |
| 6132 | 6197 |
| 6133 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { | 6198 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { |
| 6134 if (!CanInlinePropertyAccess(map_)) return false; | 6199 if (!CanInlinePropertyAccess(map_)) return false; |
| 6135 if (IsJSObjectFieldAccessor()) return IsLoad(); | 6200 if (IsJSObjectFieldAccessor()) return IsLoad(); |
| 6201 if (IsJSArrayBufferViewFieldAccessor()) return IsLoad(); |
| 6136 if (map_->function_with_prototype() && !map_->has_non_instance_prototype() && | 6202 if (map_->function_with_prototype() && !map_->has_non_instance_prototype() && |
| 6137 name_.is_identical_to(isolate()->factory()->prototype_string())) { | 6203 name_.is_identical_to(isolate()->factory()->prototype_string())) { |
| 6138 return IsLoad(); | 6204 return IsLoad(); |
| 6139 } | 6205 } |
| 6140 if (!LookupDescriptor()) return false; | 6206 if (!LookupDescriptor()) return false; |
| 6141 if (IsFound()) return IsLoad() || !IsReadOnly(); | 6207 if (IsFound()) return IsLoad() || !IsReadOnly(); |
| 6142 if (IsIntegerIndexedExotic()) return false; | 6208 if (IsIntegerIndexedExotic()) return false; |
| 6143 if (!LookupInPrototypes()) return false; | 6209 if (!LookupInPrototypes()) return false; |
| 6144 if (IsLoad()) return true; | 6210 if (IsLoad()) return true; |
| 6145 | 6211 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6174 if (GetJSObjectFieldAccess(&access)) { | 6240 if (GetJSObjectFieldAccess(&access)) { |
| 6175 for (int i = 1; i < maps->length(); ++i) { | 6241 for (int i = 1; i < maps->length(); ++i) { |
| 6176 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); | 6242 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
| 6177 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 6243 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
| 6178 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 6244 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
| 6179 if (!access.Equals(test_access)) return false; | 6245 if (!access.Equals(test_access)) return false; |
| 6180 } | 6246 } |
| 6181 return true; | 6247 return true; |
| 6182 } | 6248 } |
| 6183 | 6249 |
| 6250 if (GetJSArrayBufferViewFieldAccess(&access)) { |
| 6251 for (int i = 1; i < maps->length(); ++i) { |
| 6252 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
| 6253 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
| 6254 if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) { |
| 6255 return false; |
| 6256 } |
| 6257 if (!access.Equals(test_access)) return false; |
| 6258 } |
| 6259 return true; |
| 6260 } |
| 6261 |
| 6184 // Currently only handle numbers as a polymorphic case. | 6262 // Currently only handle numbers as a polymorphic case. |
| 6185 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 6263 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 6186 // instruction. | 6264 // instruction. |
| 6187 if (IsNumberType()) return false; | 6265 if (IsNumberType()) return false; |
| 6188 | 6266 |
| 6189 // Multiple maps cannot transition to the same target map. | 6267 // Multiple maps cannot transition to the same target map. |
| 6190 DCHECK(!IsLoad() || !IsTransition()); | 6268 DCHECK(!IsLoad() || !IsTransition()); |
| 6191 if (IsTransition() && maps->length() > 1) return false; | 6269 if (IsTransition() && maps->length() > 1) return false; |
| 6192 | 6270 |
| 6193 for (int i = 1; i < maps->length(); ++i) { | 6271 for (int i = 1; i < maps->length(); ++i) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 6213 !target->shared()->native(); | 6291 !target->shared()->native(); |
| 6214 } | 6292 } |
| 6215 | 6293 |
| 6216 | 6294 |
| 6217 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor( | 6295 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor( |
| 6218 Handle<JSFunction> target) const { | 6296 Handle<JSFunction> target) const { |
| 6219 return NeedsWrapping(map_, target); | 6297 return NeedsWrapping(map_, target); |
| 6220 } | 6298 } |
| 6221 | 6299 |
| 6222 | 6300 |
| 6223 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( | 6301 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess( |
| 6224 PropertyAccessInfo* info, | 6302 PropertyAccessInfo* info, HValue* object, HValue* checked_object, |
| 6225 HValue* object, | 6303 HValue* value, BailoutId ast_id, BailoutId return_id, |
| 6226 HValue* checked_object, | |
| 6227 HValue* value, | |
| 6228 BailoutId ast_id, | |
| 6229 BailoutId return_id, | |
| 6230 bool can_inline_accessor) { | 6304 bool can_inline_accessor) { |
| 6231 | |
| 6232 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6305 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
| 6233 if (info->GetJSObjectFieldAccess(&access)) { | 6306 if (info->GetJSObjectFieldAccess(&access)) { |
| 6234 DCHECK(info->IsLoad()); | 6307 DCHECK(info->IsLoad()); |
| 6235 return New<HLoadNamedField>(object, checked_object, access); | 6308 return New<HLoadNamedField>(object, checked_object, access); |
| 6236 } | 6309 } |
| 6237 | 6310 |
| 6311 if (info->GetJSArrayBufferViewFieldAccess(&access)) { |
| 6312 DCHECK(info->IsLoad()); |
| 6313 return BuildArrayBufferViewFieldAccessor( |
| 6314 object, checked_object, FieldIndex::ForInObjectOffset(access.offset())); |
| 6315 } |
| 6316 |
| 6238 if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && | 6317 if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && |
| 6239 info->map()->function_with_prototype()) { | 6318 info->map()->function_with_prototype()) { |
| 6240 DCHECK(!info->map()->has_non_instance_prototype()); | 6319 DCHECK(!info->map()->has_non_instance_prototype()); |
| 6241 return New<HLoadFunctionPrototype>(checked_object); | 6320 return New<HLoadFunctionPrototype>(checked_object); |
| 6242 } | 6321 } |
| 6243 | 6322 |
| 6244 HValue* checked_holder = checked_object; | 6323 HValue* checked_holder = checked_object; |
| 6245 if (info->has_holder()) { | 6324 if (info->has_holder()) { |
| 6246 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 6325 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
| 6247 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 6326 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6377 } | 6456 } |
| 6378 FinishCurrentBlock(compare); | 6457 FinishCurrentBlock(compare); |
| 6379 | 6458 |
| 6380 if (info.IsNumberType()) { | 6459 if (info.IsNumberType()) { |
| 6381 GotoNoSimulate(if_true, number_block); | 6460 GotoNoSimulate(if_true, number_block); |
| 6382 if_true = number_block; | 6461 if_true = number_block; |
| 6383 } | 6462 } |
| 6384 | 6463 |
| 6385 set_current_block(if_true); | 6464 set_current_block(if_true); |
| 6386 | 6465 |
| 6387 HInstruction* access = BuildMonomorphicAccess( | 6466 HValue* access = |
| 6388 &info, object, dependency, value, ast_id, | 6467 BuildMonomorphicAccess(&info, object, dependency, value, ast_id, |
| 6389 return_id, FLAG_polymorphic_inlining); | 6468 return_id, FLAG_polymorphic_inlining); |
| 6390 | 6469 |
| 6391 HValue* result = NULL; | 6470 HValue* result = NULL; |
| 6392 switch (access_type) { | 6471 switch (access_type) { |
| 6393 case LOAD: | 6472 case LOAD: |
| 6394 result = access; | 6473 result = access; |
| 6395 break; | 6474 break; |
| 6396 case STORE: | 6475 case STORE: |
| 6397 result = value; | 6476 result = value; |
| 6398 break; | 6477 break; |
| 6399 } | 6478 } |
| 6400 | 6479 |
| 6401 if (access == NULL) { | 6480 if (access == NULL) { |
| 6402 if (HasStackOverflow()) return; | 6481 if (HasStackOverflow()) return; |
| 6403 } else { | 6482 } else { |
| 6404 if (!access->IsLinked()) AddInstruction(access); | 6483 if (access->IsInstruction()) { |
| 6484 HInstruction* instr = HInstruction::cast(access); |
| 6485 if (!instr->IsLinked()) AddInstruction(instr); |
| 6486 } |
| 6405 if (!ast_context()->IsEffect()) Push(result); | 6487 if (!ast_context()->IsEffect()) Push(result); |
| 6406 } | 6488 } |
| 6407 | 6489 |
| 6408 if (current_block() != NULL) Goto(join); | 6490 if (current_block() != NULL) Goto(join); |
| 6409 set_current_block(if_false); | 6491 set_current_block(if_false); |
| 6410 } | 6492 } |
| 6411 | 6493 |
| 6412 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6494 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6413 // know about and do not want to handle ones we've never seen. Otherwise | 6495 // know about and do not want to handle ones we've never seen. Otherwise |
| 6414 // use a generic IC. | 6496 // use a generic IC. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6488 } | 6570 } |
| 6489 | 6571 |
| 6490 // Named store. | 6572 // Named store. |
| 6491 HValue* value = Pop(); | 6573 HValue* value = Pop(); |
| 6492 HValue* object = Pop(); | 6574 HValue* object = Pop(); |
| 6493 | 6575 |
| 6494 Literal* key = prop->key()->AsLiteral(); | 6576 Literal* key = prop->key()->AsLiteral(); |
| 6495 Handle<String> name = Handle<String>::cast(key->value()); | 6577 Handle<String> name = Handle<String>::cast(key->value()); |
| 6496 DCHECK(!name.is_null()); | 6578 DCHECK(!name.is_null()); |
| 6497 | 6579 |
| 6498 HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr, | 6580 HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, object, |
| 6499 object, name, value, is_uninitialized); | 6581 name, value, is_uninitialized); |
| 6500 if (instr == NULL) return; | 6582 if (access == NULL) return; |
| 6501 | 6583 |
| 6502 if (!ast_context()->IsEffect()) Push(value); | 6584 if (!ast_context()->IsEffect()) Push(value); |
| 6503 AddInstruction(instr); | 6585 if (access->IsInstruction()) AddInstruction(HInstruction::cast(access)); |
| 6504 if (instr->HasObservableSideEffects()) { | 6586 if (access->HasObservableSideEffects()) { |
| 6505 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6587 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6506 } | 6588 } |
| 6507 if (!ast_context()->IsEffect()) Drop(1); | 6589 if (!ast_context()->IsEffect()) Drop(1); |
| 6508 return ast_context()->ReturnValue(value); | 6590 return ast_context()->ReturnValue(value); |
| 6509 } | 6591 } |
| 6510 | 6592 |
| 6511 | 6593 |
| 6512 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6594 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 6513 Property* prop = expr->target()->AsProperty(); | 6595 Property* prop = expr->target()->AsProperty(); |
| 6514 DCHECK(prop != NULL); | 6596 DCHECK(prop != NULL); |
| (...skipping 735 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7250 if (key->ActualValue()->IsConstant()) { | 7332 if (key->ActualValue()->IsConstant()) { |
| 7251 Handle<Object> constant = | 7333 Handle<Object> constant = |
| 7252 HConstant::cast(key->ActualValue())->handle(isolate()); | 7334 HConstant::cast(key->ActualValue())->handle(isolate()); |
| 7253 uint32_t array_index; | 7335 uint32_t array_index; |
| 7254 if (constant->IsString() && | 7336 if (constant->IsString() && |
| 7255 !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) { | 7337 !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) { |
| 7256 if (!constant->IsUniqueName()) { | 7338 if (!constant->IsUniqueName()) { |
| 7257 constant = isolate()->factory()->InternalizeString( | 7339 constant = isolate()->factory()->InternalizeString( |
| 7258 Handle<String>::cast(constant)); | 7340 Handle<String>::cast(constant)); |
| 7259 } | 7341 } |
| 7260 HInstruction* instr = | 7342 HValue* access = |
| 7261 BuildNamedAccess(access_type, ast_id, return_id, expr, obj, | 7343 BuildNamedAccess(access_type, ast_id, return_id, expr, obj, |
| 7262 Handle<String>::cast(constant), val, false); | 7344 Handle<String>::cast(constant), val, false); |
| 7263 if (instr == NULL || instr->IsLinked()) { | 7345 if (access == NULL || access->IsPhi() || |
| 7346 HInstruction::cast(access)->IsLinked()) { |
| 7264 *has_side_effects = false; | 7347 *has_side_effects = false; |
| 7265 } else { | 7348 } else { |
| 7349 HInstruction* instr = HInstruction::cast(access); |
| 7266 AddInstruction(instr); | 7350 AddInstruction(instr); |
| 7267 *has_side_effects = instr->HasObservableSideEffects(); | 7351 *has_side_effects = instr->HasObservableSideEffects(); |
| 7268 } | 7352 } |
| 7269 return instr; | 7353 return access; |
| 7270 } | 7354 } |
| 7271 } | 7355 } |
| 7272 | 7356 |
| 7273 DCHECK(!expr->IsPropertyName()); | 7357 DCHECK(!expr->IsPropertyName()); |
| 7274 HInstruction* instr = NULL; | 7358 HInstruction* instr = NULL; |
| 7275 | 7359 |
| 7276 SmallMapList* maps; | 7360 SmallMapList* maps; |
| 7277 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone()); | 7361 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone()); |
| 7278 | 7362 |
| 7279 bool force_generic = false; | 7363 bool force_generic = false; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7418 HInstruction* length = Add<HConstant>(argument_count); | 7502 HInstruction* length = Add<HConstant>(argument_count); |
| 7419 HInstruction* checked_key = Add<HBoundsCheck>(key, length); | 7503 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
| 7420 result = New<HAccessArgumentsAt>(elements, length, checked_key); | 7504 result = New<HAccessArgumentsAt>(elements, length, checked_key); |
| 7421 } | 7505 } |
| 7422 } | 7506 } |
| 7423 ast_context()->ReturnInstruction(result, expr->id()); | 7507 ast_context()->ReturnInstruction(result, expr->id()); |
| 7424 return true; | 7508 return true; |
| 7425 } | 7509 } |
| 7426 | 7510 |
| 7427 | 7511 |
| 7428 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( | 7512 HValue* HOptimizedGraphBuilder::BuildNamedAccess( |
| 7429 PropertyAccessType access, | 7513 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, |
| 7430 BailoutId ast_id, | 7514 Expression* expr, HValue* object, Handle<String> name, HValue* value, |
| 7431 BailoutId return_id, | |
| 7432 Expression* expr, | |
| 7433 HValue* object, | |
| 7434 Handle<String> name, | |
| 7435 HValue* value, | |
| 7436 bool is_uninitialized) { | 7515 bool is_uninitialized) { |
| 7437 SmallMapList* maps; | 7516 SmallMapList* maps; |
| 7438 ComputeReceiverTypes(expr, object, &maps, zone()); | 7517 ComputeReceiverTypes(expr, object, &maps, zone()); |
| 7439 DCHECK(maps != NULL); | 7518 DCHECK(maps != NULL); |
| 7440 | 7519 |
| 7441 if (maps->length() > 0) { | 7520 if (maps->length() > 0) { |
| 7442 PropertyAccessInfo info(this, access, maps->first(), name); | 7521 PropertyAccessInfo info(this, access, maps->first(), name); |
| 7443 if (!info.CanAccessAsMonomorphic(maps)) { | 7522 if (!info.CanAccessAsMonomorphic(maps)) { |
| 7444 HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object, | 7523 HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object, |
| 7445 value, maps, name); | 7524 value, maps, name); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7481 HValue* index = Pop(); | 7560 HValue* index = Pop(); |
| 7482 HValue* string = Pop(); | 7561 HValue* string = Pop(); |
| 7483 HInstruction* char_code = BuildStringCharCodeAt(string, index); | 7562 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
| 7484 AddInstruction(char_code); | 7563 AddInstruction(char_code); |
| 7485 instr = NewUncasted<HStringCharFromCode>(char_code); | 7564 instr = NewUncasted<HStringCharFromCode>(char_code); |
| 7486 | 7565 |
| 7487 } else if (expr->key()->IsPropertyName()) { | 7566 } else if (expr->key()->IsPropertyName()) { |
| 7488 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 7567 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 7489 HValue* object = Pop(); | 7568 HValue* object = Pop(); |
| 7490 | 7569 |
| 7491 instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, | 7570 HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, object, |
| 7492 object, name, NULL, expr->IsUninitialized()); | 7571 name, NULL, expr->IsUninitialized()); |
| 7493 if (instr == NULL) return; | 7572 if (value == NULL) return; |
| 7573 if (value->IsPhi()) return ast_context()->ReturnValue(value); |
| 7574 instr = HInstruction::cast(value); |
| 7494 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 7575 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
| 7495 | 7576 |
| 7496 } else { | 7577 } else { |
| 7497 HValue* key = Pop(); | 7578 HValue* key = Pop(); |
| 7498 HValue* obj = Pop(); | 7579 HValue* obj = Pop(); |
| 7499 | 7580 |
| 7500 bool has_side_effects = false; | 7581 bool has_side_effects = false; |
| 7501 HValue* load = HandleKeyedElementAccess( | 7582 HValue* load = HandleKeyedElementAccess( |
| 7502 obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects); | 7583 obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects); |
| 7503 if (has_side_effects) { | 7584 if (has_side_effects) { |
| (...skipping 2113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9617 byte_offset); | 9698 byte_offset); |
| 9618 Add<HStoreNamedField>( | 9699 Add<HStoreNamedField>( |
| 9619 obj, | 9700 obj, |
| 9620 HObjectAccess::ForJSArrayBufferViewByteLength(), | 9701 HObjectAccess::ForJSArrayBufferViewByteLength(), |
| 9621 byte_length); | 9702 byte_length); |
| 9622 | 9703 |
| 9623 if (buffer != NULL) { | 9704 if (buffer != NULL) { |
| 9624 Add<HStoreNamedField>( | 9705 Add<HStoreNamedField>( |
| 9625 obj, | 9706 obj, |
| 9626 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); | 9707 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); |
| 9627 HObjectAccess weak_first_view_access = | |
| 9628 HObjectAccess::ForJSArrayBufferWeakFirstView(); | |
| 9629 Add<HStoreNamedField>( | |
| 9630 obj, HObjectAccess::ForJSArrayBufferViewWeakNext(), | |
| 9631 Add<HLoadNamedField>(buffer, nullptr, weak_first_view_access)); | |
| 9632 Add<HStoreNamedField>(buffer, weak_first_view_access, obj); | |
| 9633 } else { | 9708 } else { |
| 9634 Add<HStoreNamedField>( | 9709 Add<HStoreNamedField>( |
| 9635 obj, | 9710 obj, |
| 9636 HObjectAccess::ForJSArrayBufferViewBuffer(), | 9711 HObjectAccess::ForJSArrayBufferViewBuffer(), |
| 9637 Add<HConstant>(static_cast<int32_t>(0))); | 9712 Add<HConstant>(static_cast<int32_t>(0))); |
| 9638 Add<HStoreNamedField>(obj, | |
| 9639 HObjectAccess::ForJSArrayBufferViewWeakNext(), | |
| 9640 graph()->GetConstantUndefined()); | |
| 9641 } | 9713 } |
| 9642 } | 9714 } |
| 9643 | 9715 |
| 9644 | 9716 |
| 9645 void HOptimizedGraphBuilder::GenerateDataViewInitialize( | 9717 void HOptimizedGraphBuilder::GenerateDataViewInitialize( |
| 9646 CallRuntime* expr) { | 9718 CallRuntime* expr) { |
| 9647 ZoneList<Expression*>* arguments = expr->arguments(); | 9719 ZoneList<Expression*>* arguments = expr->arguments(); |
| 9648 | 9720 |
| 9649 DCHECK(arguments->length()== 4); | 9721 DCHECK(arguments->length()== 4); |
| 9650 CHECK_ALIVE(VisitForValue(arguments->at(0))); | 9722 CHECK_ALIVE(VisitForValue(arguments->at(0))); |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9926 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9998 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 9927 HValue* buffer = Pop(); | 9999 HValue* buffer = Pop(); |
| 9928 HInstruction* result = New<HLoadNamedField>( | 10000 HInstruction* result = New<HLoadNamedField>( |
| 9929 buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength()); | 10001 buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength()); |
| 9930 return ast_context()->ReturnInstruction(result, expr->id()); | 10002 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9931 } | 10003 } |
| 9932 | 10004 |
| 9933 | 10005 |
| 9934 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( | 10006 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( |
| 9935 CallRuntime* expr) { | 10007 CallRuntime* expr) { |
| 10008 NoObservableSideEffectsScope scope(this); |
| 9936 DCHECK(expr->arguments()->length() == 1); | 10009 DCHECK(expr->arguments()->length() == 1); |
| 9937 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 10010 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 9938 HValue* buffer = Pop(); | 10011 HValue* view = Pop(); |
| 9939 HInstruction* result = New<HLoadNamedField>( | 10012 |
| 9940 buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteLength()); | 10013 return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( |
| 9941 return ast_context()->ReturnInstruction(result, expr->id()); | 10014 view, nullptr, |
| 10015 FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset))); |
| 9942 } | 10016 } |
| 9943 | 10017 |
| 9944 | 10018 |
| 9945 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( | 10019 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( |
| 9946 CallRuntime* expr) { | 10020 CallRuntime* expr) { |
| 10021 NoObservableSideEffectsScope scope(this); |
| 9947 DCHECK(expr->arguments()->length() == 1); | 10022 DCHECK(expr->arguments()->length() == 1); |
| 9948 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 10023 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 9949 HValue* buffer = Pop(); | 10024 HValue* view = Pop(); |
| 9950 HInstruction* result = New<HLoadNamedField>( | 10025 |
| 9951 buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteOffset()); | 10026 return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( |
| 9952 return ast_context()->ReturnInstruction(result, expr->id()); | 10027 view, nullptr, |
| 10028 FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset))); |
| 9953 } | 10029 } |
| 9954 | 10030 |
| 9955 | 10031 |
| 9956 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( | 10032 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( |
| 9957 CallRuntime* expr) { | 10033 CallRuntime* expr) { |
| 10034 NoObservableSideEffectsScope scope(this); |
| 9958 DCHECK(expr->arguments()->length() == 1); | 10035 DCHECK(expr->arguments()->length() == 1); |
| 9959 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 10036 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 9960 HValue* buffer = Pop(); | 10037 HValue* view = Pop(); |
| 9961 HInstruction* result = New<HLoadNamedField>( | 10038 |
| 9962 buffer, nullptr, HObjectAccess::ForJSTypedArrayLength()); | 10039 return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( |
| 9963 return ast_context()->ReturnInstruction(result, expr->id()); | 10040 view, nullptr, |
| 10041 FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset))); |
| 9964 } | 10042 } |
| 9965 | 10043 |
| 9966 | 10044 |
| 9967 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 10045 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 9968 DCHECK(!HasStackOverflow()); | 10046 DCHECK(!HasStackOverflow()); |
| 9969 DCHECK(current_block() != NULL); | 10047 DCHECK(current_block() != NULL); |
| 9970 DCHECK(current_block()->HasPredecessor()); | 10048 DCHECK(current_block()->HasPredecessor()); |
| 9971 if (expr->is_jsruntime()) { | 10049 if (expr->is_jsruntime()) { |
| 9972 return Bailout(kCallToAJavaScriptRuntimeFunction); | 10050 return Bailout(kCallToAJavaScriptRuntimeFunction); |
| 9973 } | 10051 } |
| (...skipping 3029 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13003 if (ShouldProduceTraceOutput()) { | 13081 if (ShouldProduceTraceOutput()) { |
| 13004 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13082 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13005 } | 13083 } |
| 13006 | 13084 |
| 13007 #ifdef DEBUG | 13085 #ifdef DEBUG |
| 13008 graph_->Verify(false); // No full verify. | 13086 graph_->Verify(false); // No full verify. |
| 13009 #endif | 13087 #endif |
| 13010 } | 13088 } |
| 13011 | 13089 |
| 13012 } } // namespace v8::internal | 13090 } } // namespace v8::internal |
| OLD | NEW |