Chromium Code Reviews| Index: runtime/vm/constants_dbc.h |
| diff --git a/runtime/vm/constants_dbc.h b/runtime/vm/constants_dbc.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..962bdd5991ebf015eea7bd4681080d21b09c30fb |
| --- /dev/null |
| +++ b/runtime/vm/constants_dbc.h |
| @@ -0,0 +1,476 @@ |
| +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +#ifndef VM_CONSTANTS_DBC_H_ |
| +#define VM_CONSTANTS_DBC_H_ |
| + |
| +#include "platform/globals.h" |
| +#include "platform/assert.h" |
| +#include "platform/utils.h" |
| + |
| + |
| +namespace dart { |
| + |
| +// List of Dart Bytecode instructions. |
| +// |
| +// INTERPRETER STATE |
| +// |
| +// current frame info (see stack_frame_dbc.h for layout) |
| +// v-----^-----v |
| +// ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ |
| +// ~ | ~ ~ | FP[0] | FP[1] | ~ ~ | SP[-1]| SP[0] | |
| +// ~----+----~ ~----+-------+-------+-~ ~-+-------+-------+-~ |
| +// ^ ^ |
| +// FP SP |
| +// |
| +// |
| +// The state of execution is captured in few interpreter registers: |
| +// |
| +// FP - base of the current frame |
| +// SP - top of the stack (TOS) for the current frame |
| +// PP - object pool for the currently execution function |
| +// |
| +// Frame info stored below FP additionally contains pointers to the currently |
| +// executing function and code (see stack_frame_dbc.h for more information). |
| +// |
| +// In the unoptimized code most of bytecodes take operands implicitly from |
| +// stack and store results again on the stack. Constant operands are usually |
| +// taken from the object pool by index. |
| +// |
| +// ENCODING |
| +// |
| +// Each instruction is a 32-bit integer with opcode stored in the least |
| +// significant byte. The following operand encodings are used: |
| +// |
| +// 0........8.......16.......24.......32 |
| +// +--------+--------+--------+--------+ |
| +// | opcode |~~~~~~~~~~~~~~~~~~~~~~~~~~| 0: no operands |
| +// +--------+--------+--------+--------+ |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode | A |~~~~~~~~~~~~~~~~~| A: single unsigned 8-bit operand |
| +// +--------+--------+--------+--------+ |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode | A | D | A_D: unsigned 8-bit operand and |
| +// +--------+--------+--------+--------+ unsigned 16-bit operand |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode | A | X | A_X: unsigned 8-bit operand and |
| +// +--------+--------+--------+--------+ signed 16-bit operand |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode |~~~~~~~~| D | D: unsigned 16-bit operand |
| +// +--------+--------+--------+--------+ |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode |~~~~~~~~| X | X: signed 16-bit operand |
| +// +--------+--------+--------+--------+ |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode | A | B | C | A_B_C: 3 unsigned 8-bit operands |
| +// +--------+--------+--------+--------+ |
| +// |
| +// +--------+--------+--------+--------+ |
| +// | opcode | T | T: signed 24-bit operand |
| +// +--------+--------+--------+--------+ |
| +// |
| +// |
| +// INSTRUCTIONS |
| +// |
| +// - Trap |
| +// |
| +// Unreachable instruction. |
| +// |
| +// - Compile |
| +// |
| +// Compile current function and start executing newly produced code |
| +// (used to implement LazyCompileStub); |
| +// |
| +// - Intrinsic id |
| +// |
| +// Execute intrinsic with the given id. If intrinsic returns true then |
| +// return from the current function to the caller passing value produced |
| +// by the intrinsic as a result; |
| +// |
| +// - Drop1; DropR n; Drop n |
| +// |
| +// Drop 1 or n values from the stack, if instruction is DropR push the first |
| +// dropped value to the stack; |
| +// |
| +// - Jump target |
| +// |
| +// Jump to the given target. Target is specified as offset from the PC of the |
| +// jump instruction. |
| +// |
| +// - Return R; ReturnTOS |
| +// |
| +// Return to the caller using either a value from the given register or a |
| +// value from the top-of-stack as a result. |
| +// |
| +// Note: return instruction knows how many arguments to remove from the |
| +// stack because it can look at the call instruction at caller's PC and |
| +// take argument count from it. |
| +// |
| +// - Move rA, rX |
| +// |
| +// FP[rA] <- FP[rX] |
| +// Note: rX is singed so it can be used to address parameters which are |
|
Florian Schneider
2016/04/12 02:29:59
s/singed/signed
Vyacheslav Egorov (Google)
2016/04/12 09:01:21
Done.
|
| +// at negative indices with respect to FP. |
| +// |
| +// - Push rX |
| +// |
| +// Push FP[rX] to the stack. |
| +// |
| +// - LoadConstant rA, D; PushConstant D |
| +// |
| +// Load value at index D from constant pool into FP[rA] or push it onto the |
| +// stack. |
| +// |
| +// - StoreLocal rX; PopLocal rX |
| +// |
| +// Store top of the stack into FP[rX] and pop it if needed. |
| +// |
| +// - StaticCall ArgC, D |
| +// |
| +// 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 |
| +// |
| +// Lookup and invoke method using ICData in PP[D] with arguments |
| +// SP[-(1+ArgC)], ..., SP[-1]. |
| +// |
| +// - NativeCall, NativeBootstrapCall |
| +// |
| +// Invoke native function SP[-1] with argc_tag SP[0]. |
| +// |
| +// - AddTOS; SubTOS; MulTOS; BitOrTOS; BitAndTOS; EqualTOS; LessThanTOS; |
| +// GreaterThanTOS; |
| +// |
| +// Smi fast-path for a corresponding method. Checks if SP[0] and SP[-1] are |
| +// both smis and result of SP[0] <op> SP[-1] is a smi - if this is true |
| +// then pops operands and pushes result on the stack and skips the next |
| +// instruction (which implements a slow path fallback). |
| +// |
| +// - StoreStaticTOS D |
| +// |
| +// Stores TOS into the static field PP[D]. |
| +// |
| +// - PushStatic |
| +// |
| +// Pushes value of the static field PP[D] on to the stack. |
| +// |
| +// - InitStaticTOS |
| +// |
| +// Takes static field from TOS and ensures that it is initialized. |
| +// |
| +// - IfNeStrictTOS; IfEqStrictTOS; IfNeStrictNumTOS; IfEqStrictNumTOS |
| +// |
| +// Skips the next instruction unless the given condition holds. 'Num' |
| +// variants perform number check while non-Num variants just compare |
| +// RawObject pointers. |
| +// |
| +// Used to implement conditional jump: |
| +// |
| +// IfNeStrictTOS |
| +// Jump T ;; jump if not equal |
| +// |
| +// - CreateArrayTOS |
| +// |
| +// Allocate array of length SP[0] with type arguments SP[-1]. |
| +// |
| +// - Allocate D |
| +// |
| +// Allocate object of class PP[D] with no type arguments. |
| +// |
| +// - AllocateT |
| +// |
| +// Allocate object of class SP[0] with type arguments SP[-1]. |
| +// |
| +// - StoreIndexedTOS |
| +// |
| +// 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. |
| +// |
| +// - StoreField rA, B, rC |
| +// |
| +// Store value FP[rC] into object FP[rA] at offset (in words) B. |
| +// |
| +// - StoreFieldTOS D |
| +// |
| +// Store value SP[0] into object SP[-1] at offset (in words) D. |
| +// |
| +// - LoadField rA, rB, C |
| +// |
| +// Load value at offset (in words) C from object FP[rB] into FP[rA]. |
| +// |
| +// - LoadFieldTOS D |
| +// |
| +// Push value at offset (in words) D from object SP[0]. |
| +// |
| +// - BooleanNegateTOS |
| +// |
| +// SP[0] = !SP[0] |
| +// |
| +// - Throw A |
| +// |
| +// Throw (Rethrow if A != 0) exception. Exception object and stack object |
| +// are taken from TOS. |
| +// |
| +// - Entry A, B, rC |
| +// |
| +// Function prologue for the function with no optional or named arguments: |
| +// A - expected number of positional arguments; |
| +// B - number of local slots to reserve; |
| +// rC - specifies context register to initialize with empty context. |
| +// |
| +// - EntryOpt A, B, C |
| +// |
| +// Function prologue for the function with optional or named arguments: |
| +// A - expected number of positional arguments; |
| +// B - number of optional arguments; |
| +// C - number of named arguments; |
| +// |
| +// Only one of B and C can be not 0. |
| +// |
| +// If B is not 0 then EntryOpt 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. |
| +// Bytecode at 2 * i specifies name of the i-th named argument and at |
| +// 2 * i + 1 default value. rA part of the LoadConsant bytecode specifies |
|
Florian Schneider
2016/04/12 02:29:59
s/LoadConsant/LoadConstant/
Vyacheslav Egorov (Google)
2016/04/12 09:01:21
Done.
|
| +// 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 |
| +// local variables this is done by a separate bytecode Frame. |
| +// |
| +// - Frame D |
| +// |
| +// Reserve and initialize with null space for D local variables. |
| +// |
| +// - SetFrame A |
| +// |
| +// Reinitialize SP assuming that current frame has size A. |
| +// Used to drop temporaries from the stack in the exception handler. |
| +// |
| +// - AllocateContext D |
| +// |
| +// Allocate Context object assuming for D context variables. |
| +// |
| +// - CloneContext |
| +// |
| +// Clone context stored in TOS. |
| +// |
| +// - MoveSpecial rA, D |
| +// |
| +// Copy special values from inside interpreter to FP[rA]. Currently only |
| +// used to pass exception object (D = 0) and stack trace object (D = 1) to |
| +// catch handler. |
| +// |
| +// - InstantiateType D |
| +// |
| +// Instantiate type PP[D] with instantiator type arguments SP[0]. |
| +// |
| +// - InstantiateTypeArgumentsTOS D |
| +// |
| +// Instantiate type arguments PP[D] with instantiator SP[0]. |
| +// |
| +// - AssertAssignable D |
| +// |
| +// Assert that SP[-3] is assignable to variable named SP[0] of type |
| +// SP[-1] with type arguments SP[-2] using SubtypeTestCache PP[D]. |
| +// |
| +// - AssertBoolean A |
| +// |
| +// Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0). |
| +// |
| +// - CheckStack |
| +// |
| +// Compare SP against isolate stack limit and call StackOverflow handler if |
| +// necessary. |
| +// |
| +// - DebugStep, DebugBreak A |
| +// |
| +// Debugger support. DebugBreak is bytecode that can be patched into the |
| +// instruction stream to trigger in place breakpoint. |
| +// |
| +// When patching instance or static call with DebugBreak we set A to |
| +// 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. |
| +// |
| +// BYTECODE LIST FORMAT |
| +// |
| +// Bytecode list below is specified using the following format: |
| +// |
| +// V(BytecodeName, OperandForm, Op1, Op2, Op3) |
| +// |
| +// - OperandForm specifies operand encoding and should be one of 0, A, T, A_D, |
| +// A_X, X, D (see ENCODING section above). |
| +// |
| +// - Op1, Op2, Op2 specify operand meaning. Possible values: |
| +// |
| +// ___ ignored / non-existent operand |
| +// num immediate operand |
| +// lit constant literal from object pool |
| +// reg register (unsigned FP relative local) |
| +// xeg x-register (signed FP relative local) |
| +// tgt jump target relative to the PC of the current instruction |
| +// |
| +// TODO(vegorov) jump targets should be encoded relative to PC of the next |
| +// instruction because PC is incremeted immediately after fetch |
| +// and before decoding. |
| +// |
| +#define BYTECODES_LIST(V) \ |
| + V(Trap, 0, ___, ___, ___) \ |
| + V(Compile, 0, ___, ___, ___) \ |
| + V(Intrinsic, A, num, ___, ___) \ |
| + V(Drop1, 0, ___, ___, ___) \ |
| + V(DropR, A, num, ___, ___) \ |
| + V(Drop, A, num, ___, ___) \ |
| + V(Jump, T, tgt, ___, ___) \ |
| + V(Return, A, num, ___, ___) \ |
| + V(ReturnTOS, 0, ___, ___, ___) \ |
| + V(Move, A_X, reg, xeg, ___) \ |
| + V(Push, X, xeg, ___, ___) \ |
| + V(LoadConstant, A_D, reg, lit, ___) \ |
| + V(PushConstant, D, lit, ___, ___) \ |
| + V(StoreLocal, X, xeg, ___, ___) \ |
| + V(PopLocal, X, xeg, ___, ___) \ |
| + V(StaticCall, A_D, num, num, ___) \ |
| + V(InstanceCall, A_D, num, num, ___) \ |
| + V(InstanceCall2, A_D, num, num, ___) \ |
| + V(InstanceCall3, A_D, num, num, ___) \ |
| + V(NativeCall, 0, ___, ___, ___) \ |
| + V(NativeBootstrapCall, 0, ___, ___, ___) \ |
| + V(AddTOS, 0, ___, ___, ___) \ |
| + V(SubTOS, 0, ___, ___, ___) \ |
| + V(MulTOS, 0, ___, ___, ___) \ |
| + V(BitOrTOS, 0, ___, ___, ___) \ |
| + V(BitAndTOS, 0, ___, ___, ___) \ |
| + V(EqualTOS, 0, ___, ___, ___) \ |
| + V(LessThanTOS, 0, ___, ___, ___) \ |
| + V(GreaterThanTOS, 0, ___, ___, ___) \ |
| + V(StoreStaticTOS, D, lit, ___, ___) \ |
| + V(PushStatic, D, lit, ___, ___) \ |
| + V(InitStaticTOS, 0, ___, ___, ___) \ |
| + V(IfNeStrictTOS, 0, ___, ___, ___) \ |
| + V(IfEqStrictTOS, 0, ___, ___, ___) \ |
| + V(IfNeStrictNumTOS, 0, ___, ___, ___) \ |
| + V(IfEqStrictNumTOS, 0, ___, ___, ___) \ |
| + V(CreateArrayTOS, 0, ___, ___, ___) \ |
| + V(Allocate, D, lit, ___, ___) \ |
| + V(AllocateT, 0, ___, ___, ___) \ |
| + V(StoreIndexedTOS, 0, ___, ___, ___) \ |
| + V(StoreField, A_B_C, reg, reg, reg) \ |
| + V(StoreFieldTOS, D, num, ___, ___) \ |
| + V(LoadField, A_B_C, reg, reg, reg) \ |
| + V(LoadFieldTOS, D, num, ___, ___) \ |
| + V(BooleanNegateTOS, 0, ___, ___, ___) \ |
| + V(Throw, A, num, ___, ___) \ |
| + V(Entry, A_B_C, num, num, num) \ |
| + V(EntryOpt, A_B_C, num, num, num) \ |
| + V(Frame, D, num, ___, ___) \ |
| + V(SetFrame, A, num, ___, num) \ |
| + V(AllocateContext, D, num, ___, ___) \ |
| + V(CloneContext, 0, ___, ___, ___) \ |
| + V(MoveSpecial, A_D, reg, num, ___) \ |
| + V(InstantiateType, D, lit, ___, ___) \ |
| + V(InstantiateTypeArgumentsTOS, A_D, num, lit, ___) \ |
| + V(AssertAssignable, D, num, lit, ___) \ |
| + V(AssertBoolean, A, num, ___, ___) \ |
| + V(CheckStack, 0, ___, ___, ___) \ |
| + V(DebugStep, 0, ___, ___, ___) \ |
| + V(DebugBreak, A, num, ___, ___) \ |
| + |
| +typedef uint32_t Instr; |
| + |
| +class Bytecode { |
| + public: |
| + enum Opcode { |
| +#define DECLARE_BYTECODE(name, encoding, op1, op2, op3) k##name, |
| +BYTECODES_LIST(DECLARE_BYTECODE) |
| +#undef DECLARE_BYTECODE |
| + }; |
| + |
| + static Instr Encode(Opcode op, uintptr_t a, uintptr_t b, uintptr_t c) { |
| + ASSERT((a & 0xFF) == a); |
| + ASSERT((b & 0xFF) == b); |
| + ASSERT((c & 0xFF) == c); |
| + return op | (a << 8) | (b << 16) | (c << 24); |
| + } |
| + |
| + static Instr Encode(Opcode op, uintptr_t a, uintptr_t d) { |
| + ASSERT((a & 0x00FF) == a); |
| + ASSERT((d & 0xFFFF) == d); |
| + return op | (a << 8) | (d << 16); |
| + } |
| + |
| + static Instr Encode(Opcode op, uint32_t abc) { |
|
Florian Schneider
2016/04/12 02:29:59
Maybe also add an assert that abc fits into range:
Vyacheslav Egorov (Google)
2016/04/12 09:01:21
Removed this function - it was incorrectly used to
|
| + return op | (abc << 8); |
| + } |
| + |
| + static Instr EncodeSigned(Opcode op, uintptr_t a, intptr_t x) { |
| + ASSERT((a & 0x00FF) == a); |
| + ASSERT((x << 16) >> 16 == x); |
| + return op | (a << 8) | (x << 16); |
| + } |
| + |
| + static Instr EncodeSigned(Opcode op, intptr_t x) { |
| + ASSERT((x << 8) >> 8 == x); |
| + return op | (x << 8); |
| + } |
| + |
| + static Instr Encode(Opcode op) { |
| + return op; |
| + } |
| + |
| + DART_FORCE_INLINE static Opcode DecodeOpcode(Instr bc) { |
| + return static_cast<Opcode>(bc & 0xFF); |
| + } |
| + |
| + 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 |
| + return (call >> 8) & 0xFF; |
| + } |
| +}; |
| + |
| +// Various dummy declarations to make shared code compile. |
| +// TODO(vegorov) we need to prune away as much dead code as possible instead |
| +// of just making it compile. |
| +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 kNoRegister = -1; |
| +const intptr_t kReservedCpuRegisters = 0; |
| +const intptr_t ARGS_DESC_REG = 0; |
| +const intptr_t CODE_REG = 0; |
| +const intptr_t kExceptionObjectReg = 0; |
| +const intptr_t kStackTraceObjectReg = 0; |
| +const intptr_t CTX = 0; |
| + |
| +enum FpuRegister { kNoFpuRegister = -1, kFakeFpuRegister }; |
| +const FpuRegister FpuTMP = kFakeFpuRegister; |
| +const intptr_t kNumberOfFpuRegisters = 1; |
| + |
| +enum Condition { EQ, NE }; |
| + |
| +} // namespace dart |
| + |
| +#endif // VM_CONSTANTS_DBC_H_ |