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 |