Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/code-stub-assembler.h" | 5 #include "src/compiler/code-stub-assembler.h" |
| 6 | 6 |
| 7 #include <ostream> | 7 #include <ostream> |
| 8 | 8 |
| 9 #include "src/code-factory.h" | 9 #include "src/code-factory.h" |
| 10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 } | 107 } |
| 108 | 108 |
| 109 Node* CodeStubAssembler::Float64Constant(double value) { | 109 Node* CodeStubAssembler::Float64Constant(double value) { |
| 110 return raw_assembler_->Float64Constant(value); | 110 return raw_assembler_->Float64Constant(value); |
| 111 } | 111 } |
| 112 | 112 |
| 113 Node* CodeStubAssembler::BooleanMapConstant() { | 113 Node* CodeStubAssembler::BooleanMapConstant() { |
| 114 return HeapConstant(isolate()->factory()->boolean_map()); | 114 return HeapConstant(isolate()->factory()->boolean_map()); |
| 115 } | 115 } |
| 116 | 116 |
| 117 Node* CodeStubAssembler::EmptyStringConstant() { | |
| 118 return LoadRoot(Heap::kempty_stringRootIndex); | |
| 119 } | |
| 120 | |
| 117 Node* CodeStubAssembler::HeapNumberMapConstant() { | 121 Node* CodeStubAssembler::HeapNumberMapConstant() { |
| 118 return HeapConstant(isolate()->factory()->heap_number_map()); | 122 return HeapConstant(isolate()->factory()->heap_number_map()); |
| 119 } | 123 } |
| 120 | 124 |
| 125 Node* CodeStubAssembler::NaNConstant() { | |
| 126 return LoadRoot(Heap::kNanValueRootIndex); | |
| 127 } | |
| 128 | |
| 129 Node* CodeStubAssembler::NoContextConstant() { | |
| 130 return SmiConstant(Smi::FromInt(0)); | |
| 131 } | |
| 132 | |
| 121 Node* CodeStubAssembler::NullConstant() { | 133 Node* CodeStubAssembler::NullConstant() { |
| 122 return LoadRoot(Heap::kNullValueRootIndex); | 134 return LoadRoot(Heap::kNullValueRootIndex); |
| 123 } | 135 } |
| 124 | 136 |
| 125 Node* CodeStubAssembler::UndefinedConstant() { | 137 Node* CodeStubAssembler::UndefinedConstant() { |
| 126 return LoadRoot(Heap::kUndefinedValueRootIndex); | 138 return LoadRoot(Heap::kUndefinedValueRootIndex); |
| 127 } | 139 } |
| 128 | 140 |
| 129 Node* CodeStubAssembler::Parameter(int value) { | 141 Node* CodeStubAssembler::Parameter(int value) { |
| 130 return raw_assembler_->Parameter(value); | 142 return raw_assembler_->Parameter(value); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 } | 354 } |
| 343 | 355 |
| 344 Node* CodeStubAssembler::SmiTag(Node* value) { | 356 Node* CodeStubAssembler::SmiTag(Node* value) { |
| 345 return raw_assembler_->WordShl(value, SmiShiftBitsConstant()); | 357 return raw_assembler_->WordShl(value, SmiShiftBitsConstant()); |
| 346 } | 358 } |
| 347 | 359 |
| 348 Node* CodeStubAssembler::SmiUntag(Node* value) { | 360 Node* CodeStubAssembler::SmiUntag(Node* value) { |
| 349 return raw_assembler_->WordSar(value, SmiShiftBitsConstant()); | 361 return raw_assembler_->WordSar(value, SmiShiftBitsConstant()); |
| 350 } | 362 } |
| 351 | 363 |
| 364 Node* CodeStubAssembler::SmiFromWord32(Node* value) { | |
| 365 if (raw_assembler_->machine()->Is64()) { | |
| 366 value = raw_assembler_->ChangeInt32ToInt64(value); | |
| 367 } | |
| 368 return raw_assembler_->WordShl(value, SmiShiftBitsConstant()); | |
| 369 } | |
| 370 | |
| 352 Node* CodeStubAssembler::SmiToWord32(Node* value) { | 371 Node* CodeStubAssembler::SmiToWord32(Node* value) { |
| 353 Node* result = raw_assembler_->WordSar(value, SmiShiftBitsConstant()); | 372 Node* result = raw_assembler_->WordSar(value, SmiShiftBitsConstant()); |
| 354 if (raw_assembler_->machine()->Is64()) { | 373 if (raw_assembler_->machine()->Is64()) { |
| 355 result = raw_assembler_->TruncateInt64ToInt32(result); | 374 result = raw_assembler_->TruncateInt64ToInt32(result); |
| 356 } | 375 } |
| 357 return result; | 376 return result; |
| 358 } | 377 } |
| 359 | 378 |
| 360 Node* CodeStubAssembler::SmiToFloat64(Node* value) { | 379 Node* CodeStubAssembler::SmiToFloat64(Node* value) { |
| 361 return ChangeInt32ToFloat64(SmiUntag(value)); | 380 return ChangeInt32ToFloat64(SmiUntag(value)); |
| 362 } | 381 } |
| 363 | 382 |
| 364 Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); } | 383 Node* CodeStubAssembler::SmiAdd(Node* a, Node* b) { return IntPtrAdd(a, b); } |
| 365 | 384 |
| 366 Node* CodeStubAssembler::SmiAddWithOverflow(Node* a, Node* b) { | 385 Node* CodeStubAssembler::SmiAddWithOverflow(Node* a, Node* b) { |
| 367 return IntPtrAddWithOverflow(a, b); | 386 return IntPtrAddWithOverflow(a, b); |
| 368 } | 387 } |
| 369 | 388 |
| 370 Node* CodeStubAssembler::SmiSub(Node* a, Node* b) { return IntPtrSub(a, b); } | 389 Node* CodeStubAssembler::SmiSub(Node* a, Node* b) { return IntPtrSub(a, b); } |
| 371 | 390 |
| 372 Node* CodeStubAssembler::SmiSubWithOverflow(Node* a, Node* b) { | 391 Node* CodeStubAssembler::SmiSubWithOverflow(Node* a, Node* b) { |
| 373 return IntPtrSubWithOverflow(a, b); | 392 return IntPtrSubWithOverflow(a, b); |
| 374 } | 393 } |
| 375 | 394 |
| 376 Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); } | 395 Node* CodeStubAssembler::SmiEqual(Node* a, Node* b) { return WordEqual(a, b); } |
| 377 | 396 |
| 397 Node* CodeStubAssembler::SmiAboveOrEqual(Node* a, Node* b) { | |
| 398 return UintPtrGreaterThanOrEqual(a, b); | |
| 399 } | |
| 400 | |
| 378 Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) { | 401 Node* CodeStubAssembler::SmiLessThan(Node* a, Node* b) { |
| 379 return IntPtrLessThan(a, b); | 402 return IntPtrLessThan(a, b); |
| 380 } | 403 } |
| 381 | 404 |
| 382 Node* CodeStubAssembler::SmiLessThanOrEqual(Node* a, Node* b) { | 405 Node* CodeStubAssembler::SmiLessThanOrEqual(Node* a, Node* b) { |
| 383 return IntPtrLessThanOrEqual(a, b); | 406 return IntPtrLessThanOrEqual(a, b); |
| 384 } | 407 } |
| 385 | 408 |
| 386 Node* CodeStubAssembler::SmiMin(Node* a, Node* b) { | 409 Node* CodeStubAssembler::SmiMin(Node* a, Node* b) { |
| 387 // TODO(bmeurer): Consider using Select once available. | 410 // TODO(bmeurer): Consider using Select once available. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 429 MachineType rep) { | 452 MachineType rep) { |
| 430 return raw_assembler_->Load(rep, buffer, IntPtrConstant(offset)); | 453 return raw_assembler_->Load(rep, buffer, IntPtrConstant(offset)); |
| 431 } | 454 } |
| 432 | 455 |
| 433 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset, | 456 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset, |
| 434 MachineType rep) { | 457 MachineType rep) { |
| 435 return raw_assembler_->Load(rep, object, | 458 return raw_assembler_->Load(rep, object, |
| 436 IntPtrConstant(offset - kHeapObjectTag)); | 459 IntPtrConstant(offset - kHeapObjectTag)); |
| 437 } | 460 } |
| 438 | 461 |
| 462 Node* CodeStubAssembler::StoreObjectFieldNoWriteBarrier( | |
| 463 Node* object, int offset, Node* value, MachineRepresentation rep) { | |
| 464 return StoreNoWriteBarrier(rep, object, | |
| 465 IntPtrConstant(offset - kHeapObjectTag), value); | |
| 466 } | |
| 467 | |
| 439 Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) { | 468 Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) { |
| 440 return Load(MachineType::Float64(), object, | 469 return Load(MachineType::Float64(), object, |
| 441 IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag)); | 470 IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag)); |
| 442 } | 471 } |
| 443 | 472 |
| 444 Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) { | 473 Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) { |
| 445 return StoreNoWriteBarrier( | 474 return StoreNoWriteBarrier( |
| 446 MachineRepresentation::kFloat64, object, | 475 MachineRepresentation::kFloat64, object, |
| 447 IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), value); | 476 IntPtrConstant(HeapNumber::kValueOffset - kHeapObjectTag), value); |
| 448 } | 477 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 476 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { | 505 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { |
| 477 return LoadObjectField(map, Map::kDescriptorsOffset); | 506 return LoadObjectField(map, Map::kDescriptorsOffset); |
| 478 } | 507 } |
| 479 | 508 |
| 480 Node* CodeStubAssembler::LoadNameHash(Node* name) { | 509 Node* CodeStubAssembler::LoadNameHash(Node* name) { |
| 481 return Load(MachineType::Uint32(), name, | 510 return Load(MachineType::Uint32(), name, |
| 482 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); | 511 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); |
| 483 } | 512 } |
| 484 | 513 |
| 485 Node* CodeStubAssembler::LoadFixedArrayElementInt32Index( | 514 Node* CodeStubAssembler::LoadFixedArrayElementInt32Index( |
| 486 Node* object, Node* int32_index, int additional_offset) { | 515 Node* object, Node* index, int additional_offset) { |
| 487 Node* header_size = IntPtrConstant(additional_offset + | 516 Node* header_size = IntPtrConstant(additional_offset + |
| 488 FixedArray::kHeaderSize - kHeapObjectTag); | 517 FixedArray::kHeaderSize - kHeapObjectTag); |
| 489 Node* scaled_index = WordShl(int32_index, IntPtrConstant(kPointerSizeLog2)); | 518 if (raw_assembler_->machine()->Is64()) { |
| 519 index = ChangeInt32ToInt64(index); | |
| 520 } | |
| 521 Node* scaled_index = WordShl(index, IntPtrConstant(kPointerSizeLog2)); | |
| 490 Node* offset = IntPtrAdd(scaled_index, header_size); | 522 Node* offset = IntPtrAdd(scaled_index, header_size); |
| 491 return Load(MachineType::AnyTagged(), object, offset); | 523 return Load(MachineType::AnyTagged(), object, offset); |
| 492 } | 524 } |
| 493 | 525 |
| 494 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object, | 526 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object, |
| 495 Node* smi_index, | 527 Node* smi_index, |
| 496 int additional_offset) { | 528 int additional_offset) { |
| 497 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; | 529 int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize; |
| 498 Node* header_size = IntPtrConstant(additional_offset + | 530 Node* header_size = IntPtrConstant(additional_offset + |
| 499 FixedArray::kHeaderSize - kHeapObjectTag); | 531 FixedArray::kHeaderSize - kHeapObjectTag); |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 516 Node* CodeStubAssembler::StoreFixedArrayElementNoWriteBarrier(Node* object, | 548 Node* CodeStubAssembler::StoreFixedArrayElementNoWriteBarrier(Node* object, |
| 517 Node* index, | 549 Node* index, |
| 518 Node* value) { | 550 Node* value) { |
| 519 Node* offset = | 551 Node* offset = |
| 520 IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)), | 552 IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)), |
| 521 IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); | 553 IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 522 return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset, | 554 return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset, |
| 523 value); | 555 value); |
| 524 } | 556 } |
| 525 | 557 |
| 558 Node* CodeStubAssembler::StoreFixedArrayElementInt32Index(Node* object, | |
| 559 Node* index, | |
| 560 Node* value) { | |
| 561 if (raw_assembler_->machine()->Is64()) { | |
| 562 index = ChangeInt32ToInt64(index); | |
| 563 } | |
| 564 Node* offset = | |
| 565 IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)), | |
| 566 IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); | |
| 567 return Store(MachineRepresentation::kTagged, object, offset, value); | |
| 568 } | |
| 569 | |
| 526 Node* CodeStubAssembler::LoadRoot(Heap::RootListIndex root_index) { | 570 Node* CodeStubAssembler::LoadRoot(Heap::RootListIndex root_index) { |
| 527 if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) { | 571 if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) { |
| 528 Handle<Object> root = isolate()->heap()->root_handle(root_index); | 572 Handle<Object> root = isolate()->heap()->root_handle(root_index); |
| 529 if (root->IsSmi()) { | 573 if (root->IsSmi()) { |
| 530 return SmiConstant(Smi::cast(*root)); | 574 return SmiConstant(Smi::cast(*root)); |
| 531 } else { | 575 } else { |
| 532 return HeapConstant(Handle<HeapObject>::cast(root)); | 576 return HeapConstant(Handle<HeapObject>::cast(root)); |
| 533 } | 577 } |
| 534 } | 578 } |
| 535 | 579 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 StoreMapNoWriteBarrier(result, HeapNumberMapConstant()); | 709 StoreMapNoWriteBarrier(result, HeapNumberMapConstant()); |
| 666 return result; | 710 return result; |
| 667 } | 711 } |
| 668 | 712 |
| 669 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value) { | 713 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value) { |
| 670 Node* result = AllocateHeapNumber(); | 714 Node* result = AllocateHeapNumber(); |
| 671 StoreHeapNumberValue(result, value); | 715 StoreHeapNumberValue(result, value); |
| 672 return result; | 716 return result; |
| 673 } | 717 } |
| 674 | 718 |
| 719 Node* CodeStubAssembler::AllocateSeqOneByteString(int length) { | |
| 720 Node* result = Allocate(SeqOneByteString::SizeFor(length)); | |
| 721 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex)); | |
| 722 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, | |
| 723 SmiConstant(Smi::FromInt(length))); | |
| 724 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset, | |
| 725 IntPtrConstant(String::kEmptyHashField)); | |
| 726 return result; | |
| 727 } | |
| 728 | |
| 729 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) { | |
| 730 Node* result = Allocate(SeqTwoByteString::SizeFor(length)); | |
| 731 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex)); | |
| 732 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, | |
| 733 SmiConstant(Smi::FromInt(length))); | |
| 734 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset, | |
| 735 IntPtrConstant(String::kEmptyHashField)); | |
| 736 return result; | |
| 737 } | |
| 738 | |
| 675 Node* CodeStubAssembler::Load(MachineType rep, Node* base) { | 739 Node* CodeStubAssembler::Load(MachineType rep, Node* base) { |
| 676 return raw_assembler_->Load(rep, base); | 740 return raw_assembler_->Load(rep, base); |
| 677 } | 741 } |
| 678 | 742 |
| 679 Node* CodeStubAssembler::Load(MachineType rep, Node* base, Node* index) { | 743 Node* CodeStubAssembler::Load(MachineType rep, Node* base, Node* index) { |
| 680 return raw_assembler_->Load(rep, base, index); | 744 return raw_assembler_->Load(rep, base, index); |
| 681 } | 745 } |
| 682 | 746 |
| 683 Node* CodeStubAssembler::Store(MachineRepresentation rep, Node* base, | 747 Node* CodeStubAssembler::Store(MachineRepresentation rep, Node* base, |
| 684 Node* value) { | 748 Node* value) { |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 914 Callable callable = CodeFactory::NonNumberToNumber(isolate()); | 978 Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
| 915 var_value.Bind(CallStub(callable, context, value)); | 979 var_value.Bind(CallStub(callable, context, value)); |
| 916 Goto(&loop); | 980 Goto(&loop); |
| 917 } | 981 } |
| 918 } | 982 } |
| 919 } | 983 } |
| 920 Bind(&done_loop); | 984 Bind(&done_loop); |
| 921 return var_result.value(); | 985 return var_result.value(); |
| 922 } | 986 } |
| 923 | 987 |
| 988 Node* CodeStubAssembler::ToThisString(Node* context, Node* value, | |
| 989 char const* method_name) { | |
| 990 Variable var_value(this, MachineRepresentation::kTagged); | |
| 991 var_value.Bind(value); | |
| 992 | |
| 993 // Check if the {value} is a Smi or a HeapObject. | |
| 994 Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this), | |
| 995 if_valueisstring(this); | |
| 996 Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi); | |
| 997 Bind(&if_valueisnotsmi); | |
| 998 { | |
| 999 // Load the instance type of the {value}. | |
| 1000 Node* value_instance_type = LoadInstanceType(value); | |
| 1001 | |
| 1002 // Check if the {value} is already String. | |
| 1003 Label if_valueisnotstring(this, Label::kDeferred); | |
| 1004 Branch( | |
| 1005 Int32LessThan(value_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), | |
| 1006 &if_valueisstring, &if_valueisnotstring); | |
| 1007 Bind(&if_valueisnotstring); | |
| 1008 { | |
| 1009 // Check if the {value} is null. | |
| 1010 Label if_valueisnullorundefined(this, Label::kDeferred), | |
| 1011 if_valueisnotnullorundefined(this, Label::kDeferred), | |
| 1012 if_valueisnotnull(this, Label::kDeferred); | |
| 1013 Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined, | |
| 1014 &if_valueisnotnull); | |
| 1015 Bind(&if_valueisnotnull); | |
| 1016 { | |
| 1017 // Check if the {value} is undefined. | |
| 1018 Branch(WordEqual(value, UndefinedConstant()), | |
| 1019 &if_valueisnullorundefined, &if_valueisnotnullorundefined); | |
| 1020 Bind(&if_valueisnotnullorundefined); | |
| 1021 { | |
| 1022 // Convert the {value} to a String. | |
| 1023 Callable callable = CodeFactory::ToString(isolate()); | |
| 1024 var_value.Bind(CallStub(callable, context, value)); | |
| 1025 Goto(&if_valueisstring); | |
| 1026 } | |
| 1027 } | |
| 1028 | |
| 1029 Bind(&if_valueisnullorundefined); | |
| 1030 { | |
| 1031 // The {value} is either null or undefined. | |
| 1032 CallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context, | |
| 1033 HeapConstant(factory()->NewStringFromAsciiChecked( | |
| 1034 method_name, TENURED))); | |
| 1035 Goto(&if_valueisstring); // Never reached. | |
| 1036 } | |
| 1037 } | |
| 1038 } | |
| 1039 Bind(&if_valueissmi); | |
| 1040 { | |
| 1041 // The {value} is a Smi, convert it to a String. | |
| 1042 Callable callable = CodeFactory::NumberToString(isolate()); | |
| 1043 var_value.Bind(CallStub(callable, context, value)); | |
| 1044 Goto(&if_valueisstring); | |
| 1045 } | |
| 1046 Bind(&if_valueisstring); | |
| 1047 return var_value.value(); | |
| 1048 } | |
| 1049 | |
| 1050 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) { | |
| 1051 // Translate the {index} into a Word. | |
| 1052 index = SmiToWord(index); | |
| 1053 | |
| 1054 // We may need to loop in case of cons or sliced strings. | |
| 1055 Variable var_index(this, MachineType::PointerRepresentation()); | |
| 1056 Variable var_result(this, MachineRepresentation::kWord32); | |
| 1057 Variable var_string(this, MachineRepresentation::kTagged); | |
| 1058 Variable* loop_vars[] = {&var_index, &var_string}; | |
| 1059 Label done_loop(this, &var_result), loop(this, 2, loop_vars); | |
| 1060 var_string.Bind(string); | |
| 1061 var_index.Bind(index); | |
| 1062 Goto(&loop); | |
| 1063 Bind(&loop); | |
| 1064 { | |
| 1065 // Load the current {index}. | |
| 1066 index = var_index.value(); | |
| 1067 | |
| 1068 // Load the current {string}. | |
| 1069 string = var_string.value(); | |
| 1070 | |
| 1071 // Load the instance type of the {string}. | |
| 1072 Node* string_instance_type = LoadInstanceType(string); | |
| 1073 | |
| 1074 // Check if the {string} is a SeqString. | |
| 1075 Label if_stringissequential(this), if_stringisnotsequential(this); | |
| 1076 Branch(Word32Equal(Word32And(string_instance_type, | |
| 1077 Int32Constant(kStringRepresentationMask)), | |
| 1078 Int32Constant(kSeqStringTag)), | |
| 1079 &if_stringissequential, &if_stringisnotsequential); | |
| 1080 | |
| 1081 Bind(&if_stringissequential); | |
| 1082 { | |
| 1083 // Check if the {string} is a TwoByteSeqString or a OneByteSeqString. | |
| 1084 Label if_stringistwobyte(this), if_stringisonebyte(this); | |
| 1085 Branch(Word32Equal(Word32And(string_instance_type, | |
| 1086 Int32Constant(kStringEncodingMask)), | |
| 1087 Int32Constant(kTwoByteStringTag)), | |
| 1088 &if_stringistwobyte, &if_stringisonebyte); | |
| 1089 | |
| 1090 Bind(&if_stringisonebyte); | |
| 1091 { | |
| 1092 var_result.Bind( | |
| 1093 Load(MachineType::Uint8(), string, | |
| 1094 IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize - | |
| 1095 kHeapObjectTag)))); | |
| 1096 Goto(&done_loop); | |
| 1097 } | |
| 1098 | |
| 1099 Bind(&if_stringistwobyte); | |
| 1100 { | |
| 1101 var_result.Bind( | |
| 1102 Load(MachineType::Uint16(), string, | |
| 1103 IntPtrAdd(WordShl(index, IntPtrConstant(1)), | |
| 1104 IntPtrConstant(SeqTwoByteString::kHeaderSize - | |
| 1105 kHeapObjectTag)))); | |
| 1106 Goto(&done_loop); | |
| 1107 } | |
| 1108 } | |
| 1109 | |
| 1110 Bind(&if_stringisnotsequential); | |
| 1111 { | |
| 1112 // Check if the {string} is a ConsString. | |
| 1113 Label if_stringiscons(this), if_stringisnotcons(this); | |
| 1114 Branch(Word32Equal(Word32And(string_instance_type, | |
| 1115 Int32Constant(kStringRepresentationMask)), | |
| 1116 Int32Constant(kConsStringTag)), | |
| 1117 &if_stringiscons, &if_stringisnotcons); | |
| 1118 | |
| 1119 Bind(&if_stringiscons); | |
| 1120 { | |
| 1121 // Check whether the right hand side is the empty string (i.e. if | |
| 1122 // this is really a flat string in a cons string). If that is not | |
| 1123 // the case we flatten the string first. | |
| 1124 Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred); | |
| 1125 Node* rhs = LoadObjectField(string, ConsString::kSecondOffset); | |
| 1126 Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty, | |
| 1127 &if_rhsisnotempty); | |
| 1128 | |
| 1129 Bind(&if_rhsisempty); | |
| 1130 { | |
| 1131 // Just operate on the left hand side of the {string}. | |
| 1132 var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset)); | |
| 1133 Goto(&loop); | |
| 1134 } | |
| 1135 | |
| 1136 Bind(&if_rhsisnotempty); | |
| 1137 { | |
| 1138 // Flatten the {string} and lookup in the resulting string. | |
| 1139 var_string.Bind(CallRuntime(Runtime::kFlattenString, | |
| 1140 NoContextConstant(), string)); | |
| 1141 Goto(&loop); | |
| 1142 } | |
| 1143 } | |
| 1144 | |
| 1145 Bind(&if_stringisnotcons); | |
| 1146 { | |
| 1147 // Check if the {string} is an ExternalString. | |
| 1148 Label if_stringisexternal(this), if_stringisnotexternal(this); | |
| 1149 Branch(Word32Equal(Word32And(string_instance_type, | |
| 1150 Int32Constant(kStringRepresentationMask)), | |
| 1151 Int32Constant(kExternalStringTag)), | |
| 1152 &if_stringisexternal, &if_stringisnotexternal); | |
| 1153 | |
| 1154 Bind(&if_stringisexternal); | |
| 1155 { | |
| 1156 // Check if the {string} is a short external string. | |
| 1157 Label if_stringisshort(this), | |
| 1158 if_stringisnotshort(this, Label::kDeferred); | |
| 1159 Branch(Word32Equal(Word32And(string_instance_type, | |
| 1160 Int32Constant(kShortExternalStringMask)), | |
| 1161 Int32Constant(0)), | |
| 1162 &if_stringisshort, &if_stringisnotshort); | |
|
Igor Sheludko
2016/09/28 16:00:23
DBC: These label names are not in sync with the sh
| |
| 1163 | |
| 1164 Bind(&if_stringisshort); | |
| 1165 { | |
| 1166 // Load the actual resource data from the {string}. | |
| 1167 Node* string_resource_data = | |
| 1168 LoadObjectField(string, ExternalString::kResourceDataOffset, | |
| 1169 MachineType::Pointer()); | |
| 1170 | |
| 1171 // Check if the {string} is a TwoByteExternalString or a | |
| 1172 // OneByteExternalString. | |
| 1173 Label if_stringistwobyte(this), if_stringisonebyte(this); | |
| 1174 Branch(Word32Equal(Word32And(string_instance_type, | |
| 1175 Int32Constant(kStringEncodingMask)), | |
| 1176 Int32Constant(kTwoByteStringTag)), | |
| 1177 &if_stringistwobyte, &if_stringisonebyte); | |
| 1178 | |
| 1179 Bind(&if_stringisonebyte); | |
| 1180 { | |
| 1181 var_result.Bind( | |
| 1182 Load(MachineType::Uint8(), string_resource_data, index)); | |
| 1183 Goto(&done_loop); | |
| 1184 } | |
| 1185 | |
| 1186 Bind(&if_stringistwobyte); | |
| 1187 { | |
| 1188 var_result.Bind(Load(MachineType::Uint16(), string_resource_data, | |
| 1189 WordShl(index, IntPtrConstant(1)))); | |
| 1190 Goto(&done_loop); | |
| 1191 } | |
| 1192 } | |
| 1193 | |
| 1194 Bind(&if_stringisnotshort); | |
| 1195 { | |
| 1196 // The {string} might be compressed, call the runtime. | |
| 1197 var_result.Bind(SmiToWord32( | |
| 1198 CallRuntime(Runtime::kExternalStringGetChar, | |
| 1199 NoContextConstant(), string, SmiTag(index)))); | |
| 1200 Goto(&done_loop); | |
| 1201 } | |
| 1202 } | |
| 1203 | |
| 1204 Bind(&if_stringisnotexternal); | |
| 1205 { | |
| 1206 // The {string} is a SlicedString, continue with its parent. | |
| 1207 Node* string_offset = | |
| 1208 SmiToWord(LoadObjectField(string, SlicedString::kOffsetOffset)); | |
| 1209 Node* string_parent = | |
| 1210 LoadObjectField(string, SlicedString::kParentOffset); | |
| 1211 var_index.Bind(IntPtrAdd(index, string_offset)); | |
| 1212 var_string.Bind(string_parent); | |
| 1213 Goto(&loop); | |
| 1214 } | |
| 1215 } | |
| 1216 } | |
| 1217 } | |
| 1218 | |
| 1219 Bind(&done_loop); | |
| 1220 return var_result.value(); | |
| 1221 } | |
| 1222 | |
| 1223 Node* CodeStubAssembler::StringFromCharCode(Node* code) { | |
| 1224 Variable var_result(this, MachineRepresentation::kTagged); | |
| 1225 | |
| 1226 // Check if the {code} is a one-byte char code. | |
| 1227 Label if_codeisonebyte(this), if_codeistwobyte(this, Label::kDeferred), | |
| 1228 if_done(this); | |
| 1229 Branch(Int32LessThanOrEqual(code, Int32Constant(String::kMaxOneByteCharCode)), | |
| 1230 &if_codeisonebyte, &if_codeistwobyte); | |
| 1231 Bind(&if_codeisonebyte); | |
| 1232 { | |
| 1233 // Load the isolate wide single character string cache. | |
| 1234 Node* cache = LoadRoot(Heap::kSingleCharacterStringCacheRootIndex); | |
| 1235 | |
| 1236 // Check if we have an entry for the {code} in the single character string | |
| 1237 // cache already. | |
| 1238 Label if_entryisundefined(this, Label::kDeferred), | |
| 1239 if_entryisnotundefined(this); | |
| 1240 Node* entry = LoadFixedArrayElementInt32Index(cache, code); | |
| 1241 Branch(WordEqual(entry, UndefinedConstant()), &if_entryisundefined, | |
| 1242 &if_entryisnotundefined); | |
| 1243 | |
| 1244 Bind(&if_entryisundefined); | |
| 1245 { | |
| 1246 // Allocate a new SeqOneByteString for {code} and store it in the {cache}. | |
| 1247 Node* result = AllocateSeqOneByteString(1); | |
| 1248 StoreNoWriteBarrier( | |
| 1249 MachineRepresentation::kWord8, result, | |
| 1250 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), code); | |
| 1251 StoreFixedArrayElementInt32Index(cache, code, result); | |
| 1252 var_result.Bind(result); | |
| 1253 Goto(&if_done); | |
| 1254 } | |
| 1255 | |
| 1256 Bind(&if_entryisnotundefined); | |
| 1257 { | |
| 1258 // Return the entry from the {cache}. | |
| 1259 var_result.Bind(entry); | |
| 1260 Goto(&if_done); | |
| 1261 } | |
| 1262 } | |
| 1263 | |
| 1264 Bind(&if_codeistwobyte); | |
| 1265 { | |
| 1266 // Allocate a new SeqTwoByteString for {code}. | |
| 1267 Node* result = AllocateSeqTwoByteString(1); | |
| 1268 StoreNoWriteBarrier( | |
| 1269 MachineRepresentation::kWord16, result, | |
| 1270 IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), code); | |
| 1271 var_result.Bind(result); | |
| 1272 Goto(&if_done); | |
| 1273 } | |
| 1274 | |
| 1275 Bind(&if_done); | |
| 1276 return var_result.value(); | |
| 1277 } | |
| 1278 | |
| 924 void CodeStubAssembler::BranchIf(Node* condition, Label* if_true, | 1279 void CodeStubAssembler::BranchIf(Node* condition, Label* if_true, |
| 925 Label* if_false) { | 1280 Label* if_false) { |
| 926 Label if_condition_is_true(this), if_condition_is_false(this); | 1281 Label if_condition_is_true(this), if_condition_is_false(this); |
| 927 Branch(condition, &if_condition_is_true, &if_condition_is_false); | 1282 Branch(condition, &if_condition_is_true, &if_condition_is_false); |
| 928 Bind(&if_condition_is_true); | 1283 Bind(&if_condition_is_true); |
| 929 Goto(if_true); | 1284 Goto(if_true); |
| 930 Bind(&if_condition_is_false); | 1285 Bind(&if_condition_is_false); |
| 931 Goto(if_false); | 1286 Goto(if_false); |
| 932 } | 1287 } |
| 933 | 1288 |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1359 } | 1714 } |
| 1360 } | 1715 } |
| 1361 } | 1716 } |
| 1362 | 1717 |
| 1363 bound_ = true; | 1718 bound_ = true; |
| 1364 } | 1719 } |
| 1365 | 1720 |
| 1366 } // namespace compiler | 1721 } // namespace compiler |
| 1367 } // namespace internal | 1722 } // namespace internal |
| 1368 } // namespace v8 | 1723 } // namespace v8 |
| OLD | NEW |