Commit 11a4cb57 authored by vitalyr@chromium.org's avatar vitalyr@chromium.org

Introduce extra IC state to record additional feedback from IC-s.

Extra IC state is only two bits and only supported for call IC-s for
now. To change its extra state an IC stub jumps to a new miss stub
that goes to runtime as usual but then instead of going megamorphic
generates a monomorphic stub with the updated state.

Review URL: http://codereview.chromium.org/6344005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6370 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b4c88d5d
......@@ -542,8 +542,12 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
Label number, non_number, non_string, boolean, probe, miss;
// Probe the stub cache.
Code::Flags flags =
Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
Code::Flags flags = Code::ComputeFlags(kind,
NOT_IN_LOOP,
MONOMORPHIC,
Code::kNoExtraICState,
NORMAL,
argc);
StubCache::GenerateProbe(masm, flags, r1, r2, r3, r4, r5);
// If the stub cache probing failed, the receiver might be a value.
......
......@@ -1332,11 +1332,10 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
MaybeObject* CallStubCompiler::GenerateMissBranch() {
MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
kind_);
Object* obj;
{ MaybeObject* maybe_obj =
StubCache::ComputeCallMiss(arguments().immediate(), kind_);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
return obj;
}
......@@ -1646,8 +1645,15 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
const int argc = arguments().immediate();
Label miss;
Label name_miss;
Label index_out_of_range;
GenerateNameCheck(name, &miss);
Label* index_out_of_range_label = &index_out_of_range;
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
......@@ -1675,7 +1681,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
result,
&miss, // When not a string.
&miss, // When not a number.
&index_out_of_range,
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
char_code_at_generator.GenerateFast(masm());
__ Drop(argc + 1);
......@@ -1684,12 +1690,17 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
StubRuntimeCallHelper call_helper;
char_code_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
__ LoadRoot(r0, Heap::kNanValueRootIndex);
__ Drop(argc + 1);
__ Ret();
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, Handle<String>(name));
__ bind(&name_miss);
Object* obj;
{ MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
......@@ -1720,9 +1731,15 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
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;
GenerateNameCheck(name, &miss);
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
......@@ -1752,7 +1769,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
result,
&miss, // When not a string.
&miss, // When not a number.
&index_out_of_range,
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
char_at_generator.GenerateFast(masm());
__ Drop(argc + 1);
......@@ -1761,12 +1778,17 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
__ LoadRoot(r0, Heap::kEmptyStringRootIndex);
__ Drop(argc + 1);
__ Ret();
if (index_out_of_range.is_linked()) {
__ bind(&index_out_of_range);
__ LoadRoot(r0, Heap::kEmptyStringRootIndex);
__ Drop(argc + 1);
__ Ret();
}
__ bind(&miss);
// Restore function name in r2.
__ Move(r2, Handle<String>(name));
__ bind(&name_miss);
Object* obj;
{ MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
......
......@@ -1231,8 +1231,12 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
Label number, non_number, non_string, boolean, probe, miss;
// Probe the stub cache.
Code::Flags flags =
Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
Code::Flags flags = Code::ComputeFlags(kind,
NOT_IN_LOOP,
MONOMORPHIC,
Code::kNoExtraICState,
NORMAL,
argc);
StubCache::GenerateProbe(masm, flags, edx, ecx, ebx, eax);
// If the stub cache probing failed, the receiver might be a value.
......@@ -1325,7 +1329,9 @@ static void GenerateCallNormal(MacroAssembler* masm, int argc) {
}
static void GenerateCallMiss(MacroAssembler* masm, int argc, IC::UtilityId id) {
static void GenerateCallMiss(MacroAssembler* masm,
int argc,
IC::UtilityId id) {
// ----------- S t a t e -------------
// -- ecx : name
// -- esp[0] : return address
......
......@@ -1362,11 +1362,10 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
MaybeObject* CallStubCompiler::GenerateMissBranch() {
MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
kind_);
Object* obj;
{ MaybeObject* maybe_obj =
StubCache::ComputeCallMiss(arguments().immediate(), kind_);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
__ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
return obj;
}
......@@ -1685,9 +1684,15 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
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;
GenerateNameCheck(name, &miss);
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
......@@ -1715,7 +1720,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
result,
&miss, // When not a string.
&miss, // When not a number.
&index_out_of_range,
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
char_code_at_generator.GenerateFast(masm());
__ ret((argc + 1) * kPointerSize);
......@@ -1723,11 +1728,16 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
StubRuntimeCallHelper call_helper;
char_code_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
__ Set(eax, Immediate(Factory::nan_value()));
__ ret((argc + 1) * kPointerSize);
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(Handle<String>(name)));
__ bind(&name_miss);
Object* obj;
{ MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
......@@ -1758,9 +1768,15 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
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;
GenerateNameCheck(name, &miss);
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
......@@ -1790,7 +1806,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
result,
&miss, // When not a string.
&miss, // When not a number.
&index_out_of_range,
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
char_at_generator.GenerateFast(masm());
__ ret((argc + 1) * kPointerSize);
......@@ -1798,11 +1814,16 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
__ Set(eax, Immediate(Factory::empty_string()));
__ ret((argc + 1) * kPointerSize);
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(Handle<String>(name)));
__ bind(&name_miss);
Object* obj;
{ MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
......
This diff is collapsed.
......@@ -193,16 +193,29 @@ class CallICBase: public IC {
public:
MUST_USE_RESULT MaybeObject* LoadFunction(State state,
Code::ExtraICState extra_ic_state,
Handle<Object> object,
Handle<String> name);
protected:
Code::Kind kind_;
bool TryUpdateExtraICState(LookupResult* lookup,
Handle<Object> object,
Code::ExtraICState* extra_ic_state);
MUST_USE_RESULT MaybeObject* ComputeMonomorphicStub(
LookupResult* lookup,
State state,
Code::ExtraICState extra_ic_state,
Handle<Object> object,
Handle<String> name);
// Update the inline cache and the global stub cache based on the
// lookup result.
void UpdateCaches(LookupResult* lookup,
State state,
Code::ExtraICState extra_ic_state,
Handle<Object> object,
Handle<String> name);
......
......@@ -2416,6 +2416,12 @@ InlineCacheState Code::ic_state() {
}
Code::ExtraICState Code::extra_ic_state() {
ASSERT(is_inline_cache_stub());
return ExtractExtraICStateFromFlags(flags());
}
PropertyType Code::type() {
ASSERT(ic_state() == MONOMORPHIC);
return ExtractTypeFromFlags(flags());
......@@ -2592,14 +2598,20 @@ bool Code::is_inline_cache_stub() {
Code::Flags Code::ComputeFlags(Kind kind,
InLoopFlag in_loop,
InlineCacheState ic_state,
ExtraICState extra_ic_state,
PropertyType type,
int argc,
InlineCacheHolderFlag holder) {
// Extra IC state is only allowed for monomorphic call IC stubs.
ASSERT(extra_ic_state == kNoExtraICState ||
(kind == CALL_IC && (ic_state == MONOMORPHIC ||
ic_state == MONOMORPHIC_PROTOTYPE_FAILURE)));
// Compute the bit mask.
int bits = kind << kFlagsKindShift;
if (in_loop) bits |= kFlagsICInLoopMask;
bits |= ic_state << kFlagsICStateShift;
bits |= type << kFlagsTypeShift;
bits |= extra_ic_state << kFlagsExtraICStateShift;
bits |= argc << kFlagsArgumentsCountShift;
if (holder == PROTOTYPE_MAP) bits |= kFlagsCacheInPrototypeMapMask;
// Cast to flags and validate result before returning it.
......@@ -2608,6 +2620,7 @@ Code::Flags Code::ComputeFlags(Kind kind,
ASSERT(ExtractICStateFromFlags(result) == ic_state);
ASSERT(ExtractICInLoopFromFlags(result) == in_loop);
ASSERT(ExtractTypeFromFlags(result) == type);
ASSERT(ExtractExtraICStateFromFlags(result) == extra_ic_state);
ASSERT(ExtractArgumentsCountFromFlags(result) == argc);
return result;
}
......@@ -2615,10 +2628,12 @@ Code::Flags Code::ComputeFlags(Kind kind,
Code::Flags Code::ComputeMonomorphicFlags(Kind kind,
PropertyType type,
ExtraICState extra_ic_state,
InlineCacheHolderFlag holder,
InLoopFlag in_loop,
int argc) {
return ComputeFlags(kind, in_loop, MONOMORPHIC, type, argc, holder);
return ComputeFlags(
kind, in_loop, MONOMORPHIC, extra_ic_state, type, argc, holder);
}
......@@ -2634,6 +2649,12 @@ InlineCacheState Code::ExtractICStateFromFlags(Flags flags) {
}
Code::ExtraICState Code::ExtractExtraICStateFromFlags(Flags flags) {
int bits = (flags & kFlagsExtraICStateMask) >> kFlagsExtraICStateShift;
return static_cast<ExtraICState>(bits);
}
InLoopFlag Code::ExtractICInLoopFromFlags(Flags flags) {
int bits = (flags & kFlagsICInLoopMask);
return bits != 0 ? IN_LOOP : NOT_IN_LOOP;
......
......@@ -3168,6 +3168,10 @@ class Code: public HeapObject {
NUMBER_OF_KINDS = LAST_IC_KIND + 1
};
typedef int ExtraICState;
static const ExtraICState kNoExtraICState = 0;
#ifdef ENABLE_DISASSEMBLER
// Printing
static const char* Kind2String(Kind kind);
......@@ -3203,6 +3207,7 @@ class Code: public HeapObject {
// [flags]: Access to specific code flags.
inline Kind kind();
inline InlineCacheState ic_state(); // Only valid for IC stubs.
inline ExtraICState extra_ic_state(); // Only valid for IC stubs.
inline InLoopFlag ic_in_loop(); // Only valid for IC stubs.
inline PropertyType type(); // Only valid for monomorphic IC stubs.
inline int arguments_count(); // Only valid for call IC stubs.
......@@ -3287,22 +3292,26 @@ class Code: public HeapObject {
Map* FindFirstMap();
// Flags operations.
static inline Flags ComputeFlags(Kind kind,
InLoopFlag in_loop = NOT_IN_LOOP,
InlineCacheState ic_state = UNINITIALIZED,
PropertyType type = NORMAL,
int argc = -1,
InlineCacheHolderFlag holder = OWN_MAP);
static inline Flags ComputeFlags(
Kind kind,
InLoopFlag in_loop = NOT_IN_LOOP,
InlineCacheState ic_state = UNINITIALIZED,
ExtraICState extra_ic_state = kNoExtraICState,
PropertyType type = NORMAL,
int argc = -1,
InlineCacheHolderFlag holder = OWN_MAP);
static inline Flags ComputeMonomorphicFlags(
Kind kind,
PropertyType type,
ExtraICState extra_ic_state = kNoExtraICState,
InlineCacheHolderFlag holder = OWN_MAP,
InLoopFlag in_loop = NOT_IN_LOOP,
int argc = -1);
static inline Kind ExtractKindFromFlags(Flags flags);
static inline InlineCacheState ExtractICStateFromFlags(Flags flags);
static inline ExtraICState ExtractExtraICStateFromFlags(Flags flags);
static inline InLoopFlag ExtractICInLoopFromFlags(Flags flags);
static inline PropertyType ExtractTypeFromFlags(Flags flags);
static inline int ExtractArgumentsCountFromFlags(Flags flags);
......@@ -3423,14 +3432,16 @@ class Code: public HeapObject {
static const int kFlagsTypeShift = 4;
static const int kFlagsKindShift = 7;
static const int kFlagsICHolderShift = 11;
static const int kFlagsArgumentsCountShift = 12;
static const int kFlagsExtraICStateShift = 12;
static const int kFlagsArgumentsCountShift = 14;
static const int kFlagsICStateMask = 0x00000007; // 00000000111
static const int kFlagsICInLoopMask = 0x00000008; // 00000001000
static const int kFlagsTypeMask = 0x00000070; // 00001110000
static const int kFlagsKindMask = 0x00000780; // 11110000000
static const int kFlagsCacheInPrototypeMapMask = 0x00000800;
static const int kFlagsArgumentsCountMask = 0xFFFFF000;
static const int kFlagsExtraICStateMask = 0x00003000;
static const int kFlagsArgumentsCountMask = 0xFFFFC000;
static const int kFlagsNotUsedInLookup =
(kFlagsICInLoopMask | kFlagsTypeMask | kFlagsCacheInPrototypeMapMask);
......
This diff is collapsed.
......@@ -177,13 +177,15 @@ class StubCache : public AllStatic {
JSObject* holder,
int index);
MUST_USE_RESULT static MaybeObject* ComputeCallConstant(int argc,
InLoopFlag in_loop,
Code::Kind,
String* name,
Object* object,
JSObject* holder,
JSFunction* function);
MUST_USE_RESULT static MaybeObject* ComputeCallConstant(
int argc,
InLoopFlag in_loop,
Code::Kind,
Code::ExtraICState extra_ic_state,
String* name,
Object* object,
JSObject* holder,
JSFunction* function);
MUST_USE_RESULT static MaybeObject* ComputeCallNormal(int argc,
InLoopFlag in_loop,
......@@ -660,6 +662,7 @@ class CallStubCompiler: public StubCompiler {
CallStubCompiler(int argc,
InLoopFlag in_loop,
Code::Kind kind,
Code::ExtraICState extra_ic_state,
InlineCacheHolderFlag cache_holder);
MUST_USE_RESULT MaybeObject* CompileCallField(JSObject* object,
......@@ -705,6 +708,7 @@ class CallStubCompiler: public StubCompiler {
const ParameterCount arguments_;
const InLoopFlag in_loop_;
const Code::Kind kind_;
const Code::ExtraICState extra_ic_state_;
const InlineCacheHolderFlag cache_holder_;
const ParameterCount& arguments() { return arguments_; }
......
......@@ -58,6 +58,9 @@ TypeInfo TypeInfo::TypeFromValue(Handle<Object> value) {
}
STATIC_ASSERT(DEFAULT_STRING_STUB == Code::kNoExtraICState);
TypeFeedbackOracle::TypeFeedbackOracle(Handle<Code> code,
Handle<Context> global_context) {
global_context_ = global_context;
......@@ -117,8 +120,16 @@ ZoneMapList* TypeFeedbackOracle::StoreReceiverTypes(Assignment* expr,
ZoneMapList* TypeFeedbackOracle::CallReceiverTypes(Call* expr,
Handle<String> name) {
int arity = expr->arguments()->length();
Code::Flags flags = Code::ComputeMonomorphicFlags(
Code::CALL_IC, NORMAL, OWN_MAP, NOT_IN_LOOP, arity);
// Note: these flags won't let us get maps from stubs with
// non-default extra ic state in the megamorphic case. In the more
// important monomorphic case the map is obtained directly, so it's
// not a problem until we decide to emit more polymorphic code.
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::CALL_IC,
NORMAL,
Code::kNoExtraICState,
OWN_MAP,
NOT_IN_LOOP,
arity);
return CollectReceiverTypes(expr->position(), name, flags);
}
......
......@@ -219,6 +219,12 @@ class TypeInfo {
};
enum StringStubFeedback {
DEFAULT_STRING_STUB = 0,
STRING_INDEX_OUT_OF_BOUNDS = 1
};
// Forward declarations.
class Assignment;
class BinaryOperation;
......
......@@ -1178,8 +1178,12 @@ static void GenerateMonomorphicCacheProbe(MacroAssembler* masm,
Label number, non_number, non_string, boolean, probe, miss;
// Probe the stub cache.
Code::Flags flags =
Code::ComputeFlags(kind, NOT_IN_LOOP, MONOMORPHIC, NORMAL, argc);
Code::Flags flags = Code::ComputeFlags(kind,
NOT_IN_LOOP,
MONOMORPHIC,
Code::kNoExtraICState,
NORMAL,
argc);
StubCache::GenerateProbe(masm, flags, rdx, rcx, rbx, rax);
// If the stub cache probing failed, the receiver might be a value.
......
......@@ -1327,8 +1327,8 @@ void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
MaybeObject* CallStubCompiler::GenerateMissBranch() {
MaybeObject* maybe_obj =
StubCache::ComputeCallMiss(arguments().immediate(), kind_);
MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
kind_);
Object* obj;
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
__ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
......@@ -1660,9 +1660,15 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
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;
GenerateNameCheck(name, &miss);
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
......@@ -1690,7 +1696,7 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
result,
&miss, // When not a string.
&miss, // When not a number.
&index_out_of_range,
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
char_code_at_generator.GenerateFast(masm());
__ ret((argc + 1) * kPointerSize);
......@@ -1698,11 +1704,16 @@ MaybeObject* CallStubCompiler::CompileStringCharCodeAtCall(
StubRuntimeCallHelper call_helper;
char_code_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
__ LoadRoot(rax, Heap::kNanValueRootIndex);
__ ret((argc + 1) * kPointerSize);
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, Handle<String>(name));
__ bind(&name_miss);
Object* obj;
{ MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
......@@ -1733,9 +1744,15 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
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;
GenerateNameCheck(name, &miss);
if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
index_out_of_range_label = &miss;
}
GenerateNameCheck(name, &name_miss);
// Check that the maps starting from the prototype haven't changed.
GenerateDirectLoadGlobalFunctionPrototype(masm(),
......@@ -1765,7 +1782,7 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
result,
&miss, // When not a string.
&miss, // When not a number.
&index_out_of_range,
index_out_of_range_label,
STRING_INDEX_IS_NUMBER);
char_at_generator.GenerateFast(masm());
__ ret((argc + 1) * kPointerSize);
......@@ -1773,11 +1790,16 @@ MaybeObject* CallStubCompiler::CompileStringCharAtCall(
StubRuntimeCallHelper call_helper;
char_at_generator.GenerateSlow(masm(), call_helper);
__ bind(&index_out_of_range);
__ LoadRoot(rax, Heap::kEmptyStringRootIndex);
__ ret((argc + 1) * kPointerSize);
if (index_out_of_range.is_linked()) {
__ bind(&index_out_of_range);
__ LoadRoot(rax, Heap::kEmptyStringRootIndex);
__ ret((argc + 1) * kPointerSize);
}
__ bind(&miss);
// Restore function name in rcx.
__ Move(rcx, Handle<String>(name));
__ bind(&name_miss);
Object* obj;
{ MaybeObject* maybe_obj = GenerateMissBranch();
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment