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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
482 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { | 505 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) { |
483 return LoadObjectField(map, Map::kDescriptorsOffset); | 506 return LoadObjectField(map, Map::kDescriptorsOffset); |
484 } | 507 } |
485 | 508 |
486 Node* CodeStubAssembler::LoadNameHash(Node* name) { | 509 Node* CodeStubAssembler::LoadNameHash(Node* name) { |
487 return Load(MachineType::Uint32(), name, | 510 return Load(MachineType::Uint32(), name, |
488 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); | 511 IntPtrConstant(Name::kHashFieldOffset - kHeapObjectTag)); |
489 } | 512 } |
490 | 513 |
491 Node* CodeStubAssembler::LoadFixedArrayElementInt32Index( | 514 Node* CodeStubAssembler::LoadFixedArrayElementInt32Index( |
492 Node* object, Node* int32_index, int additional_offset) { | 515 Node* object, Node* index, int additional_offset) { |
493 Node* header_size = IntPtrConstant(additional_offset + | 516 Node* header_size = IntPtrConstant(additional_offset + |
494 FixedArray::kHeaderSize - kHeapObjectTag); | 517 FixedArray::kHeaderSize - kHeapObjectTag); |
495 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)); | |
496 Node* offset = IntPtrAdd(scaled_index, header_size); | 522 Node* offset = IntPtrAdd(scaled_index, header_size); |
497 return Load(MachineType::AnyTagged(), object, offset); | 523 return Load(MachineType::AnyTagged(), object, offset); |
498 } | 524 } |
499 | 525 |
500 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { | 526 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) { |
501 return Load(MachineType::Uint8(), map, | 527 return Load(MachineType::Uint8(), map, |
502 IntPtrConstant(Map::kInstanceSizeOffset - kHeapObjectTag)); | 528 IntPtrConstant(Map::kInstanceSizeOffset - kHeapObjectTag)); |
503 } | 529 } |
504 | 530 |
505 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object, | 531 Node* CodeStubAssembler::LoadFixedArrayElementSmiIndex(Node* object, |
(...skipping 21 matching lines...) Expand all Loading... | |
527 Node* CodeStubAssembler::StoreFixedArrayElementNoWriteBarrier(Node* object, | 553 Node* CodeStubAssembler::StoreFixedArrayElementNoWriteBarrier(Node* object, |
528 Node* index, | 554 Node* index, |
529 Node* value) { | 555 Node* value) { |
530 Node* offset = | 556 Node* offset = |
531 IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)), | 557 IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)), |
532 IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); | 558 IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); |
533 return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset, | 559 return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset, |
534 value); | 560 value); |
535 } | 561 } |
536 | 562 |
563 Node* CodeStubAssembler::StoreFixedArrayElementInt32Index(Node* object, | |
564 Node* index, | |
565 Node* value) { | |
566 if (raw_assembler_->machine()->Is64()) { | |
567 index = ChangeInt32ToInt64(index); | |
568 } | |
569 Node* offset = | |
570 IntPtrAdd(WordShl(index, IntPtrConstant(kPointerSizeLog2)), | |
571 IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag)); | |
572 return Store(MachineRepresentation::kTagged, object, offset, value); | |
573 } | |
574 | |
537 Node* CodeStubAssembler::LoadRoot(Heap::RootListIndex root_index) { | 575 Node* CodeStubAssembler::LoadRoot(Heap::RootListIndex root_index) { |
538 if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) { | 576 if (isolate()->heap()->RootCanBeTreatedAsConstant(root_index)) { |
539 Handle<Object> root = isolate()->heap()->root_handle(root_index); | 577 Handle<Object> root = isolate()->heap()->root_handle(root_index); |
540 if (root->IsSmi()) { | 578 if (root->IsSmi()) { |
541 return SmiConstant(Smi::cast(*root)); | 579 return SmiConstant(Smi::cast(*root)); |
542 } else { | 580 } else { |
543 return HeapConstant(Handle<HeapObject>::cast(root)); | 581 return HeapConstant(Handle<HeapObject>::cast(root)); |
544 } | 582 } |
545 } | 583 } |
546 | 584 |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
680 StoreMapNoWriteBarrier(result, HeapNumberMapConstant()); | 718 StoreMapNoWriteBarrier(result, HeapNumberMapConstant()); |
681 return result; | 719 return result; |
682 } | 720 } |
683 | 721 |
684 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value) { | 722 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value) { |
685 Node* result = AllocateHeapNumber(); | 723 Node* result = AllocateHeapNumber(); |
686 StoreHeapNumberValue(result, value); | 724 StoreHeapNumberValue(result, value); |
687 return result; | 725 return result; |
688 } | 726 } |
689 | 727 |
728 Node* CodeStubAssembler::AllocateSeqOneByteString(int length) { | |
729 Node* result = Allocate(SeqOneByteString::SizeFor(length)); | |
730 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kOneByteStringMapRootIndex)); | |
731 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset, | |
732 SmiConstant(Smi::FromInt(length))); | |
733 StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldOffset, | |
734 IntPtrConstant(String::kEmptyHashField)); | |
735 return result; | |
736 } | |
737 | |
738 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length) { | |
739 Node* result = Allocate(SeqTwoByteString::SizeFor(length)); | |
740 StoreMapNoWriteBarrier(result, LoadRoot(Heap::kStringMapRootIndex)); | |
741 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset, | |
742 SmiConstant(Smi::FromInt(length))); | |
743 StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldOffset, | |
744 IntPtrConstant(String::kEmptyHashField)); | |
745 return result; | |
746 } | |
747 | |
690 Node* CodeStubAssembler::Load(MachineType rep, Node* base) { | 748 Node* CodeStubAssembler::Load(MachineType rep, Node* base) { |
691 return raw_assembler_->Load(rep, base); | 749 return raw_assembler_->Load(rep, base); |
692 } | 750 } |
693 | 751 |
694 Node* CodeStubAssembler::Load(MachineType rep, Node* base, Node* index) { | 752 Node* CodeStubAssembler::Load(MachineType rep, Node* base, Node* index) { |
695 return raw_assembler_->Load(rep, base, index); | 753 return raw_assembler_->Load(rep, base, index); |
696 } | 754 } |
697 | 755 |
698 Node* CodeStubAssembler::Store(MachineRepresentation rep, Node* base, | 756 Node* CodeStubAssembler::Store(MachineRepresentation rep, Node* base, |
699 Node* value) { | 757 Node* value) { |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
929 Callable callable = CodeFactory::NonNumberToNumber(isolate()); | 987 Callable callable = CodeFactory::NonNumberToNumber(isolate()); |
930 var_value.Bind(CallStub(callable, context, value)); | 988 var_value.Bind(CallStub(callable, context, value)); |
931 Goto(&loop); | 989 Goto(&loop); |
932 } | 990 } |
933 } | 991 } |
934 } | 992 } |
935 Bind(&done_loop); | 993 Bind(&done_loop); |
936 return var_result.value(); | 994 return var_result.value(); |
937 } | 995 } |
938 | 996 |
997 Node* CodeStubAssembler::ToThisString(Node* context, Node* value, | |
998 char const* method_name) { | |
999 Variable var_value(this, MachineRepresentation::kTagged); | |
1000 var_value.Bind(value); | |
1001 | |
1002 // Check if the {value} is a Smi or a HeapObject. | |
1003 Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this), | |
1004 if_valueisstring(this); | |
1005 Branch(WordIsSmi(value), &if_valueissmi, &if_valueisnotsmi); | |
1006 Bind(&if_valueisnotsmi); | |
1007 { | |
1008 // Load the instance type of the {value}. | |
1009 Node* value_instance_type = LoadInstanceType(value); | |
1010 | |
1011 // Check if the {value} is already String. | |
1012 Label if_valueisnotstring(this, Label::kDeferred); | |
1013 Branch( | |
1014 Int32LessThan(value_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), | |
1015 &if_valueisstring, &if_valueisnotstring); | |
1016 Bind(&if_valueisnotstring); | |
1017 { | |
1018 // Check if the {value} is null. | |
1019 Label if_valueisnullorundefined(this, Label::kDeferred), | |
1020 if_valueisnotnullorundefined(this, Label::kDeferred), | |
1021 if_valueisnotnull(this, Label::kDeferred); | |
1022 Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined, | |
1023 &if_valueisnotnull); | |
1024 Bind(&if_valueisnotnull); | |
1025 { | |
1026 // Check if the {value} is undefined. | |
1027 Branch(WordEqual(value, UndefinedConstant()), | |
1028 &if_valueisnullorundefined, &if_valueisnotnullorundefined); | |
1029 Bind(&if_valueisnotnullorundefined); | |
1030 { | |
1031 // Convert the {value} to a String. | |
1032 Callable callable = CodeFactory::ToString(isolate()); | |
1033 var_value.Bind(CallStub(callable, context, value)); | |
1034 Goto(&if_valueisstring); | |
1035 } | |
1036 } | |
1037 | |
1038 Bind(&if_valueisnullorundefined); | |
1039 { | |
1040 // The {value} is either null or undefined. | |
1041 CallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context, | |
1042 HeapConstant(factory()->NewStringFromAsciiChecked( | |
1043 "String.prototype.charCodeAt", TENURED))); | |
1044 Goto(&if_valueisstring); // Never reached. | |
1045 } | |
1046 } | |
1047 } | |
1048 Bind(&if_valueissmi); | |
1049 { | |
1050 // The {value} is a Smi, convert it to a String. | |
1051 Callable callable = CodeFactory::NumberToString(isolate()); | |
1052 var_value.Bind(CallStub(callable, context, value)); | |
1053 Goto(&if_valueisstring); | |
1054 } | |
1055 Bind(&if_valueisstring); | |
1056 return var_value.value(); | |
1057 } | |
1058 | |
1059 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index) { | |
1060 // Translate the {index} into a Word. | |
1061 index = SmiToWord(index); | |
1062 | |
1063 // We may need to loop in case of cons or sliced strings. | |
1064 Variable var_index(this, MachineType::PointerRepresentation()); | |
1065 Variable var_result(this, MachineRepresentation::kWord32); | |
1066 Variable var_string(this, MachineRepresentation::kTagged); | |
1067 Variable* loop_vars[] = {&var_index, &var_string}; | |
1068 Label done_loop(this, &var_result), loop(this, 2, loop_vars); | |
1069 var_string.Bind(string); | |
1070 var_index.Bind(index); | |
1071 Goto(&loop); | |
1072 Bind(&loop); | |
1073 { | |
1074 // Load the current {index}. | |
1075 index = var_index.value(); | |
1076 | |
1077 // Load the current {string}. | |
1078 string = var_string.value(); | |
1079 | |
1080 // Load the instance type of the {string}. | |
1081 Node* string_instance_type = LoadInstanceType(string); | |
1082 | |
1083 // Check if the {string} is a SeqString. | |
1084 Label if_stringissequential(this), if_stringisnotsequential(this); | |
1085 Branch(Word32Equal(Word32And(string_instance_type, | |
1086 Int32Constant(kStringRepresentationMask)), | |
1087 Int32Constant(kSeqStringTag)), | |
1088 &if_stringissequential, &if_stringisnotsequential); | |
1089 | |
1090 Bind(&if_stringissequential); | |
1091 { | |
1092 // Check if the {string} is a TwoByteSeqString or a OneByteSeqString. | |
1093 Label if_stringistwobyte(this), if_stringisonebyte(this); | |
1094 Branch(Word32Equal(Word32And(string_instance_type, | |
1095 Int32Constant(kStringEncodingMask)), | |
1096 Int32Constant(kTwoByteStringTag)), | |
1097 &if_stringistwobyte, &if_stringisonebyte); | |
1098 | |
1099 Bind(&if_stringisonebyte); | |
1100 { | |
1101 var_result.Bind( | |
1102 Load(MachineType::Uint8(), string, | |
1103 IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize - | |
1104 kHeapObjectTag)))); | |
1105 Goto(&done_loop); | |
1106 } | |
1107 | |
1108 Bind(&if_stringistwobyte); | |
1109 { | |
1110 var_result.Bind( | |
1111 Load(MachineType::Uint16(), string, | |
1112 IntPtrAdd(WordShl(index, IntPtrConstant(1)), | |
1113 IntPtrConstant(SeqTwoByteString::kHeaderSize - | |
1114 kHeapObjectTag)))); | |
1115 Goto(&done_loop); | |
1116 } | |
1117 } | |
1118 | |
1119 Bind(&if_stringisnotsequential); | |
1120 { | |
1121 // Check if the {string} is a ConsString. | |
1122 Label if_stringiscons(this), if_stringisnotcons(this); | |
1123 Branch(Word32Equal(Word32And(string_instance_type, | |
1124 Int32Constant(kStringRepresentationMask)), | |
1125 Int32Constant(kConsStringTag)), | |
1126 &if_stringiscons, &if_stringisnotcons); | |
1127 | |
1128 Bind(&if_stringiscons); | |
1129 { | |
1130 // Check whether the right hand side is the empty string (i.e. if | |
1131 // this is really a flat string in a cons string). If that is not | |
1132 // the case we flatten the string first. | |
1133 Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred); | |
1134 Node* rhs = LoadObjectField(string, ConsString::kSecondOffset); | |
1135 Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty, | |
1136 &if_rhsisnotempty); | |
1137 | |
1138 Bind(&if_rhsisempty); | |
1139 { | |
1140 // Just operate on the left hand side of the {string}. | |
1141 var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset)); | |
1142 Goto(&loop); | |
1143 } | |
1144 | |
1145 Bind(&if_rhsisnotempty); | |
1146 { | |
1147 // Flatten the {string} and lookup in the resulting string. | |
1148 var_string.Bind(CallRuntime(Runtime::kFlattenString, | |
1149 NoContextConstant(), string)); | |
1150 Goto(&loop); | |
1151 } | |
1152 } | |
1153 | |
1154 Bind(&if_stringisnotcons); | |
1155 { | |
1156 // Check if the {string} is an ExternalString. | |
1157 Label if_stringisexternal(this), if_stringisnotexternal(this); | |
1158 Branch(Word32Equal(Word32And(string_instance_type, | |
1159 Int32Constant(kStringRepresentationMask)), | |
1160 Int32Constant(kExternalStringTag)), | |
1161 &if_stringisexternal, &if_stringisnotexternal); | |
1162 | |
1163 Bind(&if_stringisexternal); | |
1164 { | |
1165 // Check if the {string} is a short external string. | |
1166 Label if_stringisshort(this), | |
1167 if_stringisnotshort(this, Label::kDeferred); | |
1168 Branch(Word32Equal(Word32And(string_instance_type, | |
1169 Int32Constant(kShortExternalStringMask)), | |
1170 Int32Constant(0)), | |
1171 &if_stringisshort, &if_stringisnotshort); | |
1172 | |
1173 Bind(&if_stringisshort); | |
1174 { | |
1175 // Load the actual resource data from the {string}. | |
1176 Node* string_resource_data = | |
1177 LoadObjectField(string, ExternalString::kResourceDataOffset, | |
1178 MachineType::Pointer()); | |
1179 | |
1180 // Check if the {string} is a TwoByteExternalString or a | |
1181 // OneByteExternalString. | |
1182 Label if_stringistwobyte(this), if_stringisonebyte(this); | |
1183 Branch(Word32Equal(Word32And(string_instance_type, | |
1184 Int32Constant(kStringEncodingMask)), | |
1185 Int32Constant(kTwoByteStringTag)), | |
1186 &if_stringistwobyte, &if_stringisonebyte); | |
1187 | |
1188 Bind(&if_stringisonebyte); | |
1189 { | |
1190 var_result.Bind( | |
1191 Load(MachineType::Uint8(), string_resource_data, index)); | |
1192 Goto(&done_loop); | |
1193 } | |
1194 | |
1195 Bind(&if_stringistwobyte); | |
1196 { | |
1197 var_result.Bind(Load(MachineType::Uint16(), string_resource_data, | |
1198 WordShl(index, IntPtrConstant(1)))); | |
1199 Goto(&done_loop); | |
1200 } | |
1201 } | |
1202 | |
1203 Bind(&if_stringisnotshort); | |
1204 { | |
1205 // The {string} might be compressed, call the runtime. | |
1206 var_result.Bind(SmiToWord32( | |
1207 CallRuntime(Runtime::kExternalStringGetChar, | |
1208 NoContextConstant(), string, SmiTag(index)))); | |
1209 Goto(&done_loop); | |
1210 } | |
1211 } | |
1212 | |
1213 Bind(&if_stringisnotexternal); | |
1214 { | |
1215 // The {string} is a SlicedString, continue with its parent. | |
1216 Node* string_offset = | |
1217 SmiToWord(LoadObjectField(string, SlicedString::kOffsetOffset)); | |
1218 Node* string_parent = | |
1219 LoadObjectField(string, SlicedString::kParentOffset); | |
1220 var_index.Bind(IntPtrAdd(index, string_offset)); | |
1221 var_string.Bind(string_parent); | |
1222 Goto(&loop); | |
1223 } | |
1224 } | |
1225 } | |
1226 } | |
1227 | |
1228 Bind(&done_loop); | |
1229 return var_result.value(); | |
1230 } | |
1231 | |
1232 Node* CodeStubAssembler::StringFromCharCode(Node* code) { | |
1233 Variable var_result(this, MachineRepresentation::kTagged); | |
1234 | |
1235 // Check if the {code} is a one-byte char code. | |
1236 Label if_codeisonebyte(this), if_codeistwobyte(this, Label::kDeferred), | |
1237 if_done(this); | |
1238 Branch(Int32LessThanOrEqual(code, Int32Constant(String::kMaxOneByteCharCode)), | |
1239 &if_codeisonebyte, &if_codeistwobyte); | |
1240 Bind(&if_codeisonebyte); | |
1241 { | |
1242 // Load the isolate wide single character string cache. | |
1243 Node* cache = LoadRoot(Heap::kSingleCharacterStringCacheRootIndex); | |
1244 | |
1245 // Check if we have an entry for the {code} in the single character string | |
1246 // cache already. | |
1247 Label if_entryisundefined(this, Label::kDeferred), | |
1248 if_entryisnotundefined(this); | |
1249 Node* entry = LoadFixedArrayElementInt32Index(cache, code); | |
1250 Branch(WordEqual(entry, UndefinedConstant()), &if_entryisundefined, | |
1251 &if_entryisnotundefined); | |
1252 | |
1253 Bind(&if_entryisundefined); | |
1254 { | |
1255 // Allocate a new SeqOneByteString for {code} and store it in the {cache}. | |
1256 Node* result = AllocateSeqOneByteString(1); | |
1257 StoreNoWriteBarrier( | |
1258 MachineRepresentation::kWord8, result, | |
1259 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), code); | |
1260 StoreFixedArrayElementInt32Index(cache, code, result); | |
1261 var_result.Bind(result); | |
1262 Goto(&if_done); | |
1263 } | |
1264 | |
1265 Bind(&if_entryisnotundefined); | |
1266 { | |
1267 // Allocate a new SeqTwoByteString for {code}. | |
epertoso
2016/04/07 14:31:10
Is this correct? There's an entry in the cache in
Benedikt Meurer
2016/04/08 04:18:42
Ah, damn copy&paste. It should use the entry obvio
| |
1268 Node* result = AllocateSeqTwoByteString(1); | |
1269 StoreNoWriteBarrier( | |
1270 MachineRepresentation::kWord16, result, | |
1271 IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), code); | |
1272 var_result.Bind(result); | |
1273 Goto(&if_done); | |
1274 } | |
1275 } | |
1276 | |
1277 Bind(&if_codeistwobyte); | |
1278 { | |
1279 var_result.Bind(CallRuntime(Runtime::kStringCharFromCode, | |
1280 NoContextConstant(), SmiFromWord32(code))); | |
1281 Goto(&if_done); | |
1282 } | |
1283 | |
1284 Bind(&if_done); | |
1285 return var_result.value(); | |
1286 } | |
1287 | |
939 void CodeStubAssembler::BranchIf(Node* condition, Label* if_true, | 1288 void CodeStubAssembler::BranchIf(Node* condition, Label* if_true, |
940 Label* if_false) { | 1289 Label* if_false) { |
941 Label if_condition_is_true(this), if_condition_is_false(this); | 1290 Label if_condition_is_true(this), if_condition_is_false(this); |
942 Branch(condition, &if_condition_is_true, &if_condition_is_false); | 1291 Branch(condition, &if_condition_is_true, &if_condition_is_false); |
943 Bind(&if_condition_is_true); | 1292 Bind(&if_condition_is_true); |
944 Goto(if_true); | 1293 Goto(if_true); |
945 Bind(&if_condition_is_false); | 1294 Bind(&if_condition_is_false); |
946 Goto(if_false); | 1295 Goto(if_false); |
947 } | 1296 } |
948 | 1297 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1374 } | 1723 } |
1375 } | 1724 } |
1376 } | 1725 } |
1377 | 1726 |
1378 bound_ = true; | 1727 bound_ = true; |
1379 } | 1728 } |
1380 | 1729 |
1381 } // namespace compiler | 1730 } // namespace compiler |
1382 } // namespace internal | 1731 } // namespace internal |
1383 } // namespace v8 | 1732 } // namespace v8 |
OLD | NEW |