Replace special IC builtins and stubs in the map's cache by codestubs.
Review URL: https://chromiumcodereview.appspot.com/11973008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13453 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
b6e2763768
commit
c3d45451f0
@ -32,6 +32,7 @@
|
||||
#include "bootstrapper.h"
|
||||
#include "code-stubs.h"
|
||||
#include "regexp-macro-assembler.h"
|
||||
#include "stub-cache.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -4502,6 +4503,37 @@ void InstanceofStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
__ cmp(r0, Operand(masm->isolate()->factory()->length_symbol()));
|
||||
__ b(ne, &miss);
|
||||
receiver = r1;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
receiver = r0;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, receiver, r3, r4, &miss,
|
||||
support_wrapper_);
|
||||
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
}
|
||||
|
||||
|
||||
Register InstanceofStub::left() { return r0; }
|
||||
|
||||
|
||||
|
@ -228,23 +228,6 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
// -- lr : return address
|
||||
// -- r0 : receiver
|
||||
// -- sp[0] : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss,
|
||||
support_wrappers);
|
||||
// Cache miss: Jump to runtime.
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r2 : name
|
||||
|
@ -3228,32 +3228,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- lr : return address
|
||||
// -- r0 : key
|
||||
// -- r1 : receiver
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = masm()->isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
|
||||
|
||||
// Check the key is the cached one.
|
||||
__ cmp(r0, Operand(name));
|
||||
__ b(ne, &miss);
|
||||
|
||||
GenerateLoadStringLength(masm(), r1, r2, r3, &miss, true);
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_load_string_length(), 1, r2, r3);
|
||||
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <math.h> // For isfinite.
|
||||
#include "builtins.h"
|
||||
#include "code-stubs.h"
|
||||
#include "conversions.h"
|
||||
#include "hashmap.h"
|
||||
#include "parser.h"
|
||||
@ -412,9 +413,10 @@ void Property::RecordTypeFeedback(TypeFeedbackOracle* oracle,
|
||||
is_monomorphic_ = oracle->LoadIsMonomorphicNormal(this);
|
||||
receiver_types_.Clear();
|
||||
if (key()->IsPropertyName()) {
|
||||
StringLengthStub string_stub(Code::LOAD_IC, false);
|
||||
if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_ArrayLength)) {
|
||||
is_array_length_ = true;
|
||||
} else if (oracle->LoadIsBuiltin(this, Builtins::kLoadIC_StringLength)) {
|
||||
} else if (oracle->LoadIsStub(this, &string_stub)) {
|
||||
is_string_length_ = true;
|
||||
} else if (oracle->LoadIsBuiltin(this,
|
||||
Builtins::kLoadIC_FunctionPrototype)) {
|
||||
|
@ -1458,16 +1458,6 @@ static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
|
||||
LoadIC::GenerateStringLength(masm, false);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_StringWrapperLength(MacroAssembler* masm) {
|
||||
LoadIC::GenerateStringLength(masm, true);
|
||||
}
|
||||
|
||||
|
||||
static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
|
||||
LoadIC::GenerateFunctionPrototype(masm);
|
||||
}
|
||||
|
@ -136,10 +136,6 @@ enum BuiltinExtraArguments {
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_ArrayLength, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_StringLength, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_StringWrapperLength, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_FunctionPrototype, LOAD_IC, MONOMORPHIC, \
|
||||
Code::kNoExtraICState) \
|
||||
V(LoadIC_Megamorphic, LOAD_IC, MEGAMORPHIC, \
|
||||
|
@ -47,6 +47,7 @@ namespace internal {
|
||||
V(Compare) \
|
||||
V(CompareIC) \
|
||||
V(MathPow) \
|
||||
V(StringLength) \
|
||||
V(RecordWrite) \
|
||||
V(StoreBufferOverflow) \
|
||||
V(RegExpExec) \
|
||||
@ -539,6 +540,45 @@ class MathPowStub: public PlatformCodeStub {
|
||||
};
|
||||
|
||||
|
||||
class ICStub: public PlatformCodeStub {
|
||||
public:
|
||||
explicit ICStub(Code::Kind kind) : kind_(kind) { }
|
||||
virtual int GetCodeKind() { return kind_; }
|
||||
virtual InlineCacheState GetICState() { return MONOMORPHIC; }
|
||||
|
||||
bool Describes(Code* code) {
|
||||
return GetMajorKey(code) == MajorKey() && code->stub_info() == MinorKey();
|
||||
}
|
||||
|
||||
protected:
|
||||
class KindBits: public BitField<Code::Kind, 0, 4> {};
|
||||
virtual void FinishCode(Handle<Code> code) {
|
||||
code->set_stub_info(MinorKey());
|
||||
}
|
||||
Code::Kind kind() { return kind_; }
|
||||
|
||||
private:
|
||||
Code::Kind kind_;
|
||||
};
|
||||
|
||||
|
||||
class StringLengthStub: public ICStub {
|
||||
public:
|
||||
StringLengthStub(Code::Kind kind, bool support_wrapper)
|
||||
: ICStub(kind), support_wrapper_(support_wrapper) { }
|
||||
virtual void Generate(MacroAssembler* masm);
|
||||
|
||||
private:
|
||||
class WrapperModeBits: public BitField<bool, 4, 1> {};
|
||||
virtual CodeStub::Major MajorKey() { return StringLength; }
|
||||
virtual int MinorKey() {
|
||||
return KindBits::encode(kind()) | WrapperModeBits::encode(support_wrapper_);
|
||||
}
|
||||
|
||||
bool support_wrapper_;
|
||||
};
|
||||
|
||||
|
||||
class BinaryOpStub: public PlatformCodeStub {
|
||||
public:
|
||||
BinaryOpStub(Token::Value op, OverwriteMode mode)
|
||||
|
@ -3259,6 +3259,26 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
__ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
|
||||
__ j(not_equal, &miss);
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
|
||||
support_wrapper_);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
||||
// The key is in edx and the parameter count is in eax.
|
||||
|
||||
|
@ -230,22 +230,6 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateStringLength(MacroAssembler* masm,
|
||||
bool support_wrappers) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, edx, eax, ebx, &miss,
|
||||
support_wrappers);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : name
|
||||
|
@ -3341,32 +3341,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- ecx : key
|
||||
// -- edx : receiver
|
||||
// -- esp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_string_length(), 1);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ cmp(ecx, Immediate(name));
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
GenerateLoadStringLength(masm(), edx, eax, ebx, &miss, true);
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_load_string_length(), 1);
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
|
91
src/ic.cc
91
src/ic.cc
@ -832,6 +832,46 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
|
||||
}
|
||||
|
||||
|
||||
bool IC::HandleLoad(State state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name,
|
||||
MaybeObject** result) {
|
||||
// Use specialized code for getting the length of strings and
|
||||
// string wrapper objects. The length property of string wrapper
|
||||
// objects is read-only and therefore always returns the length of
|
||||
// the underlying string value. See ECMA-262 15.5.5.1.
|
||||
if ((object->IsString() || object->IsStringWrapper()) &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
stub = pre_monomorphic_stub();
|
||||
} else if (state == PREMONOMORPHIC) {
|
||||
StringLengthStub string_length_stub(kind(), !object->IsString());
|
||||
stub = string_length_stub.GetCode();
|
||||
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
||||
StringLengthStub string_length_stub(kind(), true);
|
||||
stub = string_length_stub.GetCode();
|
||||
} else if (state != MEGAMORPHIC) {
|
||||
ASSERT(state != GENERIC);
|
||||
stub = megamorphic_stub();
|
||||
}
|
||||
if (!stub.is_null()) {
|
||||
set_target(*stub);
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
|
||||
#endif
|
||||
}
|
||||
// Get the string if we have a string wrapper object.
|
||||
Handle<Object> string = object->IsJSValue()
|
||||
? Handle<Object>(Handle<JSValue>::cast(object)->value())
|
||||
: object;
|
||||
*result = Smi::FromInt(String::cast(*string)->length());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* LoadIC::Load(State state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name) {
|
||||
@ -842,36 +882,9 @@ MaybeObject* LoadIC::Load(State state,
|
||||
}
|
||||
|
||||
if (FLAG_use_ic) {
|
||||
// Use specialized code for getting the length of strings and
|
||||
// string wrapper objects. The length property of string wrapper
|
||||
// objects is read-only and therefore always returns the length of
|
||||
// the underlying string value. See ECMA-262 15.5.5.1.
|
||||
if ((object->IsString() || object->IsStringWrapper()) &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
Handle<Code> stub;
|
||||
if (state == UNINITIALIZED) {
|
||||
stub = pre_monomorphic_stub();
|
||||
} else if (state == PREMONOMORPHIC) {
|
||||
stub = object->IsString()
|
||||
? isolate()->builtins()->LoadIC_StringLength()
|
||||
: isolate()->builtins()->LoadIC_StringWrapperLength();
|
||||
} else if (state == MONOMORPHIC && object->IsStringWrapper()) {
|
||||
stub = isolate()->builtins()->LoadIC_StringWrapperLength();
|
||||
} else if (state != MEGAMORPHIC) {
|
||||
ASSERT(state != GENERIC);
|
||||
stub = megamorphic_stub();
|
||||
}
|
||||
if (!stub.is_null()) {
|
||||
set_target(*stub);
|
||||
#ifdef DEBUG
|
||||
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
|
||||
#endif
|
||||
}
|
||||
// Get the string if we have a string wrapper object.
|
||||
Handle<Object> string = object->IsJSValue()
|
||||
? Handle<Object>(Handle<JSValue>::cast(object)->value())
|
||||
: object;
|
||||
return Smi::FromInt(String::cast(*string)->length());
|
||||
MaybeObject* result;
|
||||
if (HandleLoad(state, object, name, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Use specialized code for getting the length of arrays.
|
||||
@ -1156,20 +1169,12 @@ MaybeObject* KeyedLoadIC::Load(State state,
|
||||
}
|
||||
|
||||
if (FLAG_use_ic) {
|
||||
// TODO(1073): don't ignore the current stub state.
|
||||
|
||||
// Use specialized code for getting the length of strings.
|
||||
if (object->IsString() &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
Handle<String> string = Handle<String>::cast(object);
|
||||
Handle<Code> code =
|
||||
isolate()->stub_cache()->ComputeKeyedLoadStringLength(name, string);
|
||||
ASSERT(!code.is_null());
|
||||
set_target(*code);
|
||||
TRACE_IC("KeyedLoadIC", name, state, target());
|
||||
return Smi::FromInt(string->length());
|
||||
MaybeObject* result;
|
||||
if (HandleLoad(state, object, name, &result)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO(1073): don't ignore the current stub state.
|
||||
// Use specialized code for getting the length of arrays.
|
||||
if (object->IsJSArray() &&
|
||||
name->Equals(isolate()->heap()->length_symbol())) {
|
||||
@ -1612,7 +1617,7 @@ void StoreIC::UpdateCaches(LookupResult* lookup,
|
||||
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
|
||||
set_target((strict_mode == kStrictMode)
|
||||
? megamorphic_stub_strict()
|
||||
: megamorphic_stub());
|
||||
: *megamorphic_stub());
|
||||
}
|
||||
break;
|
||||
case MEGAMORPHIC:
|
||||
|
52
src/ic.h
52
src/ic.h
@ -133,6 +133,18 @@ class IC {
|
||||
InlineCacheHolderFlag holder);
|
||||
|
||||
protected:
|
||||
virtual Handle<Code> pre_monomorphic_stub() {
|
||||
UNREACHABLE();
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
virtual Handle<Code> megamorphic_stub() {
|
||||
UNREACHABLE();
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
virtual Code::Kind kind() const {
|
||||
UNREACHABLE();
|
||||
return Code::STUB;
|
||||
}
|
||||
Address fp() const { return fp_; }
|
||||
Address pc() const { return *pc_address_; }
|
||||
Isolate* isolate() const { return isolate_; }
|
||||
@ -165,6 +177,11 @@ class IC {
|
||||
static inline void SetTargetAtAddress(Address address, Code* target);
|
||||
static void PostPatching(Address address, Code* target, Code* old_target);
|
||||
|
||||
bool HandleLoad(State state,
|
||||
Handle<Object> object,
|
||||
Handle<String> name,
|
||||
MaybeObject** result);
|
||||
|
||||
private:
|
||||
// Frame pointer for the frame that uses (calls) the IC.
|
||||
Address fp_;
|
||||
@ -338,10 +355,15 @@ class LoadIC: public IC {
|
||||
|
||||
// Specialized code generator routines.
|
||||
static void GenerateArrayLength(MacroAssembler* masm);
|
||||
static void GenerateStringLength(MacroAssembler* masm,
|
||||
bool support_wrappers);
|
||||
static void GenerateFunctionPrototype(MacroAssembler* masm);
|
||||
|
||||
protected:
|
||||
virtual Code::Kind kind() const { return Code::LOAD_IC; }
|
||||
|
||||
virtual Handle<Code> megamorphic_stub() {
|
||||
return isolate()->builtins()->LoadIC_Megamorphic();
|
||||
}
|
||||
|
||||
private:
|
||||
// Update the inline cache and the global stub cache based on the
|
||||
// lookup result.
|
||||
@ -351,14 +373,11 @@ class LoadIC: public IC {
|
||||
Handle<String> name);
|
||||
|
||||
// Stub accessors.
|
||||
Handle<Code> megamorphic_stub() {
|
||||
return isolate()->builtins()->LoadIC_Megamorphic();
|
||||
}
|
||||
static Code* initialize_stub() {
|
||||
return Isolate::Current()->builtins()->builtin(
|
||||
Builtins::kLoadIC_Initialize);
|
||||
}
|
||||
Handle<Code> pre_monomorphic_stub() {
|
||||
virtual Handle<Code> pre_monomorphic_stub() {
|
||||
return isolate()->builtins()->LoadIC_PreMonomorphic();
|
||||
}
|
||||
|
||||
@ -429,8 +448,6 @@ class KeyedIC: public IC {
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
virtual Code::Kind kind() const = 0;
|
||||
|
||||
Handle<Code> ComputeStub(Handle<JSObject> receiver,
|
||||
StubKind stub_kind,
|
||||
StrictModeFlag strict_mode,
|
||||
@ -520,6 +537,10 @@ class KeyedLoadIC: public KeyedIC {
|
||||
protected:
|
||||
virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
|
||||
|
||||
virtual Handle<Code> megamorphic_stub() {
|
||||
return isolate()->builtins()->KeyedLoadIC_Generic();
|
||||
}
|
||||
|
||||
virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
|
||||
StrictModeFlag strict_mode,
|
||||
KeyedAccessGrowMode grow_mode);
|
||||
@ -540,13 +561,10 @@ class KeyedLoadIC: public KeyedIC {
|
||||
return Isolate::Current()->builtins()->builtin(
|
||||
Builtins::kKeyedLoadIC_Initialize);
|
||||
}
|
||||
Handle<Code> megamorphic_stub() {
|
||||
return isolate()->builtins()->KeyedLoadIC_Generic();
|
||||
}
|
||||
Handle<Code> generic_stub() const {
|
||||
return isolate()->builtins()->KeyedLoadIC_Generic();
|
||||
}
|
||||
Handle<Code> pre_monomorphic_stub() {
|
||||
virtual Handle<Code> pre_monomorphic_stub() {
|
||||
return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
|
||||
}
|
||||
Handle<Code> indexed_interceptor_stub() {
|
||||
@ -584,6 +602,12 @@ class StoreIC: public IC {
|
||||
static void GenerateGlobalProxy(MacroAssembler* masm,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
protected:
|
||||
virtual Code::Kind kind() const { return Code::STORE_IC; }
|
||||
virtual Handle<Code> megamorphic_stub() {
|
||||
return isolate()->builtins()->StoreIC_Megamorphic();
|
||||
}
|
||||
|
||||
private:
|
||||
// Update the inline cache and the global stub cache based on the
|
||||
// lookup result.
|
||||
@ -602,10 +626,6 @@ class StoreIC: public IC {
|
||||
}
|
||||
|
||||
// Stub accessors.
|
||||
Code* megamorphic_stub() {
|
||||
return isolate()->builtins()->builtin(
|
||||
Builtins::kStoreIC_Megamorphic);
|
||||
}
|
||||
Code* megamorphic_stub_strict() {
|
||||
return isolate()->builtins()->builtin(
|
||||
Builtins::kStoreIC_Megamorphic_Strict);
|
||||
|
@ -3456,6 +3456,8 @@ int Code::major_key() {
|
||||
kind() == UNARY_OP_IC ||
|
||||
kind() == BINARY_OP_IC ||
|
||||
kind() == COMPARE_IC ||
|
||||
kind() == LOAD_IC ||
|
||||
kind() == KEYED_LOAD_IC ||
|
||||
kind() == TO_BOOLEAN_IC);
|
||||
return StubMajorKeyField::decode(
|
||||
READ_UINT32_FIELD(this, kKindSpecificFlags2Offset));
|
||||
@ -3468,6 +3470,8 @@ void Code::set_major_key(int major) {
|
||||
kind() == UNARY_OP_IC ||
|
||||
kind() == BINARY_OP_IC ||
|
||||
kind() == COMPARE_IC ||
|
||||
kind() == LOAD_IC ||
|
||||
kind() == KEYED_LOAD_IC ||
|
||||
kind() == TO_BOOLEAN_IC);
|
||||
ASSERT(0 <= major && major < 256);
|
||||
int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
|
||||
@ -4847,14 +4851,17 @@ void Code::set_type_feedback_info(Object* value, WriteBarrierMode mode) {
|
||||
|
||||
|
||||
int Code::stub_info() {
|
||||
ASSERT(kind() == COMPARE_IC || kind() == BINARY_OP_IC);
|
||||
ASSERT(kind() == COMPARE_IC || kind() == BINARY_OP_IC || kind() == LOAD_IC);
|
||||
Object* value = READ_FIELD(this, kTypeFeedbackInfoOffset);
|
||||
return Smi::cast(value)->value();
|
||||
}
|
||||
|
||||
|
||||
void Code::set_stub_info(int value) {
|
||||
ASSERT(kind() == COMPARE_IC || kind() == BINARY_OP_IC);
|
||||
ASSERT(kind() == COMPARE_IC ||
|
||||
kind() == BINARY_OP_IC ||
|
||||
kind() == LOAD_IC ||
|
||||
kind() == KEYED_LOAD_IC);
|
||||
WRITE_FIELD(this, kTypeFeedbackInfoOffset, Smi::FromInt(value));
|
||||
}
|
||||
|
||||
|
@ -365,23 +365,6 @@ Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
|
||||
Handle<String> receiver) {
|
||||
Code::Flags flags =
|
||||
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, Code::CALLBACKS);
|
||||
Handle<Map> map(receiver->map());
|
||||
Handle<Object> probe(map->FindInCodeCache(*name, flags), isolate_);
|
||||
if (probe->IsCode()) return Handle<Code>::cast(probe);
|
||||
|
||||
KeyedLoadStubCompiler compiler(isolate_);
|
||||
Handle<Code> code = compiler.CompileLoadStringLength(name);
|
||||
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
|
||||
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
|
||||
Map::UpdateCodeCache(map, name, code);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
|
||||
Handle<String> name,
|
||||
Handle<JSFunction> receiver) {
|
||||
|
@ -136,9 +136,6 @@ class StubCache {
|
||||
Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
|
||||
Handle<JSArray> receiver);
|
||||
|
||||
Handle<Code> ComputeKeyedLoadStringLength(Handle<String> name,
|
||||
Handle<String> receiver);
|
||||
|
||||
Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
|
||||
Handle<JSFunction> receiver);
|
||||
|
||||
@ -672,8 +669,6 @@ class KeyedLoadStubCompiler: public StubCompiler {
|
||||
|
||||
Handle<Code> CompileLoadArrayLength(Handle<String> name);
|
||||
|
||||
Handle<Code> CompileLoadStringLength(Handle<String> name);
|
||||
|
||||
Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
|
||||
|
||||
Handle<Code> CompileLoadElement(Handle<Map> receiver_map);
|
||||
|
@ -305,6 +305,15 @@ bool TypeFeedbackOracle::LoadIsBuiltin(Property* expr, Builtins::Name id) {
|
||||
}
|
||||
|
||||
|
||||
bool TypeFeedbackOracle::LoadIsStub(Property* expr, ICStub* stub) {
|
||||
Handle<Object> object = GetInfo(expr->PropertyFeedbackId());
|
||||
if (!object->IsCode()) return false;
|
||||
Handle<Code> code = Handle<Code>::cast(object);
|
||||
if (!code->is_load_stub()) return false;
|
||||
return stub->Describes(*code);
|
||||
}
|
||||
|
||||
|
||||
static TypeInfo TypeFromCompareType(CompareIC::State state) {
|
||||
switch (state) {
|
||||
case CompareIC::UNINITIALIZED:
|
||||
|
@ -227,10 +227,11 @@ class CompareOperation;
|
||||
class CompilationInfo;
|
||||
class CountOperation;
|
||||
class Expression;
|
||||
class ForInStatement;
|
||||
class ICStub;
|
||||
class Property;
|
||||
class SmallMapList;
|
||||
class UnaryOperation;
|
||||
class ForInStatement;
|
||||
|
||||
|
||||
class TypeFeedbackOracle: public ZoneObject {
|
||||
@ -280,6 +281,7 @@ class TypeFeedbackOracle: public ZoneObject {
|
||||
Handle<Map> GetObjectLiteralStoreMap(ObjectLiteral::Property* prop);
|
||||
|
||||
bool LoadIsBuiltin(Property* expr, Builtins::Name id);
|
||||
bool LoadIsStub(Property* expr, ICStub* stub);
|
||||
|
||||
// TODO(1571) We can't use ToBooleanStub::Types as the return value because
|
||||
// of various cylces in our headers. Death to tons of implementations in
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "bootstrapper.h"
|
||||
#include "code-stubs.h"
|
||||
#include "regexp-macro-assembler.h"
|
||||
#include "stub-cache.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -2359,6 +2360,34 @@ void MathPowStub::Generate(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void StringLengthStub::Generate(MacroAssembler* masm) {
|
||||
Label miss;
|
||||
Register receiver;
|
||||
if (kind() == Code::KEYED_LOAD_IC) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
__ Cmp(rax, masm->isolate()->factory()->length_symbol());
|
||||
receiver = rdx;
|
||||
} else {
|
||||
ASSERT(kind() == Code::LOAD_IC);
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
receiver = rax;
|
||||
}
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, receiver, r8, r9, &miss,
|
||||
support_wrapper_);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, kind());
|
||||
}
|
||||
|
||||
|
||||
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
|
||||
// The key is in rdx and the parameter count is in rax.
|
||||
|
||||
|
@ -238,21 +238,6 @@ void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateStringLength(MacroAssembler* masm, bool support_wrappers) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
// -- rcx : name
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss,
|
||||
support_wrappers);
|
||||
__ bind(&miss);
|
||||
StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
||||
}
|
||||
|
||||
|
||||
void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : receiver
|
||||
|
@ -3154,32 +3154,6 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- rax : key
|
||||
// -- rdx : receiver
|
||||
// -- rsp[0] : return address
|
||||
// -----------------------------------
|
||||
Label miss;
|
||||
|
||||
Counters* counters = isolate()->counters();
|
||||
__ IncrementCounter(counters->keyed_load_string_length(), 1);
|
||||
|
||||
// Check that the name has not changed.
|
||||
__ Cmp(rax, name);
|
||||
__ j(not_equal, &miss);
|
||||
|
||||
GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
|
||||
__ bind(&miss);
|
||||
__ DecrementCounter(counters->keyed_load_string_length(), 1);
|
||||
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
||||
|
||||
// Return the generated code.
|
||||
return GetCode(Code::CALLBACKS, name);
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
|
||||
Handle<String> name) {
|
||||
// ----------- S t a t e -------------
|
||||
|
Loading…
Reference in New Issue
Block a user