| 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 2409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2420 HObjectAccess::ForArrayLength(elements_kind)); | 2420 HObjectAccess::ForArrayLength(elements_kind)); |
| 2421 } else { | 2421 } else { |
| 2422 length = AddLoadFixedArrayLength(elements); | 2422 length = AddLoadFixedArrayLength(elements); |
| 2423 } | 2423 } |
| 2424 length->set_type(HType::Smi()); | 2424 length->set_type(HType::Smi()); |
| 2425 HValue* checked_key = NULL; | 2425 HValue* checked_key = NULL; |
| 2426 if (IsExternalArrayElementsKind(elements_kind) || | 2426 if (IsExternalArrayElementsKind(elements_kind) || |
| 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 NoObservableSideEffectsScope no_effects(this); | |
| 2431 HInstruction* buffer = Add<HLoadNamedField>( | |
| 2432 checked_object, nullptr, HObjectAccess::ForJSArrayBufferViewBuffer()); | |
| 2433 HInstruction* flags = Add<HLoadNamedField>( | |
| 2434 buffer, nullptr, HObjectAccess::ForJSArrayBufferFlag()); | |
| 2435 HValue* was_neutered_mask = | |
| 2436 Add<HConstant>(1 << JSArrayBuffer::kWasNeuteredBit); | |
| 2437 HValue* was_neutered_test = | |
| 2438 AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask); | |
| 2439 | |
| 2440 IfBuilder if_was_neutered(this); | |
| 2441 if_was_neutered.If<HCompareNumericAndBranch>( | |
| 2442 was_neutered_test, graph()->GetConstant0(), Token::NE); | |
| 2443 if_was_neutered.ThenDeopt(Deoptimizer::kOutOfBounds); | |
| 2444 if_was_neutered.End(); | |
| 2445 | |
| 2446 backing_store = Add<HLoadNamedField>( | 2430 backing_store = Add<HLoadNamedField>( |
| 2447 elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer()); | 2431 elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer()); |
| 2448 } else { | 2432 } else { |
| 2449 backing_store = elements; | 2433 backing_store = elements; |
| 2450 } | 2434 } |
| 2451 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { | 2435 if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) { |
| 2452 NoObservableSideEffectsScope no_effects(this); | 2436 NoObservableSideEffectsScope no_effects(this); |
| 2453 IfBuilder length_checker(this); | 2437 IfBuilder length_checker(this); |
| 2454 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2438 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
| 2455 length_checker.Then(); | 2439 length_checker.Then(); |
| (...skipping 708 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3164 | 3148 |
| 3165 | 3149 |
| 3166 HInstruction* HGraphBuilder::BuildGetArrayFunction() { | 3150 HInstruction* HGraphBuilder::BuildGetArrayFunction() { |
| 3167 HInstruction* native_context = BuildGetNativeContext(); | 3151 HInstruction* native_context = BuildGetNativeContext(); |
| 3168 HInstruction* index = | 3152 HInstruction* index = |
| 3169 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); | 3153 Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX)); |
| 3170 return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS); | 3154 return Add<HLoadKeyed>(native_context, index, nullptr, FAST_ELEMENTS); |
| 3171 } | 3155 } |
| 3172 | 3156 |
| 3173 | 3157 |
| 3174 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object, | |
| 3175 HValue* checked_object, | |
| 3176 FieldIndex index) { | |
| 3177 NoObservableSideEffectsScope scope(this); | |
| 3178 HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( | |
| 3179 index.offset(), Representation::Tagged()); | |
| 3180 HInstruction* buffer = Add<HLoadNamedField>( | |
| 3181 object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer()); | |
| 3182 HInstruction* field = Add<HLoadNamedField>(object, checked_object, access); | |
| 3183 | |
| 3184 IfBuilder if_has_buffer(this); | |
| 3185 HValue* has_buffer = if_has_buffer.IfNot<HIsSmiAndBranch>(buffer); | |
| 3186 if_has_buffer.Then(); | |
| 3187 { | |
| 3188 HInstruction* flags = Add<HLoadNamedField>( | |
| 3189 buffer, has_buffer, HObjectAccess::ForJSArrayBufferFlag()); | |
| 3190 HValue* was_neutered_mask = | |
| 3191 Add<HConstant>(1 << JSArrayBuffer::kWasNeuteredBit); | |
| 3192 HValue* was_neutered_test = | |
| 3193 AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask); | |
| 3194 | |
| 3195 IfBuilder if_was_neutered(this); | |
| 3196 if_was_neutered.If<HCompareNumericAndBranch>( | |
| 3197 was_neutered_test, graph()->GetConstant0(), Token::NE); | |
| 3198 if_was_neutered.Then(); | |
| 3199 Push(graph()->GetConstant0()); | |
| 3200 if_was_neutered.Else(); | |
| 3201 Push(field); | |
| 3202 if_was_neutered.End(); | |
| 3203 } | |
| 3204 if_has_buffer.Else(); | |
| 3205 Push(field); | |
| 3206 if_has_buffer.End(); | |
| 3207 | |
| 3208 return Pop(); | |
| 3209 } | |
| 3210 | |
| 3211 | |
| 3212 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, | 3158 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, |
| 3213 ElementsKind kind, | 3159 ElementsKind kind, |
| 3214 HValue* allocation_site_payload, | 3160 HValue* allocation_site_payload, |
| 3215 HValue* constructor_function, | 3161 HValue* constructor_function, |
| 3216 AllocationSiteOverrideMode override_mode) : | 3162 AllocationSiteOverrideMode override_mode) : |
| 3217 builder_(builder), | 3163 builder_(builder), |
| 3218 kind_(kind), | 3164 kind_(kind), |
| 3219 allocation_site_payload_(allocation_site_payload), | 3165 allocation_site_payload_(allocation_site_payload), |
| 3220 constructor_function_(constructor_function) { | 3166 constructor_function_(constructor_function) { |
| 3221 DCHECK(!allocation_site_payload->IsConstant() || | 3167 DCHECK(!allocation_site_payload->IsConstant() || |
| (...skipping 2479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5701 Handle<Symbol> sym = isolate()->factory()->home_object_symbol(); | 5647 Handle<Symbol> sym = isolate()->factory()->home_object_symbol(); |
| 5702 HInstruction* store_home = BuildKeyedGeneric( | 5648 HInstruction* store_home = BuildKeyedGeneric( |
| 5703 STORE, NULL, value, Add<HConstant>(sym), literal); | 5649 STORE, NULL, value, Add<HConstant>(sym), literal); |
| 5704 AddInstruction(store_home); | 5650 AddInstruction(store_home); |
| 5705 DCHECK(store_home->HasObservableSideEffects()); | 5651 DCHECK(store_home->HasObservableSideEffects()); |
| 5706 Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE); | 5652 Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE); |
| 5707 } | 5653 } |
| 5708 | 5654 |
| 5709 Handle<Map> map = property->GetReceiverType(); | 5655 Handle<Map> map = property->GetReceiverType(); |
| 5710 Handle<String> name = key->AsPropertyName(); | 5656 Handle<String> name = key->AsPropertyName(); |
| 5711 HValue* store; | 5657 HInstruction* store; |
| 5712 if (map.is_null()) { | 5658 if (map.is_null()) { |
| 5713 // If we don't know the monomorphic type, do a generic store. | 5659 // If we don't know the monomorphic type, do a generic store. |
| 5714 CHECK_ALIVE(store = BuildNamedGeneric( | 5660 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5715 STORE, NULL, literal, name, value)); | 5661 STORE, NULL, literal, name, value)); |
| 5716 } else { | 5662 } else { |
| 5717 PropertyAccessInfo info(this, STORE, map, name); | 5663 PropertyAccessInfo info(this, STORE, map, name); |
| 5718 if (info.CanAccessMonomorphic()) { | 5664 if (info.CanAccessMonomorphic()) { |
| 5719 HValue* checked_literal = Add<HCheckMaps>(literal, map); | 5665 HValue* checked_literal = Add<HCheckMaps>(literal, map); |
| 5720 DCHECK(!info.IsAccessorConstant()); | 5666 DCHECK(!info.IsAccessorConstant()); |
| 5721 store = BuildMonomorphicAccess( | 5667 store = BuildMonomorphicAccess( |
| 5722 &info, literal, checked_literal, value, | 5668 &info, literal, checked_literal, value, |
| 5723 BailoutId::None(), BailoutId::None()); | 5669 BailoutId::None(), BailoutId::None()); |
| 5724 } else { | 5670 } else { |
| 5725 CHECK_ALIVE(store = BuildNamedGeneric( | 5671 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5726 STORE, NULL, literal, name, value)); | 5672 STORE, NULL, literal, name, value)); |
| 5727 } | 5673 } |
| 5728 } | 5674 } |
| 5729 if (store->IsInstruction()) { | 5675 AddInstruction(store); |
| 5730 AddInstruction(HInstruction::cast(store)); | |
| 5731 } | |
| 5732 DCHECK(store->HasObservableSideEffects()); | 5676 DCHECK(store->HasObservableSideEffects()); |
| 5733 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5677 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
| 5734 } else { | 5678 } else { |
| 5735 CHECK_ALIVE(VisitForEffect(value)); | 5679 CHECK_ALIVE(VisitForEffect(value)); |
| 5736 } | 5680 } |
| 5737 break; | 5681 break; |
| 5738 } | 5682 } |
| 5739 // Fall through. | 5683 // Fall through. |
| 5740 case ObjectLiteral::Property::PROTOTYPE: | 5684 case ObjectLiteral::Property::PROTOTYPE: |
| 5741 case ObjectLiteral::Property::SETTER: | 5685 case ObjectLiteral::Property::SETTER: |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6182 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() { | 6126 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() { |
| 6183 InstanceType instance_type = map_->instance_type(); | 6127 InstanceType instance_type = map_->instance_type(); |
| 6184 return instance_type == JS_TYPED_ARRAY_TYPE && | 6128 return instance_type == JS_TYPED_ARRAY_TYPE && |
| 6185 IsSpecialIndex(isolate()->unicode_cache(), *name_); | 6129 IsSpecialIndex(isolate()->unicode_cache(), *name_); |
| 6186 } | 6130 } |
| 6187 | 6131 |
| 6188 | 6132 |
| 6189 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { | 6133 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { |
| 6190 if (!CanInlinePropertyAccess(map_)) return false; | 6134 if (!CanInlinePropertyAccess(map_)) return false; |
| 6191 if (IsJSObjectFieldAccessor()) return IsLoad(); | 6135 if (IsJSObjectFieldAccessor()) return IsLoad(); |
| 6192 if (IsJSArrayBufferViewFieldAccessor()) return IsLoad(); | |
| 6193 if (map_->function_with_prototype() && !map_->has_non_instance_prototype() && | 6136 if (map_->function_with_prototype() && !map_->has_non_instance_prototype() && |
| 6194 name_.is_identical_to(isolate()->factory()->prototype_string())) { | 6137 name_.is_identical_to(isolate()->factory()->prototype_string())) { |
| 6195 return IsLoad(); | 6138 return IsLoad(); |
| 6196 } | 6139 } |
| 6197 if (!LookupDescriptor()) return false; | 6140 if (!LookupDescriptor()) return false; |
| 6198 if (IsFound()) return IsLoad() || !IsReadOnly(); | 6141 if (IsFound()) return IsLoad() || !IsReadOnly(); |
| 6199 if (IsIntegerIndexedExotic()) return false; | 6142 if (IsIntegerIndexedExotic()) return false; |
| 6200 if (!LookupInPrototypes()) return false; | 6143 if (!LookupInPrototypes()) return false; |
| 6201 if (IsLoad()) return true; | 6144 if (IsLoad()) return true; |
| 6202 | 6145 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 6231 if (GetJSObjectFieldAccess(&access)) { | 6174 if (GetJSObjectFieldAccess(&access)) { |
| 6232 for (int i = 1; i < maps->length(); ++i) { | 6175 for (int i = 1; i < maps->length(); ++i) { |
| 6233 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); | 6176 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); |
| 6234 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | 6177 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default |
| 6235 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; | 6178 if (!test_info.GetJSObjectFieldAccess(&test_access)) return false; |
| 6236 if (!access.Equals(test_access)) return false; | 6179 if (!access.Equals(test_access)) return false; |
| 6237 } | 6180 } |
| 6238 return true; | 6181 return true; |
| 6239 } | 6182 } |
| 6240 | 6183 |
| 6241 if (GetJSArrayBufferViewFieldAccess(&access)) { | |
| 6242 for (int i = 1; i < maps->length(); ++i) { | |
| 6243 PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); | |
| 6244 HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default | |
| 6245 if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) { | |
| 6246 return false; | |
| 6247 } | |
| 6248 if (!access.Equals(test_access)) return false; | |
| 6249 } | |
| 6250 return true; | |
| 6251 } | |
| 6252 | |
| 6253 // Currently only handle numbers as a polymorphic case. | 6184 // Currently only handle numbers as a polymorphic case. |
| 6254 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 6185 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
| 6255 // instruction. | 6186 // instruction. |
| 6256 if (IsNumberType()) return false; | 6187 if (IsNumberType()) return false; |
| 6257 | 6188 |
| 6258 // Multiple maps cannot transition to the same target map. | 6189 // Multiple maps cannot transition to the same target map. |
| 6259 DCHECK(!IsLoad() || !IsTransition()); | 6190 DCHECK(!IsLoad() || !IsTransition()); |
| 6260 if (IsTransition() && maps->length() > 1) return false; | 6191 if (IsTransition() && maps->length() > 1) return false; |
| 6261 | 6192 |
| 6262 for (int i = 1; i < maps->length(); ++i) { | 6193 for (int i = 1; i < maps->length(); ++i) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 6282 !target->shared()->native(); | 6213 !target->shared()->native(); |
| 6283 } | 6214 } |
| 6284 | 6215 |
| 6285 | 6216 |
| 6286 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor( | 6217 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor( |
| 6287 Handle<JSFunction> target) const { | 6218 Handle<JSFunction> target) const { |
| 6288 return NeedsWrapping(map_, target); | 6219 return NeedsWrapping(map_, target); |
| 6289 } | 6220 } |
| 6290 | 6221 |
| 6291 | 6222 |
| 6292 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess( | 6223 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( |
| 6293 PropertyAccessInfo* info, HValue* object, HValue* checked_object, | 6224 PropertyAccessInfo* info, |
| 6294 HValue* value, BailoutId ast_id, BailoutId return_id, | 6225 HValue* object, |
| 6226 HValue* checked_object, |
| 6227 HValue* value, |
| 6228 BailoutId ast_id, |
| 6229 BailoutId return_id, |
| 6295 bool can_inline_accessor) { | 6230 bool can_inline_accessor) { |
| 6231 |
| 6296 HObjectAccess access = HObjectAccess::ForMap(); // bogus default | 6232 HObjectAccess access = HObjectAccess::ForMap(); // bogus default |
| 6297 if (info->GetJSObjectFieldAccess(&access)) { | 6233 if (info->GetJSObjectFieldAccess(&access)) { |
| 6298 DCHECK(info->IsLoad()); | 6234 DCHECK(info->IsLoad()); |
| 6299 return New<HLoadNamedField>(object, checked_object, access); | 6235 return New<HLoadNamedField>(object, checked_object, access); |
| 6300 } | 6236 } |
| 6301 | 6237 |
| 6302 if (info->GetJSArrayBufferViewFieldAccess(&access)) { | |
| 6303 DCHECK(info->IsLoad()); | |
| 6304 return BuildArrayBufferViewFieldAccessor( | |
| 6305 object, checked_object, FieldIndex::ForInObjectOffset(access.offset())); | |
| 6306 } | |
| 6307 | |
| 6308 if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && | 6238 if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && |
| 6309 info->map()->function_with_prototype()) { | 6239 info->map()->function_with_prototype()) { |
| 6310 DCHECK(!info->map()->has_non_instance_prototype()); | 6240 DCHECK(!info->map()->has_non_instance_prototype()); |
| 6311 return New<HLoadFunctionPrototype>(checked_object); | 6241 return New<HLoadFunctionPrototype>(checked_object); |
| 6312 } | 6242 } |
| 6313 | 6243 |
| 6314 HValue* checked_holder = checked_object; | 6244 HValue* checked_holder = checked_object; |
| 6315 if (info->has_holder()) { | 6245 if (info->has_holder()) { |
| 6316 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); | 6246 Handle<JSObject> prototype(JSObject::cast(info->map()->prototype())); |
| 6317 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); | 6247 checked_holder = BuildCheckPrototypeMaps(prototype, info->holder()); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6447 } | 6377 } |
| 6448 FinishCurrentBlock(compare); | 6378 FinishCurrentBlock(compare); |
| 6449 | 6379 |
| 6450 if (info.IsNumberType()) { | 6380 if (info.IsNumberType()) { |
| 6451 GotoNoSimulate(if_true, number_block); | 6381 GotoNoSimulate(if_true, number_block); |
| 6452 if_true = number_block; | 6382 if_true = number_block; |
| 6453 } | 6383 } |
| 6454 | 6384 |
| 6455 set_current_block(if_true); | 6385 set_current_block(if_true); |
| 6456 | 6386 |
| 6457 HValue* access = | 6387 HInstruction* access = BuildMonomorphicAccess( |
| 6458 BuildMonomorphicAccess(&info, object, dependency, value, ast_id, | 6388 &info, object, dependency, value, ast_id, |
| 6459 return_id, FLAG_polymorphic_inlining); | 6389 return_id, FLAG_polymorphic_inlining); |
| 6460 | 6390 |
| 6461 HValue* result = NULL; | 6391 HValue* result = NULL; |
| 6462 switch (access_type) { | 6392 switch (access_type) { |
| 6463 case LOAD: | 6393 case LOAD: |
| 6464 result = access; | 6394 result = access; |
| 6465 break; | 6395 break; |
| 6466 case STORE: | 6396 case STORE: |
| 6467 result = value; | 6397 result = value; |
| 6468 break; | 6398 break; |
| 6469 } | 6399 } |
| 6470 | 6400 |
| 6471 if (access == NULL) { | 6401 if (access == NULL) { |
| 6472 if (HasStackOverflow()) return; | 6402 if (HasStackOverflow()) return; |
| 6473 } else { | 6403 } else { |
| 6474 if (access->IsInstruction()) { | 6404 if (!access->IsLinked()) AddInstruction(access); |
| 6475 HInstruction* instr = HInstruction::cast(access); | |
| 6476 if (!instr->IsLinked()) AddInstruction(instr); | |
| 6477 } | |
| 6478 if (!ast_context()->IsEffect()) Push(result); | 6405 if (!ast_context()->IsEffect()) Push(result); |
| 6479 } | 6406 } |
| 6480 | 6407 |
| 6481 if (current_block() != NULL) Goto(join); | 6408 if (current_block() != NULL) Goto(join); |
| 6482 set_current_block(if_false); | 6409 set_current_block(if_false); |
| 6483 } | 6410 } |
| 6484 | 6411 |
| 6485 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6412 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6486 // know about and do not want to handle ones we've never seen. Otherwise | 6413 // know about and do not want to handle ones we've never seen. Otherwise |
| 6487 // use a generic IC. | 6414 // use a generic IC. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6561 } | 6488 } |
| 6562 | 6489 |
| 6563 // Named store. | 6490 // Named store. |
| 6564 HValue* value = Pop(); | 6491 HValue* value = Pop(); |
| 6565 HValue* object = Pop(); | 6492 HValue* object = Pop(); |
| 6566 | 6493 |
| 6567 Literal* key = prop->key()->AsLiteral(); | 6494 Literal* key = prop->key()->AsLiteral(); |
| 6568 Handle<String> name = Handle<String>::cast(key->value()); | 6495 Handle<String> name = Handle<String>::cast(key->value()); |
| 6569 DCHECK(!name.is_null()); | 6496 DCHECK(!name.is_null()); |
| 6570 | 6497 |
| 6571 HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, object, | 6498 HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr, |
| 6572 name, value, is_uninitialized); | 6499 object, name, value, is_uninitialized); |
| 6573 if (access == NULL) return; | 6500 if (instr == NULL) return; |
| 6574 | 6501 |
| 6575 if (!ast_context()->IsEffect()) Push(value); | 6502 if (!ast_context()->IsEffect()) Push(value); |
| 6576 if (access->IsInstruction()) AddInstruction(HInstruction::cast(access)); | 6503 AddInstruction(instr); |
| 6577 if (access->HasObservableSideEffects()) { | 6504 if (instr->HasObservableSideEffects()) { |
| 6578 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6505 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 6579 } | 6506 } |
| 6580 if (!ast_context()->IsEffect()) Drop(1); | 6507 if (!ast_context()->IsEffect()) Drop(1); |
| 6581 return ast_context()->ReturnValue(value); | 6508 return ast_context()->ReturnValue(value); |
| 6582 } | 6509 } |
| 6583 | 6510 |
| 6584 | 6511 |
| 6585 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6512 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 6586 Property* prop = expr->target()->AsProperty(); | 6513 Property* prop = expr->target()->AsProperty(); |
| 6587 DCHECK(prop != NULL); | 6514 DCHECK(prop != NULL); |
| (...skipping 728 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7316 if (key->ActualValue()->IsConstant()) { | 7243 if (key->ActualValue()->IsConstant()) { |
| 7317 Handle<Object> constant = | 7244 Handle<Object> constant = |
| 7318 HConstant::cast(key->ActualValue())->handle(isolate()); | 7245 HConstant::cast(key->ActualValue())->handle(isolate()); |
| 7319 uint32_t array_index; | 7246 uint32_t array_index; |
| 7320 if (constant->IsString() && | 7247 if (constant->IsString() && |
| 7321 !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) { | 7248 !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) { |
| 7322 if (!constant->IsUniqueName()) { | 7249 if (!constant->IsUniqueName()) { |
| 7323 constant = isolate()->factory()->InternalizeString( | 7250 constant = isolate()->factory()->InternalizeString( |
| 7324 Handle<String>::cast(constant)); | 7251 Handle<String>::cast(constant)); |
| 7325 } | 7252 } |
| 7326 HValue* access = | 7253 HInstruction* instr = |
| 7327 BuildNamedAccess(access_type, ast_id, return_id, expr, obj, | 7254 BuildNamedAccess(access_type, ast_id, return_id, expr, obj, |
| 7328 Handle<String>::cast(constant), val, false); | 7255 Handle<String>::cast(constant), val, false); |
| 7329 if (access == NULL || access->IsPhi() || | 7256 if (instr == NULL || instr->IsLinked()) { |
| 7330 HInstruction::cast(access)->IsLinked()) { | |
| 7331 *has_side_effects = false; | 7257 *has_side_effects = false; |
| 7332 } else { | 7258 } else { |
| 7333 HInstruction* instr = HInstruction::cast(access); | |
| 7334 AddInstruction(instr); | 7259 AddInstruction(instr); |
| 7335 *has_side_effects = instr->HasObservableSideEffects(); | 7260 *has_side_effects = instr->HasObservableSideEffects(); |
| 7336 } | 7261 } |
| 7337 return access; | 7262 return instr; |
| 7338 } | 7263 } |
| 7339 } | 7264 } |
| 7340 | 7265 |
| 7341 DCHECK(!expr->IsPropertyName()); | 7266 DCHECK(!expr->IsPropertyName()); |
| 7342 HInstruction* instr = NULL; | 7267 HInstruction* instr = NULL; |
| 7343 | 7268 |
| 7344 SmallMapList* maps; | 7269 SmallMapList* maps; |
| 7345 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone()); | 7270 bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone()); |
| 7346 | 7271 |
| 7347 bool force_generic = false; | 7272 bool force_generic = false; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7486 HInstruction* length = Add<HConstant>(argument_count); | 7411 HInstruction* length = Add<HConstant>(argument_count); |
| 7487 HInstruction* checked_key = Add<HBoundsCheck>(key, length); | 7412 HInstruction* checked_key = Add<HBoundsCheck>(key, length); |
| 7488 result = New<HAccessArgumentsAt>(elements, length, checked_key); | 7413 result = New<HAccessArgumentsAt>(elements, length, checked_key); |
| 7489 } | 7414 } |
| 7490 } | 7415 } |
| 7491 ast_context()->ReturnInstruction(result, expr->id()); | 7416 ast_context()->ReturnInstruction(result, expr->id()); |
| 7492 return true; | 7417 return true; |
| 7493 } | 7418 } |
| 7494 | 7419 |
| 7495 | 7420 |
| 7496 HValue* HOptimizedGraphBuilder::BuildNamedAccess( | 7421 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( |
| 7497 PropertyAccessType access, BailoutId ast_id, BailoutId return_id, | 7422 PropertyAccessType access, |
| 7498 Expression* expr, HValue* object, Handle<String> name, HValue* value, | 7423 BailoutId ast_id, |
| 7424 BailoutId return_id, |
| 7425 Expression* expr, |
| 7426 HValue* object, |
| 7427 Handle<String> name, |
| 7428 HValue* value, |
| 7499 bool is_uninitialized) { | 7429 bool is_uninitialized) { |
| 7500 SmallMapList* maps; | 7430 SmallMapList* maps; |
| 7501 ComputeReceiverTypes(expr, object, &maps, zone()); | 7431 ComputeReceiverTypes(expr, object, &maps, zone()); |
| 7502 DCHECK(maps != NULL); | 7432 DCHECK(maps != NULL); |
| 7503 | 7433 |
| 7504 if (maps->length() > 0) { | 7434 if (maps->length() > 0) { |
| 7505 PropertyAccessInfo info(this, access, maps->first(), name); | 7435 PropertyAccessInfo info(this, access, maps->first(), name); |
| 7506 if (!info.CanAccessAsMonomorphic(maps)) { | 7436 if (!info.CanAccessAsMonomorphic(maps)) { |
| 7507 HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object, | 7437 HandlePolymorphicNamedFieldAccess(access, expr, ast_id, return_id, object, |
| 7508 value, maps, name); | 7438 value, maps, name); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7544 HValue* index = Pop(); | 7474 HValue* index = Pop(); |
| 7545 HValue* string = Pop(); | 7475 HValue* string = Pop(); |
| 7546 HInstruction* char_code = BuildStringCharCodeAt(string, index); | 7476 HInstruction* char_code = BuildStringCharCodeAt(string, index); |
| 7547 AddInstruction(char_code); | 7477 AddInstruction(char_code); |
| 7548 instr = NewUncasted<HStringCharFromCode>(char_code); | 7478 instr = NewUncasted<HStringCharFromCode>(char_code); |
| 7549 | 7479 |
| 7550 } else if (expr->key()->IsPropertyName()) { | 7480 } else if (expr->key()->IsPropertyName()) { |
| 7551 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 7481 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 7552 HValue* object = Pop(); | 7482 HValue* object = Pop(); |
| 7553 | 7483 |
| 7554 HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, object, | 7484 instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, |
| 7555 name, NULL, expr->IsUninitialized()); | 7485 object, name, NULL, expr->IsUninitialized()); |
| 7556 if (value == NULL) return; | 7486 if (instr == NULL) return; |
| 7557 if (value->IsPhi()) return ast_context()->ReturnValue(value); | |
| 7558 instr = HInstruction::cast(value); | |
| 7559 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); | 7487 if (instr->IsLinked()) return ast_context()->ReturnValue(instr); |
| 7560 | 7488 |
| 7561 } else { | 7489 } else { |
| 7562 HValue* key = Pop(); | 7490 HValue* key = Pop(); |
| 7563 HValue* obj = Pop(); | 7491 HValue* obj = Pop(); |
| 7564 | 7492 |
| 7565 bool has_side_effects = false; | 7493 bool has_side_effects = false; |
| 7566 HValue* load = HandleKeyedElementAccess( | 7494 HValue* load = HandleKeyedElementAccess( |
| 7567 obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects); | 7495 obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects); |
| 7568 if (has_side_effects) { | 7496 if (has_side_effects) { |
| (...skipping 2113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9682 byte_offset); | 9610 byte_offset); |
| 9683 Add<HStoreNamedField>( | 9611 Add<HStoreNamedField>( |
| 9684 obj, | 9612 obj, |
| 9685 HObjectAccess::ForJSArrayBufferViewByteLength(), | 9613 HObjectAccess::ForJSArrayBufferViewByteLength(), |
| 9686 byte_length); | 9614 byte_length); |
| 9687 | 9615 |
| 9688 if (buffer != NULL) { | 9616 if (buffer != NULL) { |
| 9689 Add<HStoreNamedField>( | 9617 Add<HStoreNamedField>( |
| 9690 obj, | 9618 obj, |
| 9691 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); | 9619 HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); |
| 9620 HObjectAccess weak_first_view_access = |
| 9621 HObjectAccess::ForJSArrayBufferWeakFirstView(); |
| 9622 Add<HStoreNamedField>( |
| 9623 obj, HObjectAccess::ForJSArrayBufferViewWeakNext(), |
| 9624 Add<HLoadNamedField>(buffer, nullptr, weak_first_view_access)); |
| 9625 Add<HStoreNamedField>(buffer, weak_first_view_access, obj); |
| 9692 } else { | 9626 } else { |
| 9693 Add<HStoreNamedField>( | 9627 Add<HStoreNamedField>( |
| 9694 obj, | 9628 obj, |
| 9695 HObjectAccess::ForJSArrayBufferViewBuffer(), | 9629 HObjectAccess::ForJSArrayBufferViewBuffer(), |
| 9696 Add<HConstant>(static_cast<int32_t>(0))); | 9630 Add<HConstant>(static_cast<int32_t>(0))); |
| 9631 Add<HStoreNamedField>(obj, |
| 9632 HObjectAccess::ForJSArrayBufferViewWeakNext(), |
| 9633 graph()->GetConstantUndefined()); |
| 9697 } | 9634 } |
| 9698 } | 9635 } |
| 9699 | 9636 |
| 9700 | 9637 |
| 9701 void HOptimizedGraphBuilder::GenerateDataViewInitialize( | 9638 void HOptimizedGraphBuilder::GenerateDataViewInitialize( |
| 9702 CallRuntime* expr) { | 9639 CallRuntime* expr) { |
| 9703 ZoneList<Expression*>* arguments = expr->arguments(); | 9640 ZoneList<Expression*>* arguments = expr->arguments(); |
| 9704 | 9641 |
| 9705 DCHECK(arguments->length()== 4); | 9642 DCHECK(arguments->length()== 4); |
| 9706 CHECK_ALIVE(VisitForValue(arguments->at(0))); | 9643 CHECK_ALIVE(VisitForValue(arguments->at(0))); |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9982 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9919 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 9983 HValue* buffer = Pop(); | 9920 HValue* buffer = Pop(); |
| 9984 HInstruction* result = New<HLoadNamedField>( | 9921 HInstruction* result = New<HLoadNamedField>( |
| 9985 buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength()); | 9922 buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength()); |
| 9986 return ast_context()->ReturnInstruction(result, expr->id()); | 9923 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9987 } | 9924 } |
| 9988 | 9925 |
| 9989 | 9926 |
| 9990 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( | 9927 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( |
| 9991 CallRuntime* expr) { | 9928 CallRuntime* expr) { |
| 9992 NoObservableSideEffectsScope scope(this); | |
| 9993 DCHECK(expr->arguments()->length() == 1); | 9929 DCHECK(expr->arguments()->length() == 1); |
| 9994 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9930 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 9995 HValue* view = Pop(); | 9931 HValue* buffer = Pop(); |
| 9996 | 9932 HInstruction* result = New<HLoadNamedField>( |
| 9997 return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( | 9933 buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteLength()); |
| 9998 view, nullptr, | 9934 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9999 FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset))); | |
| 10000 } | 9935 } |
| 10001 | 9936 |
| 10002 | 9937 |
| 10003 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( | 9938 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( |
| 10004 CallRuntime* expr) { | 9939 CallRuntime* expr) { |
| 10005 NoObservableSideEffectsScope scope(this); | |
| 10006 DCHECK(expr->arguments()->length() == 1); | 9940 DCHECK(expr->arguments()->length() == 1); |
| 10007 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9941 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 10008 HValue* view = Pop(); | 9942 HValue* buffer = Pop(); |
| 10009 | 9943 HInstruction* result = New<HLoadNamedField>( |
| 10010 return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( | 9944 buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteOffset()); |
| 10011 view, nullptr, | 9945 return ast_context()->ReturnInstruction(result, expr->id()); |
| 10012 FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset))); | |
| 10013 } | 9946 } |
| 10014 | 9947 |
| 10015 | 9948 |
| 10016 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( | 9949 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( |
| 10017 CallRuntime* expr) { | 9950 CallRuntime* expr) { |
| 10018 NoObservableSideEffectsScope scope(this); | |
| 10019 DCHECK(expr->arguments()->length() == 1); | 9951 DCHECK(expr->arguments()->length() == 1); |
| 10020 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); | 9952 CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); |
| 10021 HValue* view = Pop(); | 9953 HValue* buffer = Pop(); |
| 10022 | 9954 HInstruction* result = New<HLoadNamedField>( |
| 10023 return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( | 9955 buffer, nullptr, HObjectAccess::ForJSTypedArrayLength()); |
| 10024 view, nullptr, | 9956 return ast_context()->ReturnInstruction(result, expr->id()); |
| 10025 FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset))); | |
| 10026 } | 9957 } |
| 10027 | 9958 |
| 10028 | 9959 |
| 10029 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { | 9960 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { |
| 10030 DCHECK(!HasStackOverflow()); | 9961 DCHECK(!HasStackOverflow()); |
| 10031 DCHECK(current_block() != NULL); | 9962 DCHECK(current_block() != NULL); |
| 10032 DCHECK(current_block()->HasPredecessor()); | 9963 DCHECK(current_block()->HasPredecessor()); |
| 10033 if (expr->is_jsruntime()) { | 9964 if (expr->is_jsruntime()) { |
| 10034 return Bailout(kCallToAJavaScriptRuntimeFunction); | 9965 return Bailout(kCallToAJavaScriptRuntimeFunction); |
| 10035 } | 9966 } |
| (...skipping 3027 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13063 if (ShouldProduceTraceOutput()) { | 12994 if (ShouldProduceTraceOutput()) { |
| 13064 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 12995 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13065 } | 12996 } |
| 13066 | 12997 |
| 13067 #ifdef DEBUG | 12998 #ifdef DEBUG |
| 13068 graph_->Verify(false); // No full verify. | 12999 graph_->Verify(false); // No full verify. |
| 13069 #endif | 13000 #endif |
| 13070 } | 13001 } |
| 13071 | 13002 |
| 13072 } } // namespace v8::internal | 13003 } } // namespace v8::internal |
| OLD | NEW |