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