| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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/code-stubs.h" | 5 #include "src/code-stubs.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "src/bailout-reason.h" | 9 #include "src/bailout-reason.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 { | 369 { |
| 370 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); | 370 HValue* argument = Add<HAccessArgumentsAt>(argument_elements, argc, key); |
| 371 HValue* index = AddUncasted<HAdd>(key, length); | 371 HValue* index = AddUncasted<HAdd>(key, length); |
| 372 AddElementAccess(elements, index, argument, object, nullptr, kind, STORE); | 372 AddElementAccess(elements, index, argument, object, nullptr, kind, STORE); |
| 373 } | 373 } |
| 374 builder.EndBody(); | 374 builder.EndBody(); |
| 375 return new_length; | 375 return new_length; |
| 376 } | 376 } |
| 377 | 377 |
| 378 template <> | 378 template <> |
| 379 HValue* CodeStubGraphBuilder<FastArrayPushStub>::BuildCodeStub() { | |
| 380 // TODO(verwaest): Fix deoptimizer messages. | |
| 381 HValue* argc = GetArgumentsLength(); | |
| 382 | |
| 383 HInstruction* argument_elements = Add<HArgumentsElements>(false, false); | |
| 384 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, | |
| 385 graph()->GetConstantMinus1()); | |
| 386 BuildCheckHeapObject(object); | |
| 387 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); | |
| 388 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_ARRAY); | |
| 389 | |
| 390 // Disallow pushing onto prototypes. It might be the JSArray prototype. | |
| 391 // Disallow pushing onto non-extensible objects. | |
| 392 { | |
| 393 HValue* bit_field2 = | |
| 394 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); | |
| 395 HValue* mask = | |
| 396 Add<HConstant>(static_cast<int>(Map::IsPrototypeMapBits::kMask) | | |
| 397 (1 << Map::kIsExtensible)); | |
| 398 HValue* bits = AddUncasted<HBitwise>(Token::BIT_AND, bit_field2, mask); | |
| 399 IfBuilder check(this); | |
| 400 check.If<HCompareNumericAndBranch>( | |
| 401 bits, Add<HConstant>(1 << Map::kIsExtensible), Token::NE); | |
| 402 check.ThenDeopt(DeoptimizeReason::kFastPathFailed); | |
| 403 check.End(); | |
| 404 } | |
| 405 | |
| 406 // Disallow pushing onto arrays in dictionary named property mode. We need to | |
| 407 // figure out whether the length property is still writable. | |
| 408 { | |
| 409 HValue* bit_field3 = | |
| 410 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); | |
| 411 HValue* mask = Add<HConstant>(static_cast<int>(Map::DictionaryMap::kMask)); | |
| 412 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, bit_field3, mask); | |
| 413 IfBuilder check(this); | |
| 414 check.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); | |
| 415 check.ThenDeopt(DeoptimizeReason::kFastPathFailed); | |
| 416 check.End(); | |
| 417 } | |
| 418 | |
| 419 // Check whether the length property is writable. The length property is the | |
| 420 // only default named property on arrays. It's nonconfigurable, hence is | |
| 421 // guaranteed to stay the first property. | |
| 422 { | |
| 423 HValue* descriptors = | |
| 424 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapDescriptors()); | |
| 425 HValue* details = Add<HLoadKeyed>( | |
| 426 descriptors, Add<HConstant>(DescriptorArray::ToDetailsIndex(0)), | |
| 427 nullptr, nullptr, FAST_SMI_ELEMENTS); | |
| 428 HValue* mask = | |
| 429 Add<HConstant>(READ_ONLY << PropertyDetails::AttributesField::kShift); | |
| 430 HValue* bit = AddUncasted<HBitwise>(Token::BIT_AND, details, mask); | |
| 431 IfBuilder readonly(this); | |
| 432 readonly.If<HCompareNumericAndBranch>(bit, mask, Token::EQ); | |
| 433 readonly.ThenDeopt(DeoptimizeReason::kFastPathFailed); | |
| 434 readonly.End(); | |
| 435 } | |
| 436 | |
| 437 HValue* null = Add<HLoadRoot>(Heap::kNullValueRootIndex); | |
| 438 HValue* empty = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex); | |
| 439 environment()->Push(map); | |
| 440 LoopBuilder check_prototypes(this); | |
| 441 check_prototypes.BeginBody(1); | |
| 442 { | |
| 443 HValue* parent_map = environment()->Pop(); | |
| 444 HValue* prototype = Add<HLoadNamedField>(parent_map, nullptr, | |
| 445 HObjectAccess::ForPrototype()); | |
| 446 | |
| 447 IfBuilder is_null(this); | |
| 448 is_null.If<HCompareObjectEqAndBranch>(prototype, null); | |
| 449 is_null.Then(); | |
| 450 check_prototypes.Break(); | |
| 451 is_null.End(); | |
| 452 | |
| 453 HValue* prototype_map = | |
| 454 Add<HLoadNamedField>(prototype, nullptr, HObjectAccess::ForMap()); | |
| 455 HValue* instance_type = Add<HLoadNamedField>( | |
| 456 prototype_map, nullptr, HObjectAccess::ForMapInstanceType()); | |
| 457 IfBuilder check_instance_type(this); | |
| 458 check_instance_type.If<HCompareNumericAndBranch>( | |
| 459 instance_type, Add<HConstant>(LAST_CUSTOM_ELEMENTS_RECEIVER), | |
| 460 Token::LTE); | |
| 461 check_instance_type.ThenDeopt(DeoptimizeReason::kFastPathFailed); | |
| 462 check_instance_type.End(); | |
| 463 | |
| 464 HValue* elements = Add<HLoadNamedField>( | |
| 465 prototype, nullptr, HObjectAccess::ForElementsPointer()); | |
| 466 IfBuilder no_elements(this); | |
| 467 no_elements.IfNot<HCompareObjectEqAndBranch>(elements, empty); | |
| 468 no_elements.ThenDeopt(DeoptimizeReason::kFastPathFailed); | |
| 469 no_elements.End(); | |
| 470 | |
| 471 environment()->Push(prototype_map); | |
| 472 } | |
| 473 check_prototypes.EndBody(); | |
| 474 | |
| 475 HValue* bit_field2 = | |
| 476 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2()); | |
| 477 HValue* kind = BuildDecodeField<Map::ElementsKindBits>(bit_field2); | |
| 478 | |
| 479 // Below we only check the upper bound of the relevant ranges to include both | |
| 480 // holey and non-holey versions. We check them in order smi, object, double | |
| 481 // since smi < object < double. | |
| 482 STATIC_ASSERT(FAST_SMI_ELEMENTS < FAST_HOLEY_SMI_ELEMENTS); | |
| 483 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS < FAST_HOLEY_ELEMENTS); | |
| 484 STATIC_ASSERT(FAST_ELEMENTS < FAST_HOLEY_ELEMENTS); | |
| 485 STATIC_ASSERT(FAST_HOLEY_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); | |
| 486 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FAST_HOLEY_DOUBLE_ELEMENTS); | |
| 487 IfBuilder has_smi_elements(this); | |
| 488 has_smi_elements.If<HCompareNumericAndBranch>( | |
| 489 kind, Add<HConstant>(FAST_HOLEY_SMI_ELEMENTS), Token::LTE); | |
| 490 has_smi_elements.Then(); | |
| 491 { | |
| 492 HValue* new_length = BuildPushElement(object, argc, argument_elements, | |
| 493 FAST_HOLEY_SMI_ELEMENTS); | |
| 494 environment()->Push(new_length); | |
| 495 } | |
| 496 has_smi_elements.Else(); | |
| 497 { | |
| 498 IfBuilder has_object_elements(this); | |
| 499 has_object_elements.If<HCompareNumericAndBranch>( | |
| 500 kind, Add<HConstant>(FAST_HOLEY_ELEMENTS), Token::LTE); | |
| 501 has_object_elements.Then(); | |
| 502 { | |
| 503 HValue* new_length = BuildPushElement(object, argc, argument_elements, | |
| 504 FAST_HOLEY_ELEMENTS); | |
| 505 environment()->Push(new_length); | |
| 506 } | |
| 507 has_object_elements.Else(); | |
| 508 { | |
| 509 IfBuilder has_double_elements(this); | |
| 510 has_double_elements.If<HCompareNumericAndBranch>( | |
| 511 kind, Add<HConstant>(FAST_HOLEY_DOUBLE_ELEMENTS), Token::LTE); | |
| 512 has_double_elements.Then(); | |
| 513 { | |
| 514 HValue* new_length = BuildPushElement(object, argc, argument_elements, | |
| 515 FAST_HOLEY_DOUBLE_ELEMENTS); | |
| 516 environment()->Push(new_length); | |
| 517 } | |
| 518 has_double_elements.ElseDeopt(DeoptimizeReason::kFastPathFailed); | |
| 519 has_double_elements.End(); | |
| 520 } | |
| 521 has_object_elements.End(); | |
| 522 } | |
| 523 has_smi_elements.End(); | |
| 524 | |
| 525 return environment()->Pop(); | |
| 526 } | |
| 527 | |
| 528 Handle<Code> FastArrayPushStub::GenerateCode() { return DoGenerateCode(this); } | |
| 529 | |
| 530 template <> | |
| 531 HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() { | 379 HValue* CodeStubGraphBuilder<FastFunctionBindStub>::BuildCodeStub() { |
| 532 // TODO(verwaest): Fix deoptimizer messages. | 380 // TODO(verwaest): Fix deoptimizer messages. |
| 533 HValue* argc = GetArgumentsLength(); | 381 HValue* argc = GetArgumentsLength(); |
| 534 HInstruction* argument_elements = Add<HArgumentsElements>(false, false); | 382 HInstruction* argument_elements = Add<HArgumentsElements>(false, false); |
| 535 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, | 383 HInstruction* object = Add<HAccessArgumentsAt>(argument_elements, argc, |
| 536 graph()->GetConstantMinus1()); | 384 graph()->GetConstantMinus1()); |
| 537 BuildCheckHeapObject(object); | 385 BuildCheckHeapObject(object); |
| 538 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); | 386 HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap()); |
| 539 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION); | 387 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_JS_FUNCTION); |
| 540 | 388 |
| (...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); | 997 return BuildUncheckedDictionaryElementLoad(receiver, elements, key, hash); |
| 1150 } | 998 } |
| 1151 | 999 |
| 1152 | 1000 |
| 1153 Handle<Code> LoadDictionaryElementStub::GenerateCode() { | 1001 Handle<Code> LoadDictionaryElementStub::GenerateCode() { |
| 1154 return DoGenerateCode(this); | 1002 return DoGenerateCode(this); |
| 1155 } | 1003 } |
| 1156 | 1004 |
| 1157 } // namespace internal | 1005 } // namespace internal |
| 1158 } // namespace v8 | 1006 } // namespace v8 |
| OLD | NEW |