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();
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");
: 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();
+ }
}
Handle<Code> FastCloneShallowArrayStub::GenerateCode() {
- CodeStubGraphBuilder<FastCloneShallowArrayStub> builder(this);
- LChunk* chunk = OptimizeGraph(builder.CreateGraph());
- return chunk->Codegen();
+ return DoGenerateCode(this);
}
#define V8_CODE_STUBS_H_
#include "allocation.h"
+#include "assembler.h"
#include "globals.h"
#include "codegen.h"
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) {
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; }
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_;
};
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);
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_);
// 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);
}
int length_;
Major MajorKey() { return FastCloneShallowObject; }
- int MinorKey() { return length_; }
+ int NotMissMinorKey() { return length_; }
DISALLOW_COPY_AND_ASSIGN(FastCloneShallowObjectStub);
};
public:
KeyedLoadDictionaryElementStub() {}
- Major MajorKey() { return KeyedLoadElement; }
- int MinorKey() { return DICTIONARY_ELEMENTS; }
-
void Generate(MacroAssembler* masm);
private:
+ Major MajorKey() { return KeyedLoadElement; }
+ int MinorKey() { return DICTIONARY_ELEMENTS; }
+
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);
}
CodeStubInterfaceDescriptor* descriptor);
private:
- class IsJSArrayBits: public BitField<bool, 8, 1> {};
class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
+ class IsJSArrayBits: public BitField<bool, 8, 1> {};
uint32_t bit_field_;
Major MajorKey() { return KeyedLoadElement; }
- int MinorKey() { return bit_field_; }
+ int NotMissMinorKey() { return bit_field_; }
DISALLOW_COPY_AND_ASSIGN(KeyedLoadFastElementStub);
};
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_);
}
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);
};
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);
}
uint32_t bit_field_;
Major MajorKey() { return TransitionElementsKind; }
- int MinorKey() { return bit_field_; }
+ int NotMissMinorKey() { return bit_field_; }
DISALLOW_COPY_AND_ASSIGN(TransitionElementsKindStub);
};
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();
virtual void InitializeInterfaceDescriptor(
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();
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();
CodeStubInterfaceDescriptor* descriptor);
private:
+ Major MajorKey() { return ArrayNArgumentsConstructor; }
+ int NotMissMinorKey() { return 0; }
+
DISALLOW_COPY_AND_ASSIGN(ArrayNArgumentsConstructorStub);
};