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