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:
verwaest@chromium.org 2014-01-17 11:28:22 +00:00
parent ef52aeb701
commit e9f957ce2c
11 changed files with 7 additions and 609 deletions

View File

@ -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,

View File

@ -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_;

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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) {

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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,