// -----------------------------------
// Probe the stub cache.
- ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+ ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
Code::Flags flags = Code::ComputeFlags(
Code::HANDLER, MONOMORPHIC, extra_ic_state,
Code::NORMAL, Code::LOAD_IC);
}
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
- LOperand* context = UseFixed(instr->context(), cp);
- LOperand* global_object = UseFixed(instr->global_object(), r1);
- LOperand* value = UseFixed(instr->value(), r0);
- LStoreGlobalGeneric* result =
- new(zone()) LStoreGlobalGeneric(context, global_object, value);
- return MarkAsCall(result, instr);
-}
-
-
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
LInstruction* result =
V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
V(StoreKeyed) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
};
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
- LStoreGlobalGeneric(LOperand* context,
- LOperand* global_object,
- LOperand* value) {
- inputs_[0] = context;
- inputs_[1] = global_object;
- inputs_[2] = value;
- }
-
- LOperand* context() { return inputs_[0]; }
- LOperand* global_object() { return inputs_[1]; }
- LOperand* value() { return inputs_[2]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
- DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
- Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadContextSlot(LOperand* context) {
}
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
- ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->global_object()).is(r1));
- ASSERT(ToRegister(instr->value()).is(r0));
-
- __ mov(r2, Operand(instr->name()));
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- CONTEXTUAL);
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
-
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
// Name is always in r2.
__ mov(r2, Operand(instr->name()));
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- NOT_CONTEXTUAL);
+ instr->strict_mode_flag());
CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS);
}
class KeyedArrayCallStub: public HICStub {
public:
KeyedArrayCallStub(bool holey, int argc) : HICStub(), argc_(argc) {
- bit_field_ = ContextualBits::encode(false) | HoleyBits::encode(holey);
+ bit_field_ = HoleyBits::encode(holey);
}
virtual Code::Kind kind() const { return Code::KEYED_CALL_IC; }
return GetExtraICState() | ArgcBits::encode(argc_);
}
- class ContextualBits: public BitField<bool, 0, 1> {};
- STATIC_ASSERT(IC::Contextual::kShift == ContextualBits::kShift);
- STATIC_ASSERT(IC::Contextual::kSize == ContextualBits::kSize);
+ // We have to start storing extra ic bits at 1, because calls use bit zero
+ // for string stub state.
+ STATIC_ASSERT(CallICBase::StringStubState::kShift == 0);
+ STATIC_ASSERT(CallICBase::StringStubState::kSize == 1);
class HoleyBits: public BitField<bool, 1, 1> {};
STATIC_ASSERT(Code::kArgumentsBits <= kStubMinorKeyBits - 2);
class ArgcBits: public BitField<int, 2, Code::kArgumentsBits> {};
Code* code = Code::GetCodeFromTargetAddress(relocinfo.target_address());
Code::Kind kind = code->kind();
if (code->is_inline_cache_stub()) {
- if (code->IsContextual()) {
+ if (kind == Code::LOAD_IC &&
+ LoadIC::GetContextualMode(code->extra_ic_state()) == CONTEXTUAL) {
out.AddFormatted(" contextual,");
}
InlineCacheState ic_state = code->ic_state();
void FullCodeGenerator::CallStoreIC(ContextualMode mode, TypeFeedbackId id) {
- Handle<Code> ic = StoreIC::initialize_stub(isolate(), strict_mode(), mode);
+ Handle<Code> ic = StoreIC::initialize_stub(isolate(), strict_mode());
CallIC(ic, mode, id);
}
}
-void HStoreGlobalGeneric::PrintDataTo(StringStream* stream) {
- stream->Add("%o = ", *name());
- value()->PrintNameTo(stream);
-}
-
-
void HLoadContextSlot::PrintDataTo(StringStream* stream) {
value()->PrintNameTo(stream);
stream->Add("[%d]", slot_index());
V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
V(StoreKeyed) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
};
-class HStoreGlobalGeneric : public HTemplateInstruction<3> {
- public:
- inline static HStoreGlobalGeneric* New(Zone* zone,
- HValue* context,
- HValue* global_object,
- Handle<Object> name,
- HValue* value,
- StrictModeFlag strict_mode_flag) {
- return new(zone) HStoreGlobalGeneric(context, global_object,
- name, value, strict_mode_flag);
- }
-
- HValue* context() { return OperandAt(0); }
- HValue* global_object() { return OperandAt(1); }
- Handle<Object> name() const { return name_; }
- HValue* value() { return OperandAt(2); }
- StrictModeFlag strict_mode_flag() { return strict_mode_flag_; }
-
- virtual void PrintDataTo(StringStream* stream) V8_OVERRIDE;
-
- virtual Representation RequiredInputRepresentation(int index) V8_OVERRIDE {
- return Representation::Tagged();
- }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric)
-
- private:
- HStoreGlobalGeneric(HValue* context,
- HValue* global_object,
- Handle<Object> name,
- HValue* value,
- StrictModeFlag strict_mode_flag)
- : name_(name),
- strict_mode_flag_(strict_mode_flag) {
- SetOperandAt(0, context);
- SetOperandAt(1, global_object);
- SetOperandAt(2, value);
- set_representation(Representation::Tagged());
- SetAllSideEffects();
- }
-
- Handle<Object> name_;
- StrictModeFlag strict_mode_flag_;
-};
-
-
class HLoadContextSlot V8_FINAL : public HUnaryOperation {
public:
enum Mode {
}
} else {
HGlobalObject* global_object = Add<HGlobalObject>();
- HStoreGlobalGeneric* instr =
- Add<HStoreGlobalGeneric>(global_object, var->name(),
+ HStoreNamedGeneric* instr =
+ Add<HStoreNamedGeneric>(global_object, var->name(),
value, function_strict_mode_flag());
USE(instr);
ASSERT(instr->HasObservableSideEffects());
// -----------------------------------
// Probe the stub cache.
- ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+ ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
Code::Flags flags = Code::ComputeFlags(
Code::HANDLER, MONOMORPHIC, extra_ic_state,
Code::NORMAL, Code::LOAD_IC);
}
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
- ASSERT(ToRegister(instr->context()).is(esi));
- ASSERT(ToRegister(instr->global_object()).is(edx));
- ASSERT(ToRegister(instr->value()).is(eax));
-
- __ mov(ecx, instr->name());
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- CONTEXTUAL);
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
-
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
__ mov(ecx, instr->name());
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- NOT_CONTEXTUAL);
+ instr->strict_mode_flag());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
}
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
- LOperand* context = UseFixed(instr->context(), esi);
- LOperand* global_object = UseFixed(instr->global_object(), edx);
- LOperand* value = UseFixed(instr->value(), eax);
- LStoreGlobalGeneric* result =
- new(zone()) LStoreGlobalGeneric(context, global_object, value);
- return MarkAsCall(result, instr);
-}
-
-
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
LInstruction* result =
V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
V(StoreKeyed) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
};
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
- LStoreGlobalGeneric(LOperand* context,
- LOperand* global_object,
- LOperand* value) {
- inputs_[0] = context;
- inputs_[1] = global_object;
- inputs_[2] = value;
- }
-
- LOperand* context() { return inputs_[0]; }
- LOperand* global_object() { return inputs_[1]; }
- LOperand* value() { return inputs_[2]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
- DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
- Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadContextSlot(LOperand* context) {
if (!lookup.IsFound()) {
// If the object does not have the requested property, check which
// exception we need to throw.
- return IsUndeclaredGlobal(object)
+ return object->IsGlobalObject()
? ReferenceError("not_defined", name)
: TypeError("undefined_method", object, name);
}
if (lookup.IsInterceptor() && attr == ABSENT) {
// If the object does not have the requested property, check which
// exception we need to throw.
- return IsUndeclaredGlobal(object)
+ return object->IsGlobalObject()
? ReferenceError("not_defined", name)
: TypeError("undefined_method", object, name);
}
Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) {
Handle<Code> ic = isolate->stub_cache()->ComputeLoad(
- UNINITIALIZED, IC::ComputeExtraICState(mode));
+ UNINITIALIZED, ComputeExtraICState(mode));
return ic;
}
Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate,
ContextualMode mode) {
return isolate->stub_cache()->ComputeLoad(
- PREMONOMORPHIC, IC::ComputeExtraICState(mode));
+ PREMONOMORPHIC, ComputeExtraICState(mode));
}
if (!can_store &&
strict_mode() == kStrictMode &&
!(lookup.IsProperty() && lookup.IsReadOnly()) &&
- IsUndeclaredGlobal(object)) {
+ object->IsGlobalObject()) {
// Strict mode doesn't allow setting non-existent global property.
return ReferenceError("not_defined", name);
}
Handle<Code> StoreIC::initialize_stub(Isolate* isolate,
- StrictModeFlag strict_mode,
- ContextualMode mode) {
- ExtraICState extra_state = ComputeExtraICState(strict_mode, mode);
+ StrictModeFlag strict_mode) {
+ ExtraICState extra_state = ComputeExtraICState(strict_mode);
Handle<Code> ic = isolate->stub_cache()->ComputeStore(
UNINITIALIZED, extra_state);
return ic;
Handle<Code> StoreIC::pre_monomorphic_stub(Isolate* isolate,
- StrictModeFlag strict_mode,
- ContextualMode contextual_mode) {
- ExtraICState state = StoreIC::ComputeExtraICState(strict_mode,
- contextual_mode);
+ StrictModeFlag strict_mode) {
+ ExtraICState state = ComputeExtraICState(strict_mode);
return isolate->stub_cache()->ComputeStore(PREMONOMORPHIC, state);
}
EXTRA_CALL_FRAME = 1
};
- // ExtraICState shared by all ICs.
- class Contextual: public BitField<ContextualMode, 0, 1> {};
- STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
- static ExtraICState ComputeExtraICState(ContextualMode mode) {
- return Contextual::encode(mode);
- }
-
- static ContextualMode GetContextualMode(ExtraICState state) {
- return Contextual::decode(state);
- }
-
- static const ExtraICState kContextualState =
- static_cast<int>(CONTEXTUAL) << Contextual::kShift;
-
// Construct the IC structure with the given number of extra
// JavaScript frames on the stack.
IC(FrameDepth depth, Isolate* isolate);
// Clear the inline cache to initial state.
static void Clear(Isolate* isolate, Address address);
- // Returns if this IC is for contextual (no explicit receiver)
- // access to properties.
- bool IsUndeclaredGlobal(Handle<Object> receiver) {
- if (receiver->IsGlobalObject()) {
- return IsCallStub() || IsContextual();
- } else {
- ASSERT(!IsContextual());
- return false;
- }
- }
-
#ifdef DEBUG
- bool IsLoadStub() {
+ bool IsLoadStub() const {
return target()->is_load_stub() || target()->is_keyed_load_stub();
}
- bool IsStoreStub() {
+ bool IsStoreStub() const {
return target()->is_store_stub() || target()->is_keyed_store_stub();
}
-#endif
- bool IsCallStub() {
+ bool IsCallStub() const {
return target()->is_call_stub() || target()->is_keyed_call_stub();
}
+#endif
// Determines which map must be used for keeping the code stub.
// These methods should not be called with undefined or null.
static Handle<Type> MapToType(Handle<Map> type);
static Handle<Type> CurrentTypeOf(Handle<Object> object, Isolate* isolate);
- ContextualMode contextual_mode() const {
- return Contextual::decode(extra_ic_state());
- }
-
- bool IsContextual() const { return contextual_mode() == CONTEXTUAL; }
-
protected:
// Get the call-site target; used for determining the state.
Handle<Code> target() const { return target_; }
class LoadIC: public IC {
public:
+ // ExtraICState bits
+ class Contextual: public BitField<ContextualMode, 0, 1> {};
+ STATIC_ASSERT(static_cast<int>(NOT_CONTEXTUAL) == 0);
+
+ static ExtraICState ComputeExtraICState(ContextualMode mode) {
+ return Contextual::encode(mode);
+ }
+
+ static ContextualMode GetContextualMode(ExtraICState state) {
+ return Contextual::decode(state);
+ }
+
+ ContextualMode contextual_mode() const {
+ return Contextual::decode(extra_ic_state());
+ }
+
explicit LoadIC(FrameDepth depth, Isolate* isolate)
: IC(depth, isolate) {
ASSERT(IsLoadStub());
}
+ // Returns if this IC is for contextual (no explicit receiver)
+ // access to properties.
+ bool IsUndeclaredGlobal(Handle<Object> receiver) {
+ if (receiver->IsGlobalObject()) {
+ return contextual_mode() == CONTEXTUAL;
+ } else {
+ ASSERT(contextual_mode() != CONTEXTUAL);
+ return false;
+ }
+ }
+
// Code generator routines.
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
static void GeneratePreMonomorphic(MacroAssembler* masm) {
protected:
virtual Code::Kind kind() const { return Code::LOAD_IC; }
+ void set_target(Code* code) {
+ // The contextual mode must be preserved across IC patching.
+ ASSERT(GetContextualMode(code->extra_ic_state()) ==
+ GetContextualMode(target()->extra_ic_state()));
+
+ IC::set_target(code);
+ }
+
virtual Handle<Code> slow_stub() const {
return isolate()->builtins()->LoadIC_Slow();
}
class StoreIC: public IC {
public:
- // ExtraICState bits
class StrictModeState: public BitField<StrictModeFlag, 1, 1> {};
static ExtraICState ComputeExtraICState(StrictModeFlag flag) {
return StrictModeState::encode(flag);
}
- static ExtraICState ComputeExtraICState(StrictModeFlag flag,
- ContextualMode mode) {
- return StrictModeState::encode(flag) | Contextual::encode(mode);
- }
-
static StrictModeFlag GetStrictMode(ExtraICState state) {
return StrictModeState::decode(state);
}
StrictModeFlag strict_mode);
static Handle<Code> initialize_stub(Isolate* isolate,
- StrictModeFlag strict_mode,
- ContextualMode mode);
+ StrictModeFlag strict_mode);
MUST_USE_RESULT MaybeObject* Store(
Handle<Object> object,
}
virtual Handle<Code> pre_monomorphic_stub() {
- return pre_monomorphic_stub(isolate(), strict_mode(), contextual_mode());
+ return pre_monomorphic_stub(isolate(), strict_mode());
}
static Handle<Code> pre_monomorphic_stub(Isolate* isolate,
- StrictModeFlag strict_mode,
- ContextualMode contextual_mode);
+ StrictModeFlag strict_mode);
// Update the inline cache and the global stub cache based on the
// lookup result.
// Strict mode must be preserved across IC patching.
ASSERT(GetStrictMode(code->extra_ic_state()) ==
GetStrictMode(target()->extra_ic_state()));
- // As must the contextual mode
- ASSERT(GetContextualMode(code->extra_ic_state()) ==
- GetContextualMode(target()->extra_ic_state()));
IC::set_target(code);
}
// -----------------------------------
// Probe the stub cache.
- ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+ ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
Code::Flags flags = Code::ComputeFlags(
Code::HANDLER, MONOMORPHIC, extra_ic_state,
Code::NORMAL, Code::LOAD_IC);
}
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
- ASSERT(ToRegister(instr->context()).is(cp));
- ASSERT(ToRegister(instr->global_object()).is(a1));
- ASSERT(ToRegister(instr->value()).is(a0));
-
- __ li(a2, Operand(instr->name()));
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- CONTEXTUAL);
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
Register context = ToRegister(instr->context());
// Name is always in a2.
__ li(a2, Operand(instr->name()));
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- NOT_CONTEXTUAL);
+ instr->strict_mode_flag());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
}
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
- LOperand* context = UseFixed(instr->context(), cp);
- LOperand* global_object = UseFixed(instr->global_object(), a1);
- LOperand* value = UseFixed(instr->value(), a0);
- LStoreGlobalGeneric* result =
- new(zone()) LStoreGlobalGeneric(context, global_object, value);
- return MarkAsCall(result, instr);
-}
-
-
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
LInstruction* result =
V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
V(StoreKeyed) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
};
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
- LStoreGlobalGeneric(LOperand* context,
- LOperand* global_object,
- LOperand* value) {
- inputs_[0] = context;
- inputs_[1] = global_object;
- inputs_[2] = value;
- }
-
- LOperand* context() { return inputs_[0]; }
- LOperand* global_object() { return inputs_[1]; }
- LOperand* value() { return inputs_[2]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
- DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
- Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadContextSlot(LOperand* context) {
}
-bool Code::IsContextual() {
- ASSERT(is_inline_cache_stub());
- Kind kind = this->kind();
- if (kind == STORE_IC || kind == LOAD_IC || kind == CALL_IC) {
- ExtraICState extra_state = extra_ic_state();
- return IC::GetContextualMode(extra_state) == CONTEXTUAL;
- }
- return false;
-}
-
-
// Identify kind of code.
const char* Code::Kind2String(Kind kind) {
switch (kind) {
kind == BINARY_OP_IC;
}
- bool IsContextual(); // Only valid for IC stubs.
inline StubType type(); // Only valid for monomorphic IC stubs.
inline int arguments_count(); // Only valid for call IC stubs.
function SetUpPromise() {
%CheckIsBootstrapping()
- global.Promise = $Promise;
+ var global_receiver = %GlobalReceiver(global);
+ global_receiver.Promise = $Promise;
InstallFunctions($Promise, DONT_ENUM, [
"defer", PromiseDeferred,
"resolve", PromiseResolved,
function SetUpProxy() {
%CheckIsBootstrapping()
- global.Proxy = $Proxy;
+ var global_receiver = %GlobalReceiver(global);
+ global_receiver.Proxy = $Proxy;
// Set up non-enumerable properties of the Proxy object.
InstallFunctions($Proxy, DONT_ENUM, [
static MaybeObject* ThrowReferenceError(Isolate* isolate, Name* name) {
// If the load is non-contextual, just return the undefined result.
- // Note that both keyed and non-keyed loads may end up here, so we
- // can't use either LoadIC or KeyedLoadIC constructors.
+ // Note that both keyed and non-keyed loads may end up here.
HandleScope scope(isolate);
- IC ic(IC::NO_EXTRA_FRAME, isolate);
- ASSERT(ic.IsLoadStub());
- if (!ic.IsContextual()) {
+ LoadIC ic(IC::NO_EXTRA_FRAME, isolate);
+ if (ic.contextual_mode() != CONTEXTUAL) {
return isolate->heap()->undefined_value();
}
int argc = Code::ExtractArgumentsCountFromFlags(flags);
Code::Kind kind = Code::ExtractKindFromFlags(flags);
if (kind == Code::CALL_IC) {
- // Call normal is always with a explict receiver.
- ASSERT(!CallIC::Contextual::decode(
- Code::ExtractExtraICStateFromFlags(flags)));
CallIC::GenerateNormal(masm(), argc);
} else {
KeyedCallIC::GenerateNormal(masm(), argc);
Handle<Code> StubCompiler::CompileLoadMegamorphic(Code::Flags flags) {
ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
- ContextualMode mode = IC::GetContextualMode(extra_state);
+ ContextualMode mode = LoadIC::GetContextualMode(extra_state);
LoadIC::GenerateMegamorphic(masm(), mode);
Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadMegamorphic");
PROFILE(isolate(),
Isolate* isolate() { return isolate_; }
Heap* heap() { return isolate()->heap(); }
Factory* factory() { return isolate()->factory(); }
- ContextualMode contextual_mode() {
- return IC::GetContextualMode(extra_state());
- }
static void GenerateTailCall(MacroAssembler* masm, Handle<Code> code);
static Register* registers();
protected:
+ ContextualMode contextual_mode() {
+ return LoadIC::GetContextualMode(extra_state());
+ }
+
virtual Register HandlerFrontendHeader(Handle<Type> type,
Register object_reg,
Handle<JSObject> holder,
// -----------------------------------
// Probe the stub cache.
- ExtraICState extra_ic_state = IC::ComputeExtraICState(mode);
+ ExtraICState extra_ic_state = LoadIC::ComputeExtraICState(mode);
Code::Flags flags = Code::ComputeFlags(
Code::HANDLER, MONOMORPHIC, extra_ic_state,
Code::NORMAL, Code::LOAD_IC);
}
-void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) {
- ASSERT(ToRegister(instr->context()).is(rsi));
- ASSERT(ToRegister(instr->global_object()).is(rdx));
- ASSERT(ToRegister(instr->value()).is(rax));
-
- __ Move(rcx, instr->name());
- Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- CONTEXTUAL);
- CallCode(ic, RelocInfo::CODE_TARGET, instr);
-}
-
-
void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
Register context = ToRegister(instr->context());
Register result = ToRegister(instr->result());
__ Move(rcx, instr->hydrogen()->name());
Handle<Code> ic = StoreIC::initialize_stub(isolate(),
- instr->strict_mode_flag(),
- NOT_CONTEXTUAL);
+ instr->strict_mode_flag());
CallCode(ic, RelocInfo::CODE_TARGET, instr);
}
}
-LInstruction* LChunkBuilder::DoStoreGlobalGeneric(HStoreGlobalGeneric* instr) {
- LOperand* context = UseFixed(instr->context(), rsi);
- LOperand* global_object = UseFixed(instr->global_object(), rdx);
- LOperand* value = UseFixed(instr->value(), rax);
- LStoreGlobalGeneric* result =
- new(zone()) LStoreGlobalGeneric(context, global_object, value);
- return MarkAsCall(result, instr);
-}
-
-
LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) {
LOperand* context = UseRegisterAtStart(instr->value());
LInstruction* result =
V(StoreCodeEntry) \
V(StoreContextSlot) \
V(StoreGlobalCell) \
- V(StoreGlobalGeneric) \
V(StoreKeyed) \
V(StoreKeyedGeneric) \
V(StoreNamedField) \
};
-class LStoreGlobalGeneric V8_FINAL : public LTemplateInstruction<0, 3, 0> {
- public:
- explicit LStoreGlobalGeneric(LOperand* context,
- LOperand* global_object,
- LOperand* value) {
- inputs_[0] = context;
- inputs_[1] = global_object;
- inputs_[2] = value;
- }
-
- LOperand* context() { return inputs_[0]; }
- LOperand* global_object() { return inputs_[1]; }
- LOperand* value() { return inputs_[2]; }
-
- DECLARE_CONCRETE_INSTRUCTION(StoreGlobalGeneric, "store-global-generic")
- DECLARE_HYDROGEN_ACCESSOR(StoreGlobalGeneric)
-
- Handle<Object> name() const { return hydrogen()->name(); }
- StrictModeFlag strict_mode_flag() { return hydrogen()->strict_mode_flag(); }
-};
-
-
class LLoadContextSlot V8_FINAL : public LTemplateInstruction<1, 1, 0> {
public:
explicit LLoadContextSlot(LOperand* context) {
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// CallIC accumulates feedback that string index is out of bounds, then
+// misses
+function foo(index) {
+ return text.charAt(index);
+}
+
+var text = "hi there";
+foo(0);
+foo(0);
+foo(100); // Accumulate feedback that index is out of bounds.
+text = false;
+
+// This line ASSERTS in debug without fix.
+assertThrows(function () { foo(); }, TypeError);