Remove special charAt and charCodeAt handling in the ICs.
R=mvstanton@chromium.org Review URL: https://codereview.chromium.org/136443006 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18663 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ef52aeb701
commit
e9f957ce2c
@ -1889,138 +1889,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
||||
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = r0;
|
||||
Register index = r4;
|
||||
Register result = r1;
|
||||
const int argc = arguments().immediate();
|
||||
__ ldr(receiver, MemOperand(sp, argc * kPointerSize));
|
||||
if (argc > 0) {
|
||||
__ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
|
||||
} else {
|
||||
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
StringCharCodeAtGenerator generator(receiver,
|
||||
index,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ Drop(argc + 1);
|
||||
__ mov(r0, result);
|
||||
__ Ret();
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(r0, Heap::kNanValueRootIndex);
|
||||
__ Drop(argc + 1);
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in r2.
|
||||
__ Move(r2, name);
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
||||
|
||||
const int argc = arguments().immediate();
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = r0;
|
||||
Register index = r4;
|
||||
Register scratch = r3;
|
||||
Register result = r1;
|
||||
if (argc > 0) {
|
||||
__ ldr(index, MemOperand(sp, (argc - 1) * kPointerSize));
|
||||
} else {
|
||||
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
StringCharAtGenerator generator(receiver,
|
||||
index,
|
||||
scratch,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ Drop(argc + 1);
|
||||
__ mov(r0, result);
|
||||
__ Ret();
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(r0, Heap::kempty_stringRootIndex);
|
||||
__ Drop(argc + 1);
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in r2.
|
||||
__ Move(r2, name);
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
|
@ -1087,13 +1087,9 @@ class KeyedArrayCallStub: public HICStub {
|
||||
return GetExtraICState() | ArgcBits::encode(argc_);
|
||||
}
|
||||
|
||||
// We have to start storing extra ic bits at 1, because calls use bit zero
|
||||
// for string stub state.
|
||||
STATIC_ASSERT(CallICBase::StringStubState::kShift == 0);
|
||||
STATIC_ASSERT(CallICBase::StringStubState::kSize == 1);
|
||||
class HoleyBits: public BitField<bool, 1, 1> {};
|
||||
STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2);
|
||||
class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {};
|
||||
class HoleyBits: public BitField<bool, 0, 1> {};
|
||||
STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 1);
|
||||
class ArgcBits: public BitField<int, 1, Code::kArgumentsBits> {};
|
||||
virtual CodeStub::Major MajorKey() { return KeyedArrayCall; }
|
||||
int bit_field_;
|
||||
int argc_;
|
||||
|
@ -1981,140 +1981,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) {
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
const int argc = arguments().immediate();
|
||||
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = ebx;
|
||||
Register index = edi;
|
||||
Register result = eax;
|
||||
__ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
|
||||
if (argc > 0) {
|
||||
__ mov(index, Operand(esp, (argc - 0) * kPointerSize));
|
||||
} else {
|
||||
__ Set(index, Immediate(factory()->undefined_value()));
|
||||
}
|
||||
|
||||
StringCharCodeAtGenerator generator(receiver,
|
||||
index,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ Set(eax, Immediate(factory()->nan_value()));
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in ecx.
|
||||
__ Set(ecx, Immediate(name));
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) {
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
const int argc = arguments().immediate();
|
||||
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = eax;
|
||||
Register index = edi;
|
||||
Register scratch = edx;
|
||||
Register result = eax;
|
||||
__ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
|
||||
if (argc > 0) {
|
||||
__ mov(index, Operand(esp, (argc - 0) * kPointerSize));
|
||||
} else {
|
||||
__ Set(index, Immediate(factory()->undefined_value()));
|
||||
}
|
||||
|
||||
StringCharAtGenerator generator(receiver,
|
||||
index,
|
||||
scratch,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ Set(eax, Immediate(factory()->empty_string()));
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in ecx.
|
||||
__ Set(ecx, Immediate(name));
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
|
49
src/ic.cc
49
src/ic.cc
@ -231,57 +231,8 @@ static void LookupForRead(Handle<Object> object,
|
||||
}
|
||||
|
||||
|
||||
bool CallIC::TryUpdateExtraICState(LookupResult* lookup,
|
||||
Handle<Object> object) {
|
||||
if (!lookup->IsConstantFunction()) return false;
|
||||
JSFunction* function = lookup->GetConstantFunction();
|
||||
if (!function->shared()->HasBuiltinFunctionId()) return false;
|
||||
|
||||
// Fetch the arguments passed to the called function.
|
||||
const int argc = target()->arguments_count();
|
||||
Address entry = isolate()->c_entry_fp(isolate()->thread_local_top());
|
||||
Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset);
|
||||
Arguments args(argc + 1,
|
||||
&Memory::Object_at(fp +
|
||||
StandardFrameConstants::kCallerSPOffset +
|
||||
argc * kPointerSize));
|
||||
switch (function->shared()->builtin_function_id()) {
|
||||
case kStringCharCodeAt:
|
||||
case kStringCharAt:
|
||||
if (object->IsString()) {
|
||||
String* string = String::cast(*object);
|
||||
// Check there's the right string value or wrapper in the receiver slot.
|
||||
ASSERT(string == args[0] || string == JSValue::cast(args[0])->value());
|
||||
// If we're in the default (fastest) state and the index is
|
||||
// out of bounds, update the state to record this fact.
|
||||
if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB &&
|
||||
argc >= 1 && args[1]->IsNumber()) {
|
||||
double index = DoubleToInteger(args.number_at(1));
|
||||
if (index < 0 || index >= string->length()) {
|
||||
set_extra_ic_state(StringStubState::update(extra_ic_state(),
|
||||
STRING_INDEX_OUT_OF_BOUNDS));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool IC::TryRemoveInvalidPrototypeDependentStub(Handle<Object> receiver,
|
||||
Handle<String> name) {
|
||||
if (target()->is_call_stub()) {
|
||||
LookupResult lookup(isolate());
|
||||
LookupForRead(receiver, name, &lookup);
|
||||
if (static_cast<CallIC*>(this)->TryUpdateExtraICState(&lookup, receiver)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (target()->is_keyed_stub()) {
|
||||
// Determine whether the failure is due to a name failure.
|
||||
if (!name->IsName()) return false;
|
||||
|
12
src/ic.h
12
src/ic.h
@ -283,20 +283,8 @@ class IC_Utility {
|
||||
};
|
||||
|
||||
|
||||
enum StringStubFeedback {
|
||||
DEFAULT_STRING_STUB = 0,
|
||||
STRING_INDEX_OUT_OF_BOUNDS = 1
|
||||
};
|
||||
|
||||
|
||||
class CallICBase: public IC {
|
||||
public:
|
||||
// ExtraICState bits
|
||||
class StringStubState: public BitField<StringStubFeedback, 0, 1> {};
|
||||
static ExtraICState ComputeExtraICState(StringStubFeedback feedback) {
|
||||
return StringStubState::encode(feedback);
|
||||
}
|
||||
|
||||
// Returns a JSFunction or a Failure.
|
||||
MUST_USE_RESULT MaybeObject* LoadFunction(Handle<Object> object,
|
||||
Handle<String> name);
|
||||
|
@ -1872,135 +1872,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
||||
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = a0;
|
||||
Register index = t1;
|
||||
Register result = a1;
|
||||
const int argc = arguments().immediate();
|
||||
__ lw(receiver, MemOperand(sp, argc * kPointerSize));
|
||||
if (argc > 0) {
|
||||
__ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
|
||||
} else {
|
||||
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
StringCharCodeAtGenerator generator(receiver,
|
||||
index,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ mov(v0, result);
|
||||
__ DropAndRet(argc + 1);
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(v0, Heap::kNanValueRootIndex);
|
||||
__ DropAndRet(argc + 1);
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in a2.
|
||||
__ li(a2, name);
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
||||
|
||||
const int argc = arguments().immediate();
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = a0;
|
||||
Register index = t1;
|
||||
Register scratch = a3;
|
||||
Register result = a1;
|
||||
if (argc > 0) {
|
||||
__ lw(index, MemOperand(sp, (argc - 1) * kPointerSize));
|
||||
} else {
|
||||
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
StringCharAtGenerator generator(receiver,
|
||||
index,
|
||||
scratch,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ mov(v0, result);
|
||||
__ DropAndRet(argc + 1);
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(v0, Heap::kempty_stringRootIndex);
|
||||
__ DropAndRet(argc + 1);
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in a2.
|
||||
__ li(a2, name);
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
|
@ -11100,11 +11100,6 @@ void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) {
|
||||
PrintF(out, "extra_ic_state = ");
|
||||
const char* name = NULL;
|
||||
switch (kind) {
|
||||
case CALL_IC:
|
||||
if (extra == STRING_INDEX_OUT_OF_BOUNDS) {
|
||||
name = "STRING_INDEX_OUT_OF_BOUNDS";
|
||||
}
|
||||
break;
|
||||
case STORE_IC:
|
||||
case KEYED_STORE_IC:
|
||||
if (extra == kStrictMode) {
|
||||
|
@ -415,10 +415,8 @@ static void FillCache(Isolate* isolate, Handle<Code> code) {
|
||||
|
||||
|
||||
Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) {
|
||||
ExtraICState extra_state =
|
||||
CallICBase::StringStubState::encode(DEFAULT_STRING_STUB);
|
||||
Code::Flags flags =
|
||||
Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc);
|
||||
UnseededNumberDictionary* dictionary =
|
||||
isolate()->heap()->non_monomorphic_cache();
|
||||
int entry = dictionary->FindEntry(isolate(), flags);
|
||||
@ -444,10 +442,8 @@ Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) {
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) {
|
||||
ExtraICState extra_state =
|
||||
CallICBase::ComputeExtraICState(DEFAULT_STRING_STUB);
|
||||
Code::Flags flags =
|
||||
Code::ComputeFlags(kind, UNINITIALIZED, extra_state, Code::NORMAL, argc);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc);
|
||||
Handle<UnseededNumberDictionary> cache =
|
||||
isolate_->factory()->non_monomorphic_cache();
|
||||
int entry = cache->FindEntry(isolate_, flags);
|
||||
|
@ -903,8 +903,6 @@ class KeyedStoreStubCompiler: public StoreStubCompiler {
|
||||
#define CUSTOM_CALL_IC_GENERATORS(V) \
|
||||
V(ArrayPush) \
|
||||
V(ArrayPop) \
|
||||
V(StringCharCodeAt) \
|
||||
V(StringCharAt) \
|
||||
V(StringFromCharCode) \
|
||||
V(MathFloor) \
|
||||
V(MathAbs)
|
||||
|
@ -179,8 +179,6 @@ void TypeFeedbackOracle::CallReceiverTypes(TypeFeedbackId id,
|
||||
Handle<String> name,
|
||||
int arity,
|
||||
SmallMapList* types) {
|
||||
// Note: Currently we do not take string extra ic data into account
|
||||
// here.
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(
|
||||
Code::CALL_IC, kNoExtraICState, OWN_MAP, Code::NORMAL, arity);
|
||||
CollectReceiverTypes(id, name, flags, types);
|
||||
|
@ -1905,135 +1905,6 @@ Handle<Code> CallStubCompiler::CompileArrayPopCall(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharCodeAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
||||
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = rbx;
|
||||
Register index = rdi;
|
||||
Register result = rax;
|
||||
const int argc = arguments().immediate();
|
||||
StackArgumentsAccessor args(rsp, argc);
|
||||
|
||||
__ movq(receiver, args.GetReceiverOperand());
|
||||
if (argc > 0) {
|
||||
__ movq(index, args.GetArgumentOperand(1));
|
||||
} else {
|
||||
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
StringCharCodeAtGenerator generator(receiver,
|
||||
index,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(rax, Heap::kNanValueRootIndex);
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
}
|
||||
|
||||
__ bind(&miss);
|
||||
// Restore function name in rcx.
|
||||
__ Move(rcx, name);
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringCharAtCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
Handle<Cell> cell,
|
||||
Handle<JSFunction> function,
|
||||
Handle<String> name,
|
||||
Code::StubType type) {
|
||||
// If object is not a string, bail out to regular call.
|
||||
if (!object->IsString() || !cell.is_null()) return Handle<Code>::null();
|
||||
|
||||
const int argc = arguments().immediate();
|
||||
StackArgumentsAccessor args(rsp, argc);
|
||||
|
||||
Label miss;
|
||||
Label name_miss;
|
||||
Label index_out_of_range;
|
||||
Label* index_out_of_range_label = &index_out_of_range;
|
||||
if (kind_ == Code::CALL_IC &&
|
||||
(CallICBase::StringStubState::decode(extra_state()) ==
|
||||
DEFAULT_STRING_STUB)) {
|
||||
index_out_of_range_label = &miss;
|
||||
}
|
||||
|
||||
HandlerFrontendHeader(object, holder, name, STRING_CHECK, &name_miss);
|
||||
|
||||
Register receiver = rax;
|
||||
Register index = rdi;
|
||||
Register scratch = rdx;
|
||||
Register result = rax;
|
||||
__ movq(receiver, args.GetReceiverOperand());
|
||||
if (argc > 0) {
|
||||
__ movq(index, args.GetArgumentOperand(1));
|
||||
} else {
|
||||
__ LoadRoot(index, Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
StringCharAtGenerator generator(receiver,
|
||||
index,
|
||||
scratch,
|
||||
result,
|
||||
&miss, // When not a string.
|
||||
&miss, // When not a number.
|
||||
index_out_of_range_label,
|
||||
STRING_INDEX_IS_NUMBER);
|
||||
generator.GenerateFast(masm());
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
|
||||
StubRuntimeCallHelper call_helper;
|
||||
generator.GenerateSlow(masm(), call_helper);
|
||||
|
||||
if (index_out_of_range.is_linked()) {
|
||||
__ bind(&index_out_of_range);
|
||||
__ LoadRoot(rax, Heap::kempty_stringRootIndex);
|
||||
__ ret((argc + 1) * kPointerSize);
|
||||
}
|
||||
__ bind(&miss);
|
||||
// Restore function name in rcx.
|
||||
__ Move(rcx, name);
|
||||
HandlerFrontendFooter(&name_miss);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(type, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> CallStubCompiler::CompileStringFromCharCodeCall(
|
||||
Handle<Object> object,
|
||||
Handle<JSObject> holder,
|
||||
|
Loading…
Reference in New Issue
Block a user