Chromium Code Reviews| Index: runtime/vm/constants_dbc.h |
| diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h |
| index 54fc66b477a12e22d9d5374a3e8e6cc86af12df1..8eaae3d8c5499108b49c703e1e1cf0b3100dbc7b 100644 |
| --- a/runtime/vm/constants_dbc.h |
| +++ b/runtime/vm/constants_dbc.h |
| @@ -119,6 +119,12 @@ namespace dart { |
| // Note: rX is signed so it can be used to address parameters which are |
| // at negative indices with respect to FP. |
| // |
| +// - Swap rA, rX |
| +// |
| +// FP[rA], FP[rX] <- FP[rX], FP[rA] |
| +// Note: rX is signed so it can be used to address parameters which are |
| +// at negative indices with respect to FP. |
| +// |
| // - Push rX |
| // |
| // Push FP[rX] to the stack. |
| @@ -137,10 +143,10 @@ namespace dart { |
| // Invoke function in SP[0] with arguments SP[-(1+ArgC)], ..., SP[-1] and |
| // argument descriptor PP[D]. |
| // |
| -// - InstanceCall ArgC, D; InstanceCall2 ArgC, D; InstanceCall3 ArgC, D |
|
zra
2016/05/19 16:24:27
Was InstanceCall3 never used?
Vyacheslav Egorov (Google)
2016/05/20 12:11:47
Yep.
Turns out we removed 3-arg ICs last year. Th
|
| +// - InstanceCall<N> ArgC, D; InstanceCall<N>Opt ArgC, D |
| // |
| -// Lookup and invoke method using ICData in PP[D] with arguments |
| -// SP[-(1+ArgC)], ..., SP[-1]. |
| +// Lookup and invoke method with N checked arguments using ICData in PP[D] |
| +// with arguments SP[-(1+ArgC)], ..., SP[-1]. |
| // |
| // - NativeCall, NativeBootstrapCall |
| // |
| @@ -166,7 +172,10 @@ namespace dart { |
| // |
| // Takes static field from TOS and ensures that it is initialized. |
| // |
| -// - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS |
| +// - If<Cond>(Num)TOS |
| +// If<Cond>(Num) rA, rD |
| +// |
| +// Cond is either NeStrict or EqStrict |
| // |
| // Skips the next instruction unless the given condition holds. 'Num' |
| // variants perform number check while non-Num variants just compare |
| @@ -194,6 +203,11 @@ namespace dart { |
| // Store SP[0] into array SP[-2] at index SP[-1]. No typechecking is done. |
| // SP[-2] is assumed to be a RawArray, SP[-1] to be a smi. |
| // |
| +// - StoreIndexed rA, rB, rC |
| +// |
| +// Store rC into array rA at index rB. No typechecking is done. |
| +// rA is assumed to be a RawArray, rB to be a smi. |
| +// |
| // - StoreField rA, B, rC |
| // |
| // Store value FP[rC] into object FP[rA] at offset (in words) B. |
| @@ -226,7 +240,7 @@ namespace dart { |
| // B - number of local slots to reserve; |
| // rC - specifies context register to initialize with empty context. |
| // |
| -// - EntryOpt A, B, C |
| +// - EntryOptional A, B, C |
| // |
| // Function prologue for the function with optional or named arguments: |
| // A - expected number of positional arguments; |
| @@ -235,19 +249,36 @@ namespace dart { |
| // |
| // Only one of B and C can be not 0. |
| // |
| -// If B is not 0 then EntryOpt bytecode is followed by B LoadConstant |
| +// If B is not 0 then EntryOptional bytecode is followed by B LoadConstant |
| // bytecodes specifying default values for optional arguments. |
| // |
| -// If C is not 0 then EntryOpt is followed by 2 * B LoadConstant bytecodes. |
| +// If C is not 0 then EntryOptional is followed by 2 * B LoadConstant |
| +// bytecodes. |
| // Bytecode at 2 * i specifies name of the i-th named argument and at |
| // 2 * i + 1 default value. rA part of the LoadConstant bytecode specifies |
| // the location of the parameter on the stack. Here named arguments are |
| // sorted alphabetically to enable linear matching similar to how function |
| // prologues are implemented on other architectures. |
| // |
| -// Note: Unlike Entry bytecode EntryOpt does not setup the frame for |
| +// Note: Unlike Entry bytecode EntryOptional does not setup the frame for |
| // local variables this is done by a separate bytecode Frame. |
| // |
| +// - EntryOptimized A, D |
| +// |
| +// Function prologue for optimized functions with no optional or named |
| +// arguments. |
| +// A - expected number of positional arguments; |
| +// B - number of local slots to reserve for registers; |
| +// |
| +// Note: reserved slots are not initialized because optimized code |
| +// has stack maps attached to call sites. |
| +// |
| +// - HotCheck A, D |
| +// |
| +// Increment current function's usage counter by A and check if it |
| +// exceeds D. If it does trigger (re)optimization of the current |
| +// function. |
| +// |
| // - Frame D |
| // |
| // Reserve and initialize with null space for D local variables. |
| @@ -302,14 +333,28 @@ namespace dart { |
| // match patched call's argument count so that Return instructions continue |
| // to work. |
| // |
| +// TODO(vegorov) the way we replace calls with DebugBreak does not work |
| +// with our smi fast paths because DebugBreak is simply skipped. |
| +// |
| // - LoadClassIdTOS, LoadClassId rA, D |
| // |
| // LoadClassIdTOS loads the class id from the object at SP[0] and stores it |
| // to SP[0]. LoadClassId loads the class id from FP[rA] and stores it to |
| // FP[D]. |
| // |
| -// TODO(vegorov) the way we replace calls with DebugBreak does not work |
| -// with our smi fast paths because DebugBreak is simply skipped. |
| +// - Deopt A, D |
| +// |
| +// If D != 0 then trigger eager deoptimization with deopt id (D - 1). |
| +// If D == 0 then trigger lazy deoptimization. |
| +// |
| +// The meaning of operand A matches that of an A operand in call |
|
Florian Schneider
2016/05/19 13:21:39
Do you mean the ArgC operand?
Vyacheslav Egorov (Google)
2016/05/19 15:19:40
Done.
|
| +// instructions because we could potentially patch calls instructions with |
| +// deopt and we need to ensure that any Return/ReturnTOS instructions |
| +// returning from the patched calls will continue to function, |
| +// e.g. in bytecode sequences like |
| +// |
| +// InstanceCall ... <- lazy deopt inside first call |
| +// InstanceCall ... <- patches seconds call with Deopt |
| // |
| // BYTECODE LIST FORMAT |
| // |
| @@ -336,14 +381,16 @@ namespace dart { |
| #define BYTECODES_LIST(V) \ |
| V(Trap, 0, ___, ___, ___) \ |
| V(Compile, 0, ___, ___, ___) \ |
| + V(HotCheck, A_D, num, num, ___) \ |
| V(Intrinsic, A, num, ___, ___) \ |
| V(Drop1, 0, ___, ___, ___) \ |
| V(DropR, A, num, ___, ___) \ |
| V(Drop, A, num, ___, ___) \ |
| V(Jump, T, tgt, ___, ___) \ |
| - V(Return, A, num, ___, ___) \ |
| + V(Return, A, reg, ___, ___) \ |
| V(ReturnTOS, 0, ___, ___, ___) \ |
| V(Move, A_X, reg, xeg, ___) \ |
| + V(Swap, A_X, reg, xeg, ___) \ |
| V(Push, X, xeg, ___, ___) \ |
| V(LoadConstant, A_D, reg, lit, ___) \ |
| V(LoadClassId, A_D, reg, reg, ___) \ |
| @@ -352,9 +399,10 @@ namespace dart { |
| V(StoreLocal, X, xeg, ___, ___) \ |
| V(PopLocal, X, xeg, ___, ___) \ |
| V(StaticCall, A_D, num, num, ___) \ |
| - V(InstanceCall, A_D, num, num, ___) \ |
| + V(InstanceCall1, A_D, num, num, ___) \ |
| V(InstanceCall2, A_D, num, num, ___) \ |
| - V(InstanceCall3, A_D, num, num, ___) \ |
| + V(InstanceCall1Opt, A_D, num, num, ___) \ |
| + V(InstanceCall2Opt, A_D, num, num, ___) \ |
| V(NativeCall, 0, ___, ___, ___) \ |
| V(NativeBootstrapCall, 0, ___, ___, ___) \ |
| V(AddTOS, 0, ___, ___, ___) \ |
| @@ -372,18 +420,25 @@ namespace dart { |
| V(IfEqStrictTOS, 0, ___, ___, ___) \ |
| V(IfNeStrictNumTOS, 0, ___, ___, ___) \ |
| V(IfEqStrictNumTOS, 0, ___, ___, ___) \ |
| + V(IfNeStrict, A_D, reg, reg, ___) \ |
| + V(IfEqStrict, A_D, reg, reg, ___) \ |
| + V(IfNeStrictNum, A_D, reg, reg, ___) \ |
| + V(IfEqStrictNum, A_D, reg, reg, ___) \ |
| V(CreateArrayTOS, 0, ___, ___, ___) \ |
| V(Allocate, D, lit, ___, ___) \ |
| V(AllocateT, 0, ___, ___, ___) \ |
| V(StoreIndexedTOS, 0, ___, ___, ___) \ |
| - V(StoreField, A_B_C, reg, reg, reg) \ |
| + V(StoreIndexed, A_B_C, reg, reg, reg) \ |
| + V(StoreField, A_B_C, reg, num, reg) \ |
| V(StoreFieldTOS, D, num, ___, ___) \ |
| - V(LoadField, A_B_C, reg, reg, reg) \ |
| + V(LoadField, A_B_C, reg, reg, num) \ |
| V(LoadFieldTOS, D, num, ___, ___) \ |
| V(BooleanNegateTOS, 0, ___, ___, ___) \ |
| + V(BooleanNegate, A_D, reg, reg, ___) \ |
|
zra
2016/05/19 16:24:27
Missing from comments.
Vyacheslav Egorov (Google)
2016/05/20 12:11:47
Done.
|
| V(Throw, A, num, ___, ___) \ |
| V(Entry, A_B_C, num, num, num) \ |
| - V(EntryOpt, A_B_C, num, num, num) \ |
| + V(EntryOptional, A_B_C, num, num, num) \ |
| + V(EntryOptimized, A_D, num, num, ___) \ |
| V(Frame, D, num, ___, ___) \ |
| V(SetFrame, A, num, ___, num) \ |
| V(AllocateContext, D, num, ___, ___) \ |
| @@ -396,6 +451,7 @@ namespace dart { |
| V(CheckStack, 0, ___, ___, ___) \ |
| V(DebugStep, 0, ___, ___, ___) \ |
| V(DebugBreak, A, num, ___, ___) \ |
| + V(Deopt, A_D, num, num, ___) \ |
| typedef uint32_t Instr; |
| @@ -457,15 +513,23 @@ BYTECODES_LIST(DECLARE_BYTECODE) |
| return static_cast<Opcode>(bc & 0xFF); |
| } |
| + DART_FORCE_INLINE static bool IsCallOpcode(Instr instr) { |
| + switch (DecodeOpcode(instr)) { |
| + case Bytecode::kStaticCall: |
| + case Bytecode::kInstanceCall1: |
| + case Bytecode::kInstanceCall2: |
| + case Bytecode::kInstanceCall1Opt: |
| + case Bytecode::kInstanceCall2Opt: |
| + case Bytecode::kDebugBreak: |
| + return true; |
| + |
| + default: |
| + return false; |
| + } |
| + } |
| + |
| DART_FORCE_INLINE static uint8_t DecodeArgc(Instr call) { |
| -#if defined(DEBUG) |
| - const Opcode op = DecodeOpcode(call); |
| - ASSERT((op == Bytecode::kStaticCall) || |
| - (op == Bytecode::kInstanceCall) || |
| - (op == Bytecode::kInstanceCall2) || |
| - (op == Bytecode::kInstanceCall3) || |
| - (op == Bytecode::kDebugBreak)); |
| -#endif |
| + ASSERT(IsCallOpcode(call)); |
| return (call >> 8) & 0xFF; |
| } |
| @@ -484,7 +548,7 @@ typedef int16_t Register; |
| const int16_t FPREG = 0; |
| const int16_t SPREG = 1; |
| const intptr_t kNumberOfCpuRegisters = 20; |
| -const intptr_t kDartAvailableCpuRegs = 0; |
| +const intptr_t kDartAvailableCpuRegs = -1; |
| const intptr_t kNoRegister = -1; |
| const intptr_t kReservedCpuRegisters = 0; |
| const intptr_t ARGS_DESC_REG = 0; |