Revision: 14342
Author: [email protected]
Date: Thu Apr 18 13:37:27 2013
Log: Add infrastructure to automatucally generate IC miss stubs
Review URL: https://codereview.chromium.org/13886013
http://code.google.com/p/v8/source/detail?r=14342
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/code-stubs-hydrogen.cc
/branches/bleeding_edge/src/code-stubs.cc
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/ic.cc
/branches/bleeding_edge/src/ic.h
/branches/bleeding_edge/src/x64/code-stubs-x64.cc
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Apr 18 03:32:18
2013
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Apr 18 13:37:27
2013
@@ -159,6 +159,30 @@
__ cmp(scratch1, scratch2);
__ b(ne, not_a_heap_number);
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Thu Apr 18 03:51:24
2013
+++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Thu Apr 18 13:37:27
2013
@@ -61,11 +61,7 @@
arguments_length_(NULL),
info_(stub, isolate),
context_(NULL) {
- int major_key = stub->MajorKey();
- descriptor_ = isolate->code_stub_interface_descriptor(major_key);
- if (descriptor_->register_param_count_ < 0) {
- stub->InitializeInterfaceDescriptor(isolate, descriptor_);
- }
+ descriptor_ = stub->GetInterfaceDescriptor(isolate);
parameters_.Reset(new HParameter*[descriptor_->register_param_count_]);
}
virtual bool BuildGraph();
@@ -96,6 +92,9 @@
bool CodeStubGraphBuilderBase::BuildGraph() {
+ // Update the static counter each time a new code stub is generated.
+ isolate()->counters()->code_stubs()->Increment();
+
if (FLAG_trace_hydrogen) {
const char* name = CodeStub::MajorName(stub()->MajorKey(), false);
PrintF("-----------------------------------------------------------\n");
@@ -176,16 +175,87 @@
: CodeStubGraphBuilderBase(Isolate::Current(), stub) {}
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()); }
};
+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>
static Handle<Code> DoGenerateCode(Stub* stub) {
- CodeStubGraphBuilder<Stub> builder(stub);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen();
+ Isolate* isolate = Isolate::Current();
+ CodeStub::Major major_key =
+ 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 @@
Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
- CodeStubGraphBuilder<FastCloneShallowArrayStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen();
+ return DoGenerateCode(this);
}
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc Thu Apr 18 02:50:46 2013
+++ /branches/bleeding_edge/src/code-stubs.cc Thu Apr 18 13:37:27 2013
@@ -37,6 +37,16 @@
namespace v8 {
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) {
UnseededNumberDictionary* stubs = isolate->heap()->code_stubs();
int index = stubs->FindEntry(GetKey());
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Thu Apr 18 02:50:46 2013
+++ /branches/bleeding_edge/src/code-stubs.h Thu Apr 18 13:37:27 2013
@@ -29,6 +29,7 @@
#define V8_CODE_STUBS_H_
#include "allocation.h"
+#include "assembler.h"
#include "globals.h"
#include "codegen.h"
@@ -260,17 +261,15 @@
enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
+
struct CodeStubInterfaceDescriptor {
- CodeStubInterfaceDescriptor()
- : register_param_count_(-1),
- stack_parameter_count_(NULL),
- function_mode_(NOT_JS_FUNCTION_STUB_MODE),
- register_params_(NULL) { }
+ CodeStubInterfaceDescriptor();
int register_param_count_;
const Register* stack_parameter_count_;
StubFunctionMode function_mode_;
Register* register_params_;
Address deoptimization_handler_;
+ ExternalReference miss_handler_;
int environment_length() const {
if (stack_parameter_count_ != NULL) {
@@ -283,18 +282,51 @@
class HydrogenCodeStub : public CodeStub {
public:
- // Retrieve the code for the stub. Generate the code if needed.
- virtual Handle<Code> GenerateCode() = 0;
+ enum InitializationState {
+ 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; }
CodeStubInterfaceDescriptor* GetInterfaceDescriptor(Isolate* isolate) {
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(
Isolate* isolate,
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 @@
FastCloneShallowArrayStub(Mode mode,
AllocationSiteMode allocation_site_mode,
int length)
- : mode_(mode),
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS),
+ mode_(mode),
allocation_site_mode_(allocation_site_mode),
length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
ASSERT_GE(length_, 0);
@@ -513,7 +546,7 @@
STATIC_ASSERT(kFastCloneModeCount < 16);
STATIC_ASSERT(kMaximumClonedLength < 16);
Major MajorKey() { return FastCloneShallowArray; }
- int MinorKey() {
+ int NotMissMinorKey() {
return AllocationSiteModeBits::encode(allocation_site_mode_)
| ModeBits::encode(mode_)
| LengthBits::encode(length_);
@@ -526,7 +559,9 @@
// Maximum number of properties in copied object.
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_LE(length_, kMaximumClonedProperties);
}
@@ -543,7 +578,7 @@
int length_;
Major MajorKey() { return FastCloneShallowObject; }
- int MinorKey() { return length_; }
+ int NotMissMinorKey() { return length_; }
DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
};
@@ -1291,19 +1326,20 @@
public:
KeyedLoadDictionaryElementStub() {}
+ void Generate(MacroAssembler* masm);
+
+ private:
Major MajorKey() { return KeyedLoadElement; }
int MinorKey() { return DICTIONARY_ELEMENTS; }
- void Generate(MacroAssembler* masm);
-
- private:
DISALLOW_COPY_AND_ASSIGN(KeyedLoadDictionaryElementStub);
};
class KeyedLoadFastElementStub : public HydrogenCodeStub {
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) |
IsJSArrayBits::encode(is_js_array);
}
@@ -1323,12 +1359,12 @@
CodeStubInterfaceDescriptor* descriptor);
private:
+ class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
class IsJSArrayBits: public BitField<bool, 8, 1> {};
- class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
uint32_t bit_field_;
Major MajorKey() { return KeyedLoadElement; }
- int MinorKey() { return bit_field_; }
+ int NotMissMinorKey() { return bit_field_; }
DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
};
@@ -1338,14 +1374,12 @@
public:
KeyedStoreFastElementStub(bool is_js_array,
ElementsKind elements_kind,
- KeyedAccessStoreMode mode) {
+ KeyedAccessStoreMode mode)
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
bit_field_ = ElementsKindBits::encode(elements_kind) |
IsJSArrayBits::encode(is_js_array) |
StoreModeBits::encode(mode);
}
-
- Major MajorKey() { return KeyedStoreElement; }
- int MinorKey() { return bit_field_; }
bool is_js_array() const {
return IsJSArrayBits::decode(bit_field_);
@@ -1370,6 +1404,9 @@
class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
class IsJSArrayBits: public BitField<bool, 12, 1> {};
uint32_t bit_field_;
+
+ Major MajorKey() { return KeyedStoreElement; }
+ int NotMissMinorKey() { return bit_field_; }
DISALLOW_COPY_AND_ASSIGN(KeyedStoreFastElementStub);
};
@@ -1378,7 +1415,8 @@
class TransitionElementsKindStub : public HydrogenCodeStub {
public:
TransitionElementsKindStub(ElementsKind from_kind,
- ElementsKind to_kind) {
+ ElementsKind to_kind)
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
bit_field_ = FromKindBits::encode(from_kind) |
ToKindBits::encode(to_kind);
}
@@ -1403,7 +1441,7 @@
uint32_t bit_field_;
Major MajorKey() { return TransitionElementsKind; }
- int MinorKey() { return bit_field_; }
+ int NotMissMinorKey() { return bit_field_; }
DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
};
@@ -1411,11 +1449,9 @@
class ArrayNoArgumentConstructorStub : public HydrogenCodeStub {
public:
- ArrayNoArgumentConstructorStub() {
+ ArrayNoArgumentConstructorStub()
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {
}
-
- Major MajorKey() { return ArrayNoArgumentConstructor; }
- int MinorKey() { return 0; }
virtual Handle<Code> GenerateCode();
@@ -1424,17 +1460,17 @@
CodeStubInterfaceDescriptor* descriptor);
private:
+ Major MajorKey() { return ArrayNoArgumentConstructor; }
+ int NotMissMinorKey() { return 0; }
+
DISALLOW_COPY_AND_ASSIGN(ArrayNoArgumentConstructorStub);
};
class ArraySingleArgumentConstructorStub : public HydrogenCodeStub {
public:
- ArraySingleArgumentConstructorStub() {
- }
-
- Major MajorKey() { return ArraySingleArgumentConstructor; }
- int MinorKey() { return 0; }
+ ArraySingleArgumentConstructorStub()
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {}
virtual Handle<Code> GenerateCode();
@@ -1443,17 +1479,17 @@
CodeStubInterfaceDescriptor* descriptor);
private:
+ Major MajorKey() { return ArraySingleArgumentConstructor; }
+ int NotMissMinorKey() { return 0; }
+
DISALLOW_COPY_AND_ASSIGN(ArraySingleArgumentConstructorStub);
};
class ArrayNArgumentsConstructorStub : public HydrogenCodeStub {
public:
- ArrayNArgumentsConstructorStub() {
- }
-
- Major MajorKey() { return ArrayNArgumentsConstructor; }
- int MinorKey() { return 0; }
+ ArrayNArgumentsConstructorStub()
+ : HydrogenCodeStub(CODE_STUB_IS_NOT_MISS) {}
virtual Handle<Code> GenerateCode();
@@ -1462,6 +1498,9 @@
CodeStubInterfaceDescriptor* descriptor);
private:
+ Major MajorKey() { return ArrayNArgumentsConstructor; }
+ int NotMissMinorKey() { return 0; }
+
DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
};
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Wed Apr 17 06:51:08
2013
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Apr 18 13:37:27
2013
@@ -141,6 +141,31 @@
#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) {
// The ToNumber stub takes one argument in eax.
Label check_heap_number, call_builtin;
=======================================
--- /branches/bleeding_edge/src/ic.cc Thu Apr 18 01:14:59 2013
+++ /branches/bleeding_edge/src/ic.cc Thu Apr 18 13:37:27 2013
@@ -2764,6 +2764,13 @@
ic.UpdateCaches(args.at<Object>(0), args.at<Object>(1));
return ic.target();
}
+
+
+RUNTIME_FUNCTION(MaybeObject*, Unreachable) {
+ UNREACHABLE();
+ CHECK(false);
+ return isolate->heap()->undefined_value();
+}
RUNTIME_FUNCTION(MaybeObject*, ToBoolean_Patch) {
=======================================
--- /branches/bleeding_edge/src/ic.h Thu Mar 28 05:43:19 2013
+++ /branches/bleeding_edge/src/ic.h Thu Apr 18 13:37:27 2013
@@ -59,6 +59,7 @@
ICU(UnaryOp_Patch) \
ICU(BinaryOp_Patch) \
ICU(CompareIC_Miss) \
+ ICU(Unreachable) \
ICU(ToBoolean_Patch)
//
// IC is the base class for LoadIC, StoreIC, CallIC, KeyedLoadIC,
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Wed Apr 17 09:41:02
2013
+++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu Apr 18 13:37:27
2013
@@ -136,6 +136,31 @@
#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) {
// The ToNumber stub takes one argument in eax.
Label check_heap_number, call_builtin;
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.