}
-void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
- // The return address is on the stack.
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register name = LoadDescriptor::NameRegister();
- DCHECK(receiver.is(edx));
- DCHECK(name.is(ecx));
-
- // Probe the stub cache.
- Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
- Code::ComputeHandlerFlags(Code::LOAD_IC));
- masm->isolate()->stub_cache()->GenerateProbe(masm, flags, receiver, name, ebx,
- eax);
-
- // Cache miss: Jump to runtime.
- GenerateMiss(masm);
-}
-
-
void LoadIC::GenerateNormal(MacroAssembler* masm) {
Register dictionary = eax;
DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister()));
Code::Flags flags = Code::RemoveTypeAndHolderFromFlags(
Code::ComputeHandlerFlags(Code::STORE_IC));
masm->isolate()->stub_cache()->GenerateProbe(
- masm, flags, StoreDescriptor::ReceiverRegister(),
+ masm, flags, false, StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(), ebx, no_reg);
// Cache miss: Jump to runtime.
static void ProbeTable(Isolate* isolate, MacroAssembler* masm,
- Code::Flags flags, StubCache::Table table, Register name,
- Register receiver,
+ Code::Flags flags, bool leave_frame,
+ StubCache::Table table, Register name, Register receiver,
// Number of the cache entry pointer-size scaled.
Register offset, Register extra) {
ExternalReference key_offset(isolate->stub_cache()->key_reference(table));
}
#endif
+ if (leave_frame) __ leave();
+
// Jump to the first instruction in the code stub.
__ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(extra);
__ pop(offset);
__ mov(offset, Operand::StaticArray(offset, times_1, value_offset));
+ if (leave_frame) __ leave();
+
// Jump to the first instruction in the code stub.
__ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ jmp(offset);
void StubCache::GenerateProbe(MacroAssembler* masm, Code::Flags flags,
- Register receiver, Register name,
- Register scratch, Register extra, Register extra2,
- Register extra3) {
+ bool leave_frame, Register receiver,
+ Register name, Register scratch, Register extra,
+ Register extra2, Register extra3) {
Label miss;
// Assert that code is valid. The multiplying code relies on the entry size
DCHECK(kCacheIndexShift == kPointerSizeLog2);
// Probe the primary table.
- ProbeTable(isolate(), masm, flags, kPrimary, name, receiver, offset, extra);
+ ProbeTable(isolate(), masm, flags, leave_frame, kPrimary, name, receiver,
+ offset, extra);
// Primary miss: Compute hash for secondary probe.
__ mov(offset, FieldOperand(name, Name::kHashFieldOffset));
__ and_(offset, (kSecondaryTableSize - 1) << kCacheIndexShift);
// Probe the secondary table.
- ProbeTable(isolate(), masm, flags, kSecondary, name, receiver, offset, extra);
+ ProbeTable(isolate(), masm, flags, leave_frame, kSecondary, name, receiver,
+ offset, extra);
// Cache miss: Fall-through and let caller handle the miss by
// entering the runtime system.
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/hydrogen-osr.h"
+#include "src/ic/stub-cache.h"
#include "src/x87/lithium-codegen-x87.h"
namespace v8 {
// Load the result.
__ mov(result,
- BuildFastArrayOperand(instr->elements(),
- instr->key(),
+ BuildFastArrayOperand(instr->elements(), instr->key(),
instr->hydrogen()->key()->representation(),
- FAST_ELEMENTS,
- instr->base_offset()));
+ FAST_ELEMENTS, instr->base_offset()));
// Check for the hole value.
if (instr->hydrogen()->RequiresHoleCheck()) {
}
+void LCodeGen::DoTailCallThroughMegamorphicCache(
+ LTailCallThroughMegamorphicCache* instr) {
+ Register receiver = ToRegister(instr->receiver());
+ Register name = ToRegister(instr->name());
+ DCHECK(receiver.is(LoadDescriptor::ReceiverRegister()));
+ DCHECK(name.is(LoadDescriptor::NameRegister()));
+
+ Register scratch = ebx;
+ Register extra = eax;
+ DCHECK(!scratch.is(receiver) && !scratch.is(name));
+ DCHECK(!extra.is(receiver) && !extra.is(name));
+
+ // Important for the tail-call.
+ bool must_teardown_frame = NeedsEagerFrame();
+
+ // The probe will tail call to a handler if found.
+ isolate()->stub_cache()->GenerateProbe(masm(), instr->hydrogen()->flags(),
+ must_teardown_frame, receiver, name,
+ scratch, extra);
+
+ // Tail call to miss if we ended up here.
+ if (must_teardown_frame) __ leave();
+ LoadIC::GenerateMiss(masm());
+}
+
+
void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
DCHECK(ToRegister(instr->result()).is(eax));
}
+LInstruction* LChunkBuilder::DoTailCallThroughMegamorphicCache(
+ HTailCallThroughMegamorphicCache* instr) {
+ LOperand* context = UseFixed(instr->context(), esi);
+ LOperand* receiver_register =
+ UseFixed(instr->receiver(), LoadDescriptor::ReceiverRegister());
+ LOperand* name_register =
+ UseFixed(instr->name(), LoadDescriptor::NameRegister());
+ // Not marked as call. It can't deoptimize, and it never returns.
+ return new (zone()) LTailCallThroughMegamorphicCache(
+ context, receiver_register, name_register);
+}
+
+
LInstruction* LChunkBuilder::DoInvokeFunction(HInvokeFunction* instr) {
LOperand* context = UseFixed(instr->context(), esi);
LOperand* function = UseFixed(instr->function(), edi);
// Forward declarations.
class LCodeGen;
-#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
- V(AccessArgumentsAt) \
- V(AddI) \
- V(AllocateBlockContext) \
- V(Allocate) \
- V(ApplyArguments) \
- V(ArgumentsElements) \
- V(ArgumentsLength) \
- V(ArithmeticD) \
- V(ArithmeticT) \
- V(BitI) \
- V(BoundsCheck) \
- V(Branch) \
- V(CallJSFunction) \
- V(CallWithDescriptor) \
- V(CallFunction) \
- V(CallNew) \
- V(CallNewArray) \
- V(CallRuntime) \
- V(CallStub) \
- V(CheckInstanceType) \
- V(CheckMaps) \
- V(CheckMapValue) \
- V(CheckNonSmi) \
- V(CheckSmi) \
- V(CheckValue) \
- V(ClampDToUint8) \
- V(ClampIToUint8) \
- V(ClampTToUint8NoSSE2) \
- V(ClassOfTestAndBranch) \
- V(ClobberDoubles) \
- V(CompareMinusZeroAndBranch) \
- V(CompareNumericAndBranch) \
- V(CmpObjectEqAndBranch) \
- V(CmpHoleAndBranch) \
- V(CmpMapAndBranch) \
- V(CmpT) \
- V(ConstantD) \
- V(ConstantE) \
- V(ConstantI) \
- V(ConstantS) \
- V(ConstantT) \
- V(ConstructDouble) \
- V(Context) \
- V(DateField) \
- V(DebugBreak) \
- V(DeclareGlobals) \
- V(Deoptimize) \
- V(DivByConstI) \
- V(DivByPowerOf2I) \
- V(DivI) \
- V(DoubleBits) \
- V(DoubleToI) \
- V(DoubleToSmi) \
- V(Drop) \
- V(Dummy) \
- V(DummyUse) \
- V(FlooringDivByConstI) \
- V(FlooringDivByPowerOf2I) \
- V(FlooringDivI) \
- V(ForInCacheArray) \
- V(ForInPrepareMap) \
- V(FunctionLiteral) \
- V(GetCachedArrayIndex) \
- V(Goto) \
- V(HasCachedArrayIndexAndBranch) \
- V(HasInstanceTypeAndBranch) \
- V(InnerAllocatedObject) \
- V(InstanceOf) \
- V(InstanceOfKnownGlobal) \
- V(InstructionGap) \
- V(Integer32ToDouble) \
- V(InvokeFunction) \
- V(IsConstructCallAndBranch) \
- V(IsObjectAndBranch) \
- V(IsStringAndBranch) \
- V(IsSmiAndBranch) \
- V(IsUndetectableAndBranch) \
- V(Label) \
- V(LazyBailout) \
- V(LoadContextSlot) \
- V(LoadFieldByIndex) \
- V(LoadFunctionPrototype) \
- V(LoadGlobalCell) \
- V(LoadGlobalGeneric) \
- V(LoadKeyed) \
- V(LoadKeyedGeneric) \
- V(LoadNamedField) \
- V(LoadNamedGeneric) \
- V(LoadRoot) \
- V(MapEnumLength) \
- V(MathAbs) \
- V(MathClz32) \
- V(MathExp) \
- V(MathFloor) \
- V(MathFround) \
- V(MathLog) \
- V(MathMinMax) \
- V(MathPowHalf) \
- V(MathRound) \
- V(MathSqrt) \
- V(ModByConstI) \
- V(ModByPowerOf2I) \
- V(ModI) \
- V(MulI) \
- V(NumberTagD) \
- V(NumberTagI) \
- V(NumberTagU) \
- V(NumberUntagD) \
- V(OsrEntry) \
- V(Parameter) \
- V(Power) \
- V(PushArgument) \
- V(RegExpLiteral) \
- V(Return) \
- V(SeqStringGetChar) \
- V(SeqStringSetChar) \
- V(ShiftI) \
- V(SmiTag) \
- V(SmiUntag) \
- V(StackCheck) \
- V(StoreCodeEntry) \
- V(StoreContextSlot) \
- V(StoreFrameContext) \
- V(StoreGlobalCell) \
- V(StoreKeyed) \
- V(StoreKeyedGeneric) \
- V(StoreNamedField) \
- V(StoreNamedGeneric) \
- V(StringAdd) \
- V(StringCharCodeAt) \
- V(StringCharFromCode) \
- V(StringCompareAndBranch) \
- V(SubI) \
- V(TaggedToI) \
- V(ThisFunction) \
- V(ToFastProperties) \
- V(TransitionElementsKind) \
- V(TrapAllocationMemento) \
- V(Typeof) \
- V(TypeofIsAndBranch) \
- V(Uint32ToDouble) \
- V(UnknownOSRValue) \
+#define LITHIUM_CONCRETE_INSTRUCTION_LIST(V) \
+ V(AccessArgumentsAt) \
+ V(AddI) \
+ V(AllocateBlockContext) \
+ V(Allocate) \
+ V(ApplyArguments) \
+ V(ArgumentsElements) \
+ V(ArgumentsLength) \
+ V(ArithmeticD) \
+ V(ArithmeticT) \
+ V(BitI) \
+ V(BoundsCheck) \
+ V(Branch) \
+ V(CallJSFunction) \
+ V(CallWithDescriptor) \
+ V(CallFunction) \
+ V(CallNew) \
+ V(CallNewArray) \
+ V(CallRuntime) \
+ V(CallStub) \
+ V(CheckInstanceType) \
+ V(CheckMaps) \
+ V(CheckMapValue) \
+ V(CheckNonSmi) \
+ V(CheckSmi) \
+ V(CheckValue) \
+ V(ClampDToUint8) \
+ V(ClampIToUint8) \
+ V(ClampTToUint8NoSSE2) \
+ V(ClassOfTestAndBranch) \
+ V(ClobberDoubles) \
+ V(CompareMinusZeroAndBranch) \
+ V(CompareNumericAndBranch) \
+ V(CmpObjectEqAndBranch) \
+ V(CmpHoleAndBranch) \
+ V(CmpMapAndBranch) \
+ V(CmpT) \
+ V(ConstantD) \
+ V(ConstantE) \
+ V(ConstantI) \
+ V(ConstantS) \
+ V(ConstantT) \
+ V(ConstructDouble) \
+ V(Context) \
+ V(DateField) \
+ V(DebugBreak) \
+ V(DeclareGlobals) \
+ V(Deoptimize) \
+ V(DivByConstI) \
+ V(DivByPowerOf2I) \
+ V(DivI) \
+ V(DoubleBits) \
+ V(DoubleToI) \
+ V(DoubleToSmi) \
+ V(Drop) \
+ V(Dummy) \
+ V(DummyUse) \
+ V(FlooringDivByConstI) \
+ V(FlooringDivByPowerOf2I) \
+ V(FlooringDivI) \
+ V(ForInCacheArray) \
+ V(ForInPrepareMap) \
+ V(FunctionLiteral) \
+ V(GetCachedArrayIndex) \
+ V(Goto) \
+ V(HasCachedArrayIndexAndBranch) \
+ V(HasInstanceTypeAndBranch) \
+ V(InnerAllocatedObject) \
+ V(InstanceOf) \
+ V(InstanceOfKnownGlobal) \
+ V(InstructionGap) \
+ V(Integer32ToDouble) \
+ V(InvokeFunction) \
+ V(IsConstructCallAndBranch) \
+ V(IsObjectAndBranch) \
+ V(IsStringAndBranch) \
+ V(IsSmiAndBranch) \
+ V(IsUndetectableAndBranch) \
+ V(Label) \
+ V(LazyBailout) \
+ V(LoadContextSlot) \
+ V(LoadFieldByIndex) \
+ V(LoadFunctionPrototype) \
+ V(LoadGlobalCell) \
+ V(LoadGlobalGeneric) \
+ V(LoadKeyed) \
+ V(LoadKeyedGeneric) \
+ V(LoadNamedField) \
+ V(LoadNamedGeneric) \
+ V(LoadRoot) \
+ V(MapEnumLength) \
+ V(MathAbs) \
+ V(MathClz32) \
+ V(MathExp) \
+ V(MathFloor) \
+ V(MathFround) \
+ V(MathLog) \
+ V(MathMinMax) \
+ V(MathPowHalf) \
+ V(MathRound) \
+ V(MathSqrt) \
+ V(ModByConstI) \
+ V(ModByPowerOf2I) \
+ V(ModI) \
+ V(MulI) \
+ V(NumberTagD) \
+ V(NumberTagI) \
+ V(NumberTagU) \
+ V(NumberUntagD) \
+ V(OsrEntry) \
+ V(Parameter) \
+ V(Power) \
+ V(PushArgument) \
+ V(RegExpLiteral) \
+ V(Return) \
+ V(SeqStringGetChar) \
+ V(SeqStringSetChar) \
+ V(ShiftI) \
+ V(SmiTag) \
+ V(SmiUntag) \
+ V(StackCheck) \
+ V(StoreCodeEntry) \
+ V(StoreContextSlot) \
+ V(StoreFrameContext) \
+ V(StoreGlobalCell) \
+ V(StoreKeyed) \
+ V(StoreKeyedGeneric) \
+ V(StoreNamedField) \
+ V(StoreNamedGeneric) \
+ V(StringAdd) \
+ V(StringCharCodeAt) \
+ V(StringCharFromCode) \
+ V(StringCompareAndBranch) \
+ V(SubI) \
+ V(TaggedToI) \
+ V(TailCallThroughMegamorphicCache) \
+ V(ThisFunction) \
+ V(ToFastProperties) \
+ V(TransitionElementsKind) \
+ V(TrapAllocationMemento) \
+ V(Typeof) \
+ V(TypeofIsAndBranch) \
+ V(Uint32ToDouble) \
+ V(UnknownOSRValue) \
V(WrapReceiver)
};
+class LTailCallThroughMegamorphicCache FINAL
+ : public LTemplateInstruction<0, 3, 0> {
+ public:
+ explicit LTailCallThroughMegamorphicCache(LOperand* context,
+ LOperand* receiver,
+ LOperand* name) {
+ inputs_[0] = context;
+ inputs_[1] = receiver;
+ inputs_[2] = name;
+ }
+
+ LOperand* context() { return inputs_[0]; }
+ LOperand* receiver() { return inputs_[1]; }
+ LOperand* name() { return inputs_[2]; }
+
+ DECLARE_CONCRETE_INSTRUCTION(TailCallThroughMegamorphicCache,
+ "tail-call-through-megamorphic-cache")
+ DECLARE_HYDROGEN_ACCESSOR(TailCallThroughMegamorphicCache)
+};
+
+
class LUnknownOSRValue FINAL : public LTemplateInstruction<1, 0, 0> {
public:
virtual bool HasInterestingComment(LCodeGen* gen) const OVERRIDE {
LOperand* target() const { return inputs_[0]; }
+ DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
+
private:
DECLARE_CONCRETE_INSTRUCTION(CallWithDescriptor, "call-with-descriptor")
- DECLARE_HYDROGEN_ACCESSOR(CallWithDescriptor)
virtual void PrintDataTo(StringStream* stream) OVERRIDE;