Add infrastructure to automatucally generate IC miss stubs
Review URL: https://codereview.chromium.org/13886013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14342 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
bfb3e6ce9c
commit
80adb58933
@ -161,6 +161,30 @@ static void EmitCheckForHeapNumber(MacroAssembler* masm, Register operand,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
|
||||||
|
// Update the static counter each time a new code stub is generated.
|
||||||
|
Isolate* isolate = masm->isolate();
|
||||||
|
isolate->counters()->code_stubs()->Increment();
|
||||||
|
|
||||||
|
CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
|
||||||
|
int param_count = descriptor->register_param_count_;
|
||||||
|
{
|
||||||
|
// Call the runtime system in a fresh internal frame.
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
ASSERT(descriptor->register_param_count_ == 0 ||
|
||||||
|
r0.is(descriptor->register_params_[param_count - 1]));
|
||||||
|
// Push arguments
|
||||||
|
for (int i = 0; i < param_count; ++i) {
|
||||||
|
__ push(descriptor->register_params_[i]);
|
||||||
|
}
|
||||||
|
ExternalReference miss = descriptor->miss_handler_;
|
||||||
|
__ CallExternalReference(miss, descriptor->register_param_count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ Ret();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ToNumberStub::Generate(MacroAssembler* masm) {
|
void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||||
// The ToNumber stub takes one argument in eax.
|
// The ToNumber stub takes one argument in eax.
|
||||||
Label check_heap_number, call_builtin;
|
Label check_heap_number, call_builtin;
|
||||||
|
@ -61,11 +61,7 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
|
|||||||
arguments_length_(NULL),
|
arguments_length_(NULL),
|
||||||
info_(stub, isolate),
|
info_(stub, isolate),
|
||||||
context_(NULL) {
|
context_(NULL) {
|
||||||
int major_key = stub->MajorKey();
|
descriptor_ = stub->GetInterfaceDescriptor(isolate);
|
||||||
descriptor_ = isolate->code_stub_interface_descriptor(major_key);
|
|
||||||
if (descriptor_->register_param_count_ < 0) {
|
|
||||||
stub->InitializeInterfaceDescriptor(isolate, descriptor_);
|
|
||||||
}
|
|
||||||
parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
|
parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
|
||||||
}
|
}
|
||||||
virtual bool BuildGraph();
|
virtual bool BuildGraph();
|
||||||
@ -96,6 +92,9 @@ class CodeStubGraphBuilderBase : public HGraphBuilder {
|
|||||||
|
|
||||||
|
|
||||||
bool CodeStubGraphBuilderBase::BuildGraph() {
|
bool CodeStubGraphBuilderBase::BuildGraph() {
|
||||||
|
// Update the static counter each time a new code stub is generated.
|
||||||
|
isolate()->counters()->code_stubs()->Increment();
|
||||||
|
|
||||||
if (FLAG_trace_hydrogen) {
|
if (FLAG_trace_hydrogen) {
|
||||||
const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
|
const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
|
||||||
PrintF("-----------------------------------------------------------\n");
|
PrintF("-----------------------------------------------------------\n");
|
||||||
@ -176,16 +175,87 @@ class CodeStubGraphBuilder: public CodeStubGraphBuilderBase {
|
|||||||
: CodeStubGraphBuilderBase(Isolate::Current(), stub) {}
|
: CodeStubGraphBuilderBase(Isolate::Current(), stub) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual HValue* BuildCodeStub();
|
virtual HValue* BuildCodeStub() {
|
||||||
|
if (casted_stub()->IsMiss()) {
|
||||||
|
return BuildCodeInitializedStub();
|
||||||
|
} else {
|
||||||
|
return BuildCodeUninitializedStub();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HValue* BuildCodeInitializedStub() {
|
||||||
|
UNIMPLEMENTED();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual HValue* BuildCodeUninitializedStub() {
|
||||||
|
// Force a deopt that falls back to the runtime.
|
||||||
|
HValue* undefined = graph()->GetConstantUndefined();
|
||||||
|
CheckBuilder builder(this);
|
||||||
|
builder.CheckNotUndefined(undefined);
|
||||||
|
builder.End();
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
Stub* casted_stub() { return static_cast<Stub*>(stub()); }
|
Stub* casted_stub() { return static_cast<Stub*>(stub()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Handle<Code> HydrogenCodeStub::GenerateLightweightMissCode(Isolate* isolate) {
|
||||||
|
Factory* factory = isolate->factory();
|
||||||
|
|
||||||
|
// Generate the new code.
|
||||||
|
MacroAssembler masm(isolate, NULL, 256);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Update the static counter each time a new code stub is generated.
|
||||||
|
isolate->counters()->code_stubs()->Increment();
|
||||||
|
|
||||||
|
// Nested stubs are not allowed for leaves.
|
||||||
|
AllowStubCallsScope allow_scope(&masm, false);
|
||||||
|
|
||||||
|
// Generate the code for the stub.
|
||||||
|
masm.set_generating_stub(true);
|
||||||
|
NoCurrentFrameScope scope(&masm);
|
||||||
|
GenerateLightweightMiss(&masm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the code object.
|
||||||
|
CodeDesc desc;
|
||||||
|
masm.GetCode(&desc);
|
||||||
|
|
||||||
|
// Copy the generated code into a heap object.
|
||||||
|
Code::Flags flags = Code::ComputeFlags(
|
||||||
|
GetCodeKind(),
|
||||||
|
GetICState(),
|
||||||
|
GetExtraICState(),
|
||||||
|
GetStubType(), -1);
|
||||||
|
Handle<Code> new_object = factory->NewCode(
|
||||||
|
desc, flags, masm.CodeObject(), NeedsImmovableCode());
|
||||||
|
return new_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <class Stub>
|
template <class Stub>
|
||||||
static Handle<Code> DoGenerateCode(Stub* stub) {
|
static Handle<Code> DoGenerateCode(Stub* stub) {
|
||||||
CodeStubGraphBuilder<Stub> builder(stub);
|
Isolate* isolate = Isolate::Current();
|
||||||
LChunk* chunk = OptimizeGraph(builder.CreateGraph());
|
CodeStub::Major major_key =
|
||||||
return chunk->Codegen();
|
static_cast<HydrogenCodeStub*>(stub)->MajorKey();
|
||||||
|
CodeStubInterfaceDescriptor* descriptor =
|
||||||
|
isolate->code_stub_interface_descriptor(major_key);
|
||||||
|
if (descriptor->register_param_count_ < 0) {
|
||||||
|
stub->InitializeInterfaceDescriptor(isolate, descriptor);
|
||||||
|
}
|
||||||
|
// The miss case without stack parameters can use a light-weight stub to enter
|
||||||
|
// the runtime that is significantly faster than using the standard
|
||||||
|
// stub-failure deopt mechanism.
|
||||||
|
if (stub->IsMiss() && descriptor->stack_parameter_count_ == NULL) {
|
||||||
|
return stub->GenerateLightweightMissCode(isolate);
|
||||||
|
} else {
|
||||||
|
CodeStubGraphBuilder<Stub> builder(stub);
|
||||||
|
LChunk* chunk = OptimizeGraph(builder.CreateGraph());
|
||||||
|
return chunk->Codegen();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -248,9 +318,7 @@ HValue* CodeStubGraphBuilder<FastCloneShallowArrayStub>::BuildCodeStub() {
|
|||||||
|
|
||||||
|
|
||||||
Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
|
Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
|
||||||
CodeStubGraphBuilder<FastCloneShallowArrayStub> builder(this);
|
return DoGenerateCode(this);
|
||||||
LChunk* chunk = OptimizeGraph(builder.CreateGraph());
|
|
||||||
return chunk->Codegen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,6 +37,16 @@
|
|||||||
namespace v8 {
|
namespace v8 {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
|
||||||
|
CodeStubInterfaceDescriptor::CodeStubInterfaceDescriptor()
|
||||||
|
: register_param_count_(-1),
|
||||||
|
stack_parameter_count_(NULL),
|
||||||
|
function_mode_(NOT_JS_FUNCTION_STUB_MODE),
|
||||||
|
register_params_(NULL),
|
||||||
|
deoptimization_handler_(NULL),
|
||||||
|
miss_handler_(IC_Utility(IC::kUnreachable), Isolate::Current()) { }
|
||||||
|
|
||||||
|
|
||||||
bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
|
bool CodeStub::FindCodeInCache(Code** code_out, Isolate* isolate) {
|
||||||
UnseededNumberDictionary* stubs = isolate->heap()->code_stubs();
|
UnseededNumberDictionary* stubs = isolate->heap()->code_stubs();
|
||||||
int index = stubs->FindEntry(GetKey());
|
int index = stubs->FindEntry(GetKey());
|
||||||
|
113
src/code-stubs.h
113
src/code-stubs.h
@ -29,6 +29,7 @@
|
|||||||
#define V8_CODE_STUBS_H_
|
#define V8_CODE_STUBS_H_
|
||||||
|
|
||||||
#include "allocation.h"
|
#include "allocation.h"
|
||||||
|
#include "assembler.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
|
||||||
@ -260,17 +261,15 @@ class PlatformCodeStub : public CodeStub {
|
|||||||
|
|
||||||
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
|
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
|
||||||
|
|
||||||
|
|
||||||
struct CodeStubInterfaceDescriptor {
|
struct CodeStubInterfaceDescriptor {
|
||||||
CodeStubInterfaceDescriptor()
|
CodeStubInterfaceDescriptor();
|
||||||
: register_param_count_(-1),
|
|
||||||
stack_parameter_count_(NULL),
|
|
||||||
function_mode_(NOT_JS_FUNCTION_STUB_MODE),
|
|
||||||
register_params_(NULL) { }
|
|
||||||
int register_param_count_;
|
int register_param_count_;
|
||||||
const Register* stack_parameter_count_;
|
const Register* stack_parameter_count_;
|
||||||
StubFunctionMode function_mode_;
|
StubFunctionMode function_mode_;
|
||||||
Register* register_params_;
|
Register* register_params_;
|
||||||
Address deoptimization_handler_;
|
Address deoptimization_handler_;
|
||||||
|
ExternalReference miss_handler_;
|
||||||
|
|
||||||
int environment_length() const {
|
int environment_length() const {
|
||||||
if (stack_parameter_count_ != NULL) {
|
if (stack_parameter_count_ != NULL) {
|
||||||
@ -283,8 +282,14 @@ struct CodeStubInterfaceDescriptor {
|
|||||||
|
|
||||||
class HydrogenCodeStub : public CodeStub {
|
class HydrogenCodeStub : public CodeStub {
|
||||||
public:
|
public:
|
||||||
// Retrieve the code for the stub. Generate the code if needed.
|
enum InitializationState {
|
||||||
virtual Handle<Code> GenerateCode() = 0;
|
CODE_STUB_IS_NOT_MISS,
|
||||||
|
CODE_STUB_IS_MISS
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit HydrogenCodeStub(InitializationState state) {
|
||||||
|
is_miss_ = (state == CODE_STUB_IS_MISS);
|
||||||
|
}
|
||||||
|
|
||||||
virtual Code::Kind GetCodeKind() const { return Code::STUB; }
|
virtual Code::Kind GetCodeKind() const { return Code::STUB; }
|
||||||
|
|
||||||
@ -292,9 +297,36 @@ class HydrogenCodeStub : public CodeStub {
|
|||||||
return isolate->code_stub_interface_descriptor(MajorKey());
|
return isolate->code_stub_interface_descriptor(MajorKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsMiss() { return is_miss_; }
|
||||||
|
|
||||||
|
template<class SubClass>
|
||||||
|
static Handle<Code> GetUninitialized(Isolate* isolate) {
|
||||||
|
SubClass::GenerateAheadOfTime(isolate);
|
||||||
|
return SubClass().GetCode(isolate);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void InitializeInterfaceDescriptor(
|
virtual void InitializeInterfaceDescriptor(
|
||||||
Isolate* isolate,
|
Isolate* isolate,
|
||||||
CodeStubInterfaceDescriptor* descriptor) = 0;
|
CodeStubInterfaceDescriptor* descriptor) = 0;
|
||||||
|
|
||||||
|
// Retrieve the code for the stub. Generate the code if needed.
|
||||||
|
virtual Handle<Code> GenerateCode() = 0;
|
||||||
|
|
||||||
|
virtual int NotMissMinorKey() = 0;
|
||||||
|
|
||||||
|
Handle<Code> GenerateLightweightMissCode(Isolate* isolate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
class MinorKeyBits: public BitField<int, 0, kStubMinorKeyBits - 1> {};
|
||||||
|
class IsMissBits: public BitField<bool, kStubMinorKeyBits - 1, 1> {};
|
||||||
|
|
||||||
|
void GenerateLightweightMiss(MacroAssembler* masm);
|
||||||
|
virtual int MinorKey() {
|
||||||
|
return IsMissBits::encode(is_miss_) |
|
||||||
|
MinorKeyBits::encode(NotMissMinorKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_miss_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -467,7 +499,8 @@ class FastCloneShallowArrayStub : public HydrogenCodeStub {
|
|||||||
FastCloneShallowArrayStub(Mode mode,
|
FastCloneShallowArrayStub(Mode mode,
|
||||||
AllocationSiteMode allocation_site_mode,
|
AllocationSiteMode allocation_site_mode,
|
||||||
int length)
|
int length)
|
||||||
: mode_(mode),
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
|
||||||
|
mode_(mode),
|
||||||
allocation_site_mode_(allocation_site_mode),
|
allocation_site_mode_(allocation_site_mode),
|
||||||
length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
|
length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
|
||||||
ASSERT_GE(length_, 0);
|
ASSERT_GE(length_, 0);
|
||||||
@ -513,7 +546,7 @@ class FastCloneShallowArrayStub : public HydrogenCodeStub {
|
|||||||
STATIC_ASSERT(kFastCloneModeCount < 16);
|
STATIC_ASSERT(kFastCloneModeCount < 16);
|
||||||
STATIC_ASSERT(kMaximumClonedLength < 16);
|
STATIC_ASSERT(kMaximumClonedLength < 16);
|
||||||
Major MajorKey() { return FastCloneShallowArray; }
|
Major MajorKey() { return FastCloneShallowArray; }
|
||||||
int MinorKey() {
|
int NotMissMinorKey() {
|
||||||
return AllocationSiteModeBits::encode(allocation_site_mode_)
|
return AllocationSiteModeBits::encode(allocation_site_mode_)
|
||||||
| ModeBits::encode(mode_)
|
| ModeBits::encode(mode_)
|
||||||
| LengthBits::encode(length_);
|
| LengthBits::encode(length_);
|
||||||
@ -526,7 +559,9 @@ class FastCloneShallowObjectStub : public HydrogenCodeStub {
|
|||||||
// Maximum number of properties in copied object.
|
// Maximum number of properties in copied object.
|
||||||
static const int kMaximumClonedProperties = 6;
|
static const int kMaximumClonedProperties = 6;
|
||||||
|
|
||||||
explicit FastCloneShallowObjectStub(int length) : length_(length) {
|
explicit FastCloneShallowObjectStub(int length)
|
||||||
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
|
||||||
|
length_(length) {
|
||||||
ASSERT_GE(length_, 0);
|
ASSERT_GE(length_, 0);
|
||||||
ASSERT_LE(length_, kMaximumClonedProperties);
|
ASSERT_LE(length_, kMaximumClonedProperties);
|
||||||
}
|
}
|
||||||
@ -543,7 +578,7 @@ class FastCloneShallowObjectStub : public HydrogenCodeStub {
|
|||||||
int length_;
|
int length_;
|
||||||
|
|
||||||
Major MajorKey() { return FastCloneShallowObject; }
|
Major MajorKey() { return FastCloneShallowObject; }
|
||||||
int MinorKey() { return length_; }
|
int NotMissMinorKey() { return length_; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
|
DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
|
||||||
};
|
};
|
||||||
@ -1291,19 +1326,20 @@ class KeyedLoadDictionaryElementStub : public PlatformCodeStub {
|
|||||||
public:
|
public:
|
||||||
KeyedLoadDictionaryElementStub() {}
|
KeyedLoadDictionaryElementStub() {}
|
||||||
|
|
||||||
Major MajorKey() { return KeyedLoadElement; }
|
|
||||||
int MinorKey() { return DICTIONARY_ELEMENTS; }
|
|
||||||
|
|
||||||
void Generate(MacroAssembler* masm);
|
void Generate(MacroAssembler* masm);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Major MajorKey() { return KeyedLoadElement; }
|
||||||
|
int MinorKey() { return DICTIONARY_ELEMENTS; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
|
DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class KeyedLoadFastElementStub : public HydrogenCodeStub {
|
class KeyedLoadFastElementStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind) {
|
KeyedLoadFastElementStub(bool is_js_array, ElementsKind elements_kind)
|
||||||
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
|
||||||
bit_field_ = ElementsKindBits::encode(elements_kind) |
|
bit_field_ = ElementsKindBits::encode(elements_kind) |
|
||||||
IsJSArrayBits::encode(is_js_array);
|
IsJSArrayBits::encode(is_js_array);
|
||||||
}
|
}
|
||||||
@ -1323,12 +1359,12 @@ class KeyedLoadFastElementStub : public HydrogenCodeStub {
|
|||||||
CodeStubInterfaceDescriptor* descriptor);
|
CodeStubInterfaceDescriptor* descriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class IsJSArrayBits: public BitField<bool, 8, 1> {};
|
|
||||||
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
|
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
|
||||||
|
class IsJSArrayBits: public BitField<bool, 8, 1> {};
|
||||||
uint32_t bit_field_;
|
uint32_t bit_field_;
|
||||||
|
|
||||||
Major MajorKey() { return KeyedLoadElement; }
|
Major MajorKey() { return KeyedLoadElement; }
|
||||||
int MinorKey() { return bit_field_; }
|
int NotMissMinorKey() { return bit_field_; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
|
DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
|
||||||
};
|
};
|
||||||
@ -1338,15 +1374,13 @@ class KeyedStoreFastElementStub : public HydrogenCodeStub {
|
|||||||
public:
|
public:
|
||||||
KeyedStoreFastElementStub(bool is_js_array,
|
KeyedStoreFastElementStub(bool is_js_array,
|
||||||
ElementsKind elements_kind,
|
ElementsKind elements_kind,
|
||||||
KeyedAccessStoreMode mode) {
|
KeyedAccessStoreMode mode)
|
||||||
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
|
||||||
bit_field_ = ElementsKindBits::encode(elements_kind) |
|
bit_field_ = ElementsKindBits::encode(elements_kind) |
|
||||||
IsJSArrayBits::encode(is_js_array) |
|
IsJSArrayBits::encode(is_js_array) |
|
||||||
StoreModeBits::encode(mode);
|
StoreModeBits::encode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
Major MajorKey() { return KeyedStoreElement; }
|
|
||||||
int MinorKey() { return bit_field_; }
|
|
||||||
|
|
||||||
bool is_js_array() const {
|
bool is_js_array() const {
|
||||||
return IsJSArrayBits::decode(bit_field_);
|
return IsJSArrayBits::decode(bit_field_);
|
||||||
}
|
}
|
||||||
@ -1371,6 +1405,9 @@ class KeyedStoreFastElementStub : public HydrogenCodeStub {
|
|||||||
class IsJSArrayBits: public BitField<bool, 12, 1> {};
|
class IsJSArrayBits: public BitField<bool, 12, 1> {};
|
||||||
uint32_t bit_field_;
|
uint32_t bit_field_;
|
||||||
|
|
||||||
|
Major MajorKey() { return KeyedStoreElement; }
|
||||||
|
int NotMissMinorKey() { return bit_field_; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
|
DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1378,7 +1415,8 @@ class KeyedStoreFastElementStub : public HydrogenCodeStub {
|
|||||||
class TransitionElementsKindStub : public HydrogenCodeStub {
|
class TransitionElementsKindStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
TransitionElementsKindStub(ElementsKind from_kind,
|
TransitionElementsKindStub(ElementsKind from_kind,
|
||||||
ElementsKind to_kind) {
|
ElementsKind to_kind)
|
||||||
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
|
||||||
bit_field_ = FromKindBits::encode(from_kind) |
|
bit_field_ = FromKindBits::encode(from_kind) |
|
||||||
ToKindBits::encode(to_kind);
|
ToKindBits::encode(to_kind);
|
||||||
}
|
}
|
||||||
@ -1403,7 +1441,7 @@ class TransitionElementsKindStub : public HydrogenCodeStub {
|
|||||||
uint32_t bit_field_;
|
uint32_t bit_field_;
|
||||||
|
|
||||||
Major MajorKey() { return TransitionElementsKind; }
|
Major MajorKey() { return TransitionElementsKind; }
|
||||||
int MinorKey() { return bit_field_; }
|
int NotMissMinorKey() { return bit_field_; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
|
DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
|
||||||
};
|
};
|
||||||
@ -1411,12 +1449,10 @@ class TransitionElementsKindStub : public HydrogenCodeStub {
|
|||||||
|
|
||||||
class ArrayNoArgumentConstructorStub : public HydrogenCodeStub {
|
class ArrayNoArgumentConstructorStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
ArrayNoArgumentConstructorStub() {
|
ArrayNoArgumentConstructorStub()
|
||||||
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Major MajorKey() { return ArrayNoArgumentConstructor; }
|
|
||||||
int MinorKey() { return 0; }
|
|
||||||
|
|
||||||
virtual Handle<Code> GenerateCode();
|
virtual Handle<Code> GenerateCode();
|
||||||
|
|
||||||
virtual void InitializeInterfaceDescriptor(
|
virtual void InitializeInterfaceDescriptor(
|
||||||
@ -1424,17 +1460,17 @@ class ArrayNoArgumentConstructorStub : public HydrogenCodeStub {
|
|||||||
CodeStubInterfaceDescriptor* descriptor);
|
CodeStubInterfaceDescriptor* descriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Major MajorKey() { return ArrayNoArgumentConstructor; }
|
||||||
|
int NotMissMinorKey() { return 0; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
|
DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ArraySingleArgumentConstructorStub : public HydrogenCodeStub {
|
class ArraySingleArgumentConstructorStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
ArraySingleArgumentConstructorStub() {
|
ArraySingleArgumentConstructorStub()
|
||||||
}
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {}
|
||||||
|
|
||||||
Major MajorKey() { return ArraySingleArgumentConstructor; }
|
|
||||||
int MinorKey() { return 0; }
|
|
||||||
|
|
||||||
virtual Handle<Code> GenerateCode();
|
virtual Handle<Code> GenerateCode();
|
||||||
|
|
||||||
@ -1443,17 +1479,17 @@ class ArraySingleArgumentConstructorStub : public HydrogenCodeStub {
|
|||||||
CodeStubInterfaceDescriptor* descriptor);
|
CodeStubInterfaceDescriptor* descriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Major MajorKey() { return ArraySingleArgumentConstructor; }
|
||||||
|
int NotMissMinorKey() { return 0; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
|
DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class ArrayNArgumentsConstructorStub : public HydrogenCodeStub {
|
class ArrayNArgumentsConstructorStub : public HydrogenCodeStub {
|
||||||
public:
|
public:
|
||||||
ArrayNArgumentsConstructorStub() {
|
ArrayNArgumentsConstructorStub()
|
||||||
}
|
: HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {}
|
||||||
|
|
||||||
Major MajorKey() { return ArrayNArgumentsConstructor; }
|
|
||||||
int MinorKey() { return 0; }
|
|
||||||
|
|
||||||
virtual Handle<Code> GenerateCode();
|
virtual Handle<Code> GenerateCode();
|
||||||
|
|
||||||
@ -1462,6 +1498,9 @@ class ArrayNArgumentsConstructorStub : public HydrogenCodeStub {
|
|||||||
CodeStubInterfaceDescriptor* descriptor);
|
CodeStubInterfaceDescriptor* descriptor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Major MajorKey() { return ArrayNArgumentsConstructor; }
|
||||||
|
int NotMissMinorKey() { return 0; }
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
|
DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -141,6 +141,31 @@ void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
|
|||||||
|
|
||||||
#define __ ACCESS_MASM(masm)
|
#define __ ACCESS_MASM(masm)
|
||||||
|
|
||||||
|
|
||||||
|
void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
|
||||||
|
// Update the static counter each time a new code stub is generated.
|
||||||
|
Isolate* isolate = masm->isolate();
|
||||||
|
isolate->counters()->code_stubs()->Increment();
|
||||||
|
|
||||||
|
CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
|
||||||
|
int param_count = descriptor->register_param_count_;
|
||||||
|
{
|
||||||
|
// Call the runtime system in a fresh internal frame.
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
ASSERT(descriptor->register_param_count_ == 0 ||
|
||||||
|
eax.is(descriptor->register_params_[param_count - 1]));
|
||||||
|
// Push arguments
|
||||||
|
for (int i = 0; i < param_count; ++i) {
|
||||||
|
__ push(descriptor->register_params_[i]);
|
||||||
|
}
|
||||||
|
ExternalReference miss = descriptor->miss_handler_;
|
||||||
|
__ CallExternalReference(miss, descriptor->register_param_count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ ret(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ToNumberStub::Generate(MacroAssembler* masm) {
|
void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||||
// The ToNumber stub takes one argument in eax.
|
// The ToNumber stub takes one argument in eax.
|
||||||
Label check_heap_number, call_builtin;
|
Label check_heap_number, call_builtin;
|
||||||
|
@ -2766,6 +2766,13 @@ RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
|
||||||
|
UNREACHABLE();
|
||||||
|
CHECK(false);
|
||||||
|
return isolate->heap()->undefined_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
|
RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
|
||||||
ASSERT(args.length() == 3);
|
ASSERT(args.length() == 3);
|
||||||
|
|
||||||
|
1
src/ic.h
1
src/ic.h
@ -59,6 +59,7 @@ namespace internal {
|
|||||||
ICU(UnaryOp_Patch) \
|
ICU(UnaryOp_Patch) \
|
||||||
ICU(BinaryOp_Patch) \
|
ICU(BinaryOp_Patch) \
|
||||||
ICU(CompareIC_Miss) \
|
ICU(CompareIC_Miss) \
|
||||||
|
ICU(Unreachable) \
|
||||||
ICU(ToBoolean_Patch)
|
ICU(ToBoolean_Patch)
|
||||||
//
|
//
|
||||||
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
|
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
|
||||||
|
@ -136,6 +136,31 @@ void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor(
|
|||||||
|
|
||||||
#define __ ACCESS_MASM(masm)
|
#define __ ACCESS_MASM(masm)
|
||||||
|
|
||||||
|
|
||||||
|
void HydrogenCodeStub::GenerateLightweightMiss(MacroAssembler* masm) {
|
||||||
|
// Update the static counter each time a new code stub is generated.
|
||||||
|
Isolate* isolate = masm->isolate();
|
||||||
|
isolate->counters()->code_stubs()->Increment();
|
||||||
|
|
||||||
|
CodeStubInterfaceDescriptor* descriptor = GetInterfaceDescriptor(isolate);
|
||||||
|
int param_count = descriptor->register_param_count_;
|
||||||
|
{
|
||||||
|
// Call the runtime system in a fresh internal frame.
|
||||||
|
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||||
|
ASSERT(descriptor->register_param_count_ == 0 ||
|
||||||
|
rax.is(descriptor->register_params_[param_count - 1]));
|
||||||
|
// Push arguments
|
||||||
|
for (int i = 0; i < param_count; ++i) {
|
||||||
|
__ push(descriptor->register_params_[i]);
|
||||||
|
}
|
||||||
|
ExternalReference miss = descriptor->miss_handler_;
|
||||||
|
__ CallExternalReference(miss, descriptor->register_param_count_);
|
||||||
|
}
|
||||||
|
|
||||||
|
__ Ret();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ToNumberStub::Generate(MacroAssembler* masm) {
|
void ToNumberStub::Generate(MacroAssembler* masm) {
|
||||||
// The ToNumber stub takes one argument in eax.
|
// The ToNumber stub takes one argument in eax.
|
||||||
Label check_heap_number, call_builtin;
|
Label check_heap_number, call_builtin;
|
||||||
|
Loading…
Reference in New Issue
Block a user