[stubs] Port LoadIndexedStringStub to CSA

BUG=v8:5269

Review-Url: https://codereview.chromium.org/2682153003
Cr-Commit-Position: refs/heads/master@{#43071}
This commit is contained in:
jkummerow 2017-02-09 10:50:21 -08:00 committed by Commit bot
parent 1837cf4964
commit 63b980f996
15 changed files with 28 additions and 770 deletions

View File

@ -1169,39 +1169,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is in lr.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = r5;
Register result = r0;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadWithVectorDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1849,45 +1816,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiShiftSize == 0);
DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
__ tst(code_, Operand(kSmiTagMask |
((~String::kMaxOneByteCharCodeU) << kSmiTagSize)));
__ b(ne, &slow_case_);
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
// At this point code register contains smi tagged one-byte char code.
__ add(result_, result_, Operand::PointerOffsetFromSmiKey(code_));
__ ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
__ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
__ b(eq, &slow_case_);
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
__ Move(result_, r0);
call_helper.AfterCall(masm);
__ jmp(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(
MacroAssembler* masm, Register left, Register right, Register scratch1,
Register scratch2, Register scratch3) {

View File

@ -1285,39 +1285,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is in lr.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register result = x0;
Register scratch = x10;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadWithVectorDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ Bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
#ifdef V8_INTERPRETED_REGEXP
__ TailCallRuntime(Runtime::kRegExpExec);
@ -2056,38 +2023,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
__ JumpIfNotSmi(code_, &slow_case_);
__ Cmp(code_, Smi::FromInt(String::kMaxOneByteCharCode));
__ B(hi, &slow_case_);
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
// At this point code register contains smi tagged one-byte char code.
__ Add(result_, result_, Operand::UntagSmiAndScale(code_, kPointerSizeLog2));
__ Ldr(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
__ JumpIfRoot(result_, Heap::kUndefinedValueRootIndex, &slow_case_);
__ Bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ Bind(&slow_case_);
call_helper.BeforeCall(masm);
__ Push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
__ Mov(result_, x0);
call_helper.AfterCall(masm);
__ B(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void CompareICStub::GenerateBooleans(MacroAssembler* masm) {
// Inputs are in x0 (lhs) and x1 (rhs).
DCHECK_EQ(CompareICState::BOOLEAN, state());

View File

@ -213,14 +213,10 @@ namespace internal {
"Unexpected ElementsKind in array constructor") \
V(kUnexpectedFallthroughFromCharCodeAtSlowCase, \
"Unexpected fallthrough from CharCodeAt slow case") \
V(kUnexpectedFallthroughFromCharFromCodeSlowCase, \
"Unexpected fallthrough from CharFromCode slow case") \
V(kUnexpectedFallThroughFromStringComparison, \
"Unexpected fall-through from string comparison") \
V(kUnexpectedFallthroughToCharCodeAtSlowCase, \
"Unexpected fallthrough to CharCodeAt slow case") \
V(kUnexpectedFallthroughToCharFromCodeSlowCase, \
"Unexpected fallthrough to CharFromCode slow case") \
V(kUnexpectedFPUStackDepthAfterInstruction, \
"Unexpected FPU stack depth after instruction") \
V(kUnexpectedInitialMapForArrayFunction1, \

View File

@ -12,6 +12,30 @@
namespace v8 {
namespace internal {
TF_BUILTIN(KeyedLoadIC_IndexedString, CodeStubAssembler) {
typedef LoadWithVectorDescriptor Descriptor;
Node* receiver = Parameter(Descriptor::kReceiver);
Node* index = Parameter(Descriptor::kName);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
Label miss(this);
Node* index_intptr = TryToIntptr(index, &miss);
Node* length = SmiUntag(LoadStringLength(receiver));
GotoIf(UintPtrGreaterThanOrEqual(index_intptr, length), &miss);
Node* code = StringCharCodeAt(receiver, index_intptr, INTPTR_PARAMETERS);
Node* result = StringFromCharCode(code);
Return(result);
Bind(&miss);
TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, index, slot,
vector);
}
TF_BUILTIN(KeyedLoadIC_Miss, CodeStubAssembler) {
typedef LoadWithVectorDescriptor Descriptor;

View File

@ -417,8 +417,7 @@ TF_BUILTIN(StringCharAt, CodeStubAssembler) {
Node* position = Parameter(1);
// Load the character code at the {position} from the {receiver}.
Node* code = StringCharCodeAt(receiver, position,
CodeStubAssembler::INTPTR_PARAMETERS);
Node* code = StringCharCodeAt(receiver, position, INTPTR_PARAMETERS);
// And return the single character string with only that {code}
Node* result = StringFromCharCode(code);
@ -430,8 +429,7 @@ TF_BUILTIN(StringCharCodeAt, CodeStubAssembler) {
Node* position = Parameter(1);
// Load the character code at the {position} from the {receiver}.
Node* code = StringCharCodeAt(receiver, position,
CodeStubAssembler::INTPTR_PARAMETERS);
Node* code = StringCharCodeAt(receiver, position, INTPTR_PARAMETERS);
// And return it as TaggedSigned value.
// TODO(turbofan): Allow builtins to return values untagged.

View File

@ -233,6 +233,7 @@ class Isolate;
TFS(KeyedLoadIC_Megamorphic, BUILTIN, kNoExtraICState, LoadWithVector, 1) \
TFS(KeyedLoadIC_Miss, BUILTIN, kNoExtraICState, LoadWithVector, 1) \
TFS(KeyedLoadIC_Slow, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \
TFS(KeyedLoadIC_IndexedString, HANDLER, Code::LOAD_IC, LoadWithVector, 1) \
TFS(KeyedStoreIC_Megamorphic, BUILTIN, kNoExtraICState, StoreWithVector, 1) \
TFS(KeyedStoreIC_Megamorphic_Strict, BUILTIN, kNoExtraICState, \
StoreWithVector, 1) \

View File

@ -41,7 +41,6 @@ class Node;
V(FunctionPrototype) \
V(InternalArrayConstructor) \
V(JSEntry) \
V(LoadIndexedString) \
V(MathPow) \
V(ProfileEntryHook) \
V(RecordWrite) \
@ -893,19 +892,6 @@ class FunctionPrototypeStub : public PlatformCodeStub {
DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
};
class LoadIndexedStringStub : public PlatformCodeStub {
public:
explicit LoadIndexedStringStub(Isolate* isolate)
: PlatformCodeStub(isolate) {}
Code::Kind GetCodeKind() const override { return Code::HANDLER; }
ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
};
class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
public:
explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
@ -1383,13 +1369,6 @@ class StringCharCodeAtGenerator {
void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper);
// Skip handling slow case and directly jump to bailout.
void SkipSlow(MacroAssembler* masm, Label* bailout) {
masm->bind(&index_not_smi_);
masm->bind(&call_runtime_);
masm->jmp(bailout);
}
private:
Register object_;
Register index_;
@ -1409,94 +1388,6 @@ class StringCharCodeAtGenerator {
DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
};
// Generates code for creating a one-char string from a char code.
class StringCharFromCodeGenerator {
public:
StringCharFromCodeGenerator(Register code,
Register result)
: code_(code),
result_(result) {
DCHECK(!code_.is(result_));
}
// Generates the fast case code. On the fallthrough path |result|
// register contains the result.
void GenerateFast(MacroAssembler* masm);
// Generates the slow case code. Must not be naturally
// reachable. Expected to be put after a ret instruction (e.g., in
// deferred code). Always jumps back to the fast case.
void GenerateSlow(MacroAssembler* masm,
const RuntimeCallHelper& call_helper);
// Skip handling slow case and directly jump to bailout.
void SkipSlow(MacroAssembler* masm, Label* bailout) {
masm->bind(&slow_case_);
masm->jmp(bailout);
}
private:
Register code_;
Register result_;
Label slow_case_;
Label exit_;
DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
};
// Generates code implementing String.prototype.charAt.
//
// Only supports the case when the receiver is a string and the index
// is a number (smi or heap number) that is a valid index into the
// string. Additional index constraints are specified by the
// flags. Otherwise, bails out to the provided labels.
//
// Register usage: |object| may be changed to another string in a way
// that doesn't affect charCodeAt/charAt semantics, |index| is
// preserved, |scratch1|, |scratch2|, and |result| are clobbered.
class StringCharAtGenerator {
public:
StringCharAtGenerator(Register object, Register index, Register scratch,
Register result, Label* receiver_not_string,
Label* index_not_number, Label* index_out_of_range,
ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
: char_code_at_generator_(object, index, scratch, receiver_not_string,
index_not_number, index_out_of_range,
check_mode),
char_from_code_generator_(scratch, result) {}
// Generates the fast case code. On the fallthrough path |result|
// register contains the result.
void GenerateFast(MacroAssembler* masm) {
char_code_at_generator_.GenerateFast(masm);
char_from_code_generator_.GenerateFast(masm);
}
// Generates the slow case code. Must not be naturally
// reachable. Expected to be put after a ret instruction (e.g., in
// deferred code). Always jumps back to the fast case.
void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
const RuntimeCallHelper& call_helper) {
char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
char_from_code_generator_.GenerateSlow(masm, call_helper);
}
// Skip handling slow case and directly jump to bailout.
void SkipSlow(MacroAssembler* masm, Label* bailout) {
char_code_at_generator_.SkipSlow(masm, bailout);
char_from_code_generator_.SkipSlow(masm, bailout);
}
private:
StringCharCodeAtGenerator char_code_at_generator_;
StringCharFromCodeGenerator char_from_code_generator_;
DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
};
class CallICTrampolineStub : public TurboFanCodeStub {
public:
CallICTrampolineStub(Isolate* isolate, ConvertReceiverMode convert_mode,

View File

@ -479,40 +479,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is on the stack.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = edi;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
Register result = eax;
DCHECK(!result.is(scratch));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ ret(0);
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1781,52 +1747,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiShiftSize == 0);
DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
__ test(code_, Immediate(kSmiTagMask |
((~String::kMaxOneByteCharCodeU) << kSmiTagSize)));
__ j(not_zero, &slow_case_);
Factory* factory = masm->isolate()->factory();
__ Move(result_, Immediate(factory->single_character_string_cache()));
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
STATIC_ASSERT(kSmiShiftSize == 0);
// At this point code register contains smi tagged one byte char code.
__ mov(result_, FieldOperand(result_,
code_, times_half_pointer_size,
FixedArray::kHeaderSize));
__ cmp(result_, factory->undefined_value());
__ j(equal, &slow_case_);
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
if (!result_.is(eax)) {
__ mov(result_, eax);
}
call_helper.AfterCall(masm);
__ jmp(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,

View File

@ -352,7 +352,7 @@ Handle<Object> ElementHandlerCompiler::GetKeyedLoadHandler(
}
if (receiver_map->IsStringMap()) {
TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedStringStub);
return LoadIndexedStringStub(isolate).GetCode();
return isolate->builtins()->KeyedLoadIC_IndexedString();
}
InstanceType instance_type = receiver_map->instance_type();
if (instance_type < FIRST_JS_RECEIVER_TYPE) {

View File

@ -1277,35 +1277,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ Jump(ra);
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is in ra.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = t1;
Register result = v0;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()));
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
@ -1990,51 +1961,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
DCHECK(!t0.is(result_));
DCHECK(!t0.is(code_));
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiShiftSize == 0);
DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
__ And(t0, code_, Operand(kSmiTagMask |
((~String::kMaxOneByteCharCodeU) << kSmiTagSize)));
__ Branch(&slow_case_, ne, t0, Operand(zero_reg));
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
// At this point code register contains smi tagged one-byte char code.
STATIC_ASSERT(kSmiTag == 0);
__ Lsa(result_, result_, code_, kPointerSizeLog2 - kSmiTagSize);
__ lw(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
__ LoadRoot(t0, Heap::kUndefinedValueRootIndex);
__ Branch(&slow_case_, eq, result_, Operand(t0));
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
__ Move(result_, v0);
call_helper.AfterCall(masm);
__ Branch(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(
MacroAssembler* masm, Register left, Register right, Register scratch1,
Register scratch2, Register scratch3) {

View File

@ -1272,35 +1272,6 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ Jump(ra);
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is in ra.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = a5;
Register result = v0;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()));
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
@ -1998,44 +1969,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
__ JumpIfNotSmi(code_, &slow_case_);
__ Branch(&slow_case_, hi, code_,
Operand(Smi::FromInt(String::kMaxOneByteCharCode)));
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
// At this point code register contains smi tagged one_byte char code.
__ SmiScale(at, code_, kPointerSizeLog2);
__ Daddu(result_, result_, at);
__ ld(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(&slow_case_, eq, result_, Operand(at));
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
__ Move(result_, v0);
call_helper.AfterCall(masm);
__ Branch(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(
MacroAssembler* masm, Register left, Register right, Register scratch1,
Register scratch2, Register scratch3) {

View File

@ -1236,39 +1236,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is in lr.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = r8;
Register result = r3;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadWithVectorDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1945,46 +1912,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
__ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxOneByteCharCodeU));
__ ori(r0, r0, Operand(kSmiTagMask));
__ and_(r0, code_, r0, SetRC);
__ bne(&slow_case_, cr0);
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
// At this point code register contains smi tagged one-byte char code.
__ mr(r0, code_);
__ SmiToPtrArrayOffset(code_, code_);
__ add(result_, result_, code_);
__ mr(code_, r0);
__ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
__ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
__ beq(&slow_case_);
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
__ Move(result_, r3);
call_helper.AfterCall(masm);
__ b(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,

View File

@ -1234,37 +1234,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is in lr.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = r7;
Register result = r2;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadWithVectorDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ Ret();
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1945,44 +1914,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
__ LoadSmiLiteral(r0, Smi::FromInt(~String::kMaxOneByteCharCodeU));
__ OrP(r0, r0, Operand(kSmiTagMask));
__ AndP(r0, code_, r0);
__ bne(&slow_case_);
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
// At this point code register contains smi tagged one-byte char code.
__ LoadRR(r0, code_);
__ SmiToPtrArrayOffset(code_, code_);
__ AddP(result_, code_);
__ LoadRR(code_, r0);
__ LoadP(result_, FieldMemOperand(result_, FixedArray::kHeaderSize));
__ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
__ beq(&slow_case_);
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
__ Move(result_, r2);
call_helper.AfterCall(masm);
__ b(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,

View File

@ -360,39 +360,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is on the stack.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = rdi;
Register result = rax;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ ret(0);
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1741,44 +1708,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
__ JumpIfNotSmi(code_, &slow_case_);
__ SmiCompare(code_, Smi::FromInt(String::kMaxOneByteCharCode));
__ j(above, &slow_case_);
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
SmiIndex index = masm->SmiToIndex(kScratchRegister, code_, kPointerSizeLog2);
__ movp(result_, FieldOperand(result_, index.reg, index.scale,
FixedArray::kHeaderSize));
__ CompareRoot(result_, Heap::kUndefinedValueRootIndex);
__ j(equal, &slow_case_);
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ Push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
if (!result_.is(rax)) {
__ movp(result_, rax);
}
call_helper.AfterCall(masm);
__ jmp(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,

View File

@ -299,41 +299,6 @@ void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
masm, PropertyAccessCompiler::MissBuiltin(Code::LOAD_IC));
}
void LoadIndexedStringStub::Generate(MacroAssembler* masm) {
// Return address is on the stack.
Label miss;
Register receiver = LoadDescriptor::ReceiverRegister();
Register index = LoadDescriptor::NameRegister();
Register scratch = edi;
DCHECK(!scratch.is(receiver) && !scratch.is(index));
Register result = eax;
DCHECK(!result.is(scratch));
DCHECK(!scratch.is(LoadWithVectorDescriptor::VectorRegister()) &&
result.is(LoadDescriptor::SlotRegister()));
// StringCharAtGenerator doesn't use the result register until it's passed
// the different miss possibilities. If it did, we would have a conflict
// when FLAG_vector_ics is true.
StringCharAtGenerator char_at_generator(receiver, index, scratch, result,
&miss, // When not a string.
&miss, // When not a number.
&miss, // When index out of range.
RECEIVER_IS_STRING);
char_at_generator.GenerateFast(masm);
__ ret(0);
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper);
__ bind(&miss);
PropertyAccessCompiler::TailCallBuiltin(
masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
}
void RegExpExecStub::Generate(MacroAssembler* masm) {
// Just jump directly to runtime if native RegExp is not selected at compile
// time or if regexp entry in generated code is turned off runtime switch or
@ -1829,52 +1794,6 @@ void StringCharCodeAtGenerator::GenerateSlow(
__ Abort(kUnexpectedFallthroughFromCharCodeAtSlowCase);
}
// -------------------------------------------------------------------------
// StringCharFromCodeGenerator
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
// Fast case of Heap::LookupSingleCharacterStringFromCode.
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiShiftSize == 0);
DCHECK(base::bits::IsPowerOfTwo32(String::kMaxOneByteCharCodeU + 1));
__ test(code_, Immediate(kSmiTagMask |
((~String::kMaxOneByteCharCodeU) << kSmiTagSize)));
__ j(not_zero, &slow_case_);
Factory* factory = masm->isolate()->factory();
__ Move(result_, Immediate(factory->single_character_string_cache()));
STATIC_ASSERT(kSmiTag == 0);
STATIC_ASSERT(kSmiTagSize == 1);
STATIC_ASSERT(kSmiShiftSize == 0);
// At this point code register contains smi tagged one byte char code.
__ mov(result_, FieldOperand(result_,
code_, times_half_pointer_size,
FixedArray::kHeaderSize));
__ cmp(result_, factory->undefined_value());
__ j(equal, &slow_case_);
__ bind(&exit_);
}
void StringCharFromCodeGenerator::GenerateSlow(
MacroAssembler* masm,
const RuntimeCallHelper& call_helper) {
__ Abort(kUnexpectedFallthroughToCharFromCodeSlowCase);
__ bind(&slow_case_);
call_helper.BeforeCall(masm);
__ push(code_);
__ CallRuntime(Runtime::kStringCharFromCode);
if (!result_.is(eax)) {
__ mov(result_, eax);
}
call_helper.AfterCall(masm);
__ jmp(&exit_);
__ Abort(kUnexpectedFallthroughFromCharFromCodeSlowCase);
}
void StringHelper::GenerateFlatOneByteStringEquals(MacroAssembler* masm,
Register left,
Register right,