diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart index f4214929e87..3677188f8cc 100644 --- a/pkg/vm/lib/bytecode/assembler.dart +++ b/pkg/vm/lib/bytecode/assembler.dart @@ -98,7 +98,7 @@ class BytecodeAssembler { int _uint8(int v) => _unsigned(v, 8); int _uint16(int v) => _unsigned(v, 16); - int _int8(int v) => _signed(v, 8); +// int _int8(int v) => _signed(v, 8); int _int16(int v) => _signed(v, 16); int _int24(int v) => _signed(v, 24); @@ -110,8 +110,11 @@ class BytecodeAssembler { int _encodeAD(Opcode opcode, int ra, int rd) => _uint8(opcode.index) | (_uint8(ra) << 8) | (_uint16(rd) << 16); - int _encodeAX(Opcode opcode, int ra, int rx) => - _uint8(opcode.index) | (_uint8(ra) << 8) | (_int16(rx) << 16); +// TODO(alexmarkov) This format is currently unused. Restore it if needed, or +// remove it once bytecode instruction set is finalized. +// +// int _encodeAX(Opcode opcode, int ra, int rx) => +// _uint8(opcode.index) | (_uint8(ra) << 8) | (_int16(rx) << 16); int _encodeD(Opcode opcode, int rd) => _uint8(opcode.index) | (_uint16(rd) << 16); @@ -125,11 +128,14 @@ class BytecodeAssembler { (_uint8(rb) << 16) | (_uint8(rc) << 24); - int _encodeABY(Opcode opcode, int ra, int rb, int ry) => - _uint8(opcode.index) | - (_uint8(ra) << 8) | - (_uint8(rb) << 16) | - (_int8(ry) << 24); +// TODO(alexmarkov) This format is currently unused. Restore it if needed, or +// remove it once bytecode instruction set is finalized. +// +// int _encodeABY(Opcode opcode, int ra, int rb, int ry) => +// _uint8(opcode.index) | +// (_uint8(ra) << 8) | +// (_uint8(rb) << 16) | +// (_int8(ry) << 24); int _encodeT(Opcode opcode, int rt) => _uint8(opcode.index) | (_int24(rt) << 8); @@ -138,34 +144,10 @@ class BytecodeAssembler { emitWord(_encode0(Opcode.kTrap)); } - void emitNop(int ra, int rd) { - emitWord(_encodeAD(Opcode.kNop, ra, rd)); - } - - void emitCompile() { - emitWord(_encode0(Opcode.kCompile)); - } - - void emitHotCheck(int ra, int rd) { - emitWord(_encodeAD(Opcode.kHotCheck, ra, rd)); - } - - void emitIntrinsic(int ra) { - emitWord(_encodeA(Opcode.kIntrinsic, ra)); - } - void emitDrop1() { emitWord(_encode0(Opcode.kDrop1)); } - void emitDropR(int ra) { - emitWord(_encodeA(Opcode.kDropR, ra)); - } - - void emitDrop(int ra) { - emitWord(_encodeA(Opcode.kDrop, ra)); - } - void emitJump(Label label) { emitWord(_encodeT(Opcode.kJump, label.jumpOperand(offset))); } @@ -209,22 +191,10 @@ class BytecodeAssembler { _setWord(pos, _encodeT(opcode, rt)); } - void emitReturn(int ra) { - emitWord(_encodeA(Opcode.kReturn, ra)); - } - void emitReturnTOS() { emitWord(_encode0(Opcode.kReturnTOS)); } - void emitMove(int ra, int rx) { - emitWord(_encodeAX(Opcode.kMove, ra, rx)); - } - - void emitSwap(int ra, int rx) { - emitWord(_encodeAX(Opcode.kSwap, ra, rx)); - } - void emitPush(int rx) { emitWord(_encodeX(Opcode.kPush, rx)); } @@ -233,14 +203,6 @@ class BytecodeAssembler { emitWord(_encodeAD(Opcode.kLoadConstant, ra, rd)); } - void emitLoadClassId(int ra, int rd) { - emitWord(_encodeAD(Opcode.kLoadClassId, ra, rd)); - } - - void emitLoadClassIdTOS() { - emitWord(_encode0(Opcode.kLoadClassIdTOS)); - } - void emitPushConstant(int rd) { emitWord(_encodeD(Opcode.kPushConstant, rd)); } @@ -273,258 +235,14 @@ class BytecodeAssembler { emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd)); } - void emitStaticCall(int ra, int rd) { - emitWord(_encodeAD(Opcode.kStaticCall, ra, rd)); - } - void emitInstanceCall(int ra, int rd) { emitWord(_encodeAD(Opcode.kInstanceCall, ra, rd)); } - void emitInstanceCall1Opt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kInstanceCall1Opt, ra, rd)); - } - - void emitInstanceCall2Opt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kInstanceCall2Opt, ra, rd)); - } - - void emitPushPolymorphicInstanceCall(int ra, int rd) { - emitWord(_encodeAD(Opcode.kPushPolymorphicInstanceCall, ra, rd)); - } - - void emitPushPolymorphicInstanceCallByRange(int ra, int rd) { - emitWord(_encodeAD(Opcode.kPushPolymorphicInstanceCallByRange, ra, rd)); - } - void emitNativeCall(int rd) { emitWord(_encodeD(Opcode.kNativeCall, rd)); } - void emitOneByteStringFromCharCode(int ra, int rx) { - emitWord(_encodeAX(Opcode.kOneByteStringFromCharCode, ra, rx)); - } - - void emitStringToCharCode(int ra, int rx) { - emitWord(_encodeAX(Opcode.kStringToCharCode, ra, rx)); - } - - void emitAddTOS() { - emitWord(_encode0(Opcode.kAddTOS)); - } - - void emitSubTOS() { - emitWord(_encode0(Opcode.kSubTOS)); - } - - void emitMulTOS() { - emitWord(_encode0(Opcode.kMulTOS)); - } - - void emitBitOrTOS() { - emitWord(_encode0(Opcode.kBitOrTOS)); - } - - void emitBitAndTOS() { - emitWord(_encode0(Opcode.kBitAndTOS)); - } - - void emitEqualTOS() { - emitWord(_encode0(Opcode.kEqualTOS)); - } - - void emitLessThanTOS() { - emitWord(_encode0(Opcode.kLessThanTOS)); - } - - void emitGreaterThanTOS() { - emitWord(_encode0(Opcode.kGreaterThanTOS)); - } - - void emitSmiAddTOS() { - emitWord(_encode0(Opcode.kSmiAddTOS)); - } - - void emitSmiSubTOS() { - emitWord(_encode0(Opcode.kSmiSubTOS)); - } - - void emitSmiMulTOS() { - emitWord(_encode0(Opcode.kSmiMulTOS)); - } - - void emitSmiBitAndTOS() { - emitWord(_encode0(Opcode.kSmiBitAndTOS)); - } - - void emitAdd(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kAdd, ra, rb, rc)); - } - - void emitSub(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kSub, ra, rb, rc)); - } - - void emitMul(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kMul, ra, rb, rc)); - } - - void emitDiv(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDiv, ra, rb, rc)); - } - - void emitMod(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kMod, ra, rb, rc)); - } - - void emitShl(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kShl, ra, rb, rc)); - } - - void emitShr(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kShr, ra, rb, rc)); - } - - void emitShlImm(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kShlImm, ra, rb, rc)); - } - - void emitNeg(int ra, int rd) { - emitWord(_encodeAD(Opcode.kNeg, ra, rd)); - } - - void emitBitOr(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kBitOr, ra, rb, rc)); - } - - void emitBitAnd(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kBitAnd, ra, rb, rc)); - } - - void emitBitXor(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kBitXor, ra, rb, rc)); - } - - void emitBitNot(int ra, int rd) { - emitWord(_encodeAD(Opcode.kBitNot, ra, rd)); - } - - void emitMin(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kMin, ra, rb, rc)); - } - - void emitMax(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kMax, ra, rb, rc)); - } - - void emitWriteIntoDouble(int ra, int rd) { - emitWord(_encodeAD(Opcode.kWriteIntoDouble, ra, rd)); - } - - void emitUnboxDouble(int ra, int rd) { - emitWord(_encodeAD(Opcode.kUnboxDouble, ra, rd)); - } - - void emitCheckedUnboxDouble(int ra, int rd) { - emitWord(_encodeAD(Opcode.kCheckedUnboxDouble, ra, rd)); - } - - void emitUnboxInt32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kUnboxInt32, ra, rb, rc)); - } - - void emitBoxInt32(int ra, int rd) { - emitWord(_encodeAD(Opcode.kBoxInt32, ra, rd)); - } - - void emitBoxUint32(int ra, int rd) { - emitWord(_encodeAD(Opcode.kBoxUint32, ra, rd)); - } - - void emitSmiToDouble(int ra, int rd) { - emitWord(_encodeAD(Opcode.kSmiToDouble, ra, rd)); - } - - void emitDoubleToSmi(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDoubleToSmi, ra, rd)); - } - - void emitDAdd(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDAdd, ra, rb, rc)); - } - - void emitDSub(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDSub, ra, rb, rc)); - } - - void emitDMul(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDMul, ra, rb, rc)); - } - - void emitDDiv(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDDiv, ra, rb, rc)); - } - - void emitDNeg(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDNeg, ra, rd)); - } - - void emitDSqrt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDSqrt, ra, rd)); - } - - void emitDMin(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDMin, ra, rb, rc)); - } - - void emitDMax(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDMax, ra, rb, rc)); - } - - void emitDCos(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDCos, ra, rd)); - } - - void emitDSin(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDSin, ra, rd)); - } - - void emitDPow(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDPow, ra, rb, rc)); - } - - void emitDMod(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kDMod, ra, rb, rc)); - } - - void emitDTruncate(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDTruncate, ra, rd)); - } - - void emitDFloor(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDFloor, ra, rd)); - } - - void emitDCeil(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDCeil, ra, rd)); - } - - void emitDoubleToFloat(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDoubleToFloat, ra, rd)); - } - - void emitFloatToDouble(int ra, int rd) { - emitWord(_encodeAD(Opcode.kFloatToDouble, ra, rd)); - } - - void emitDoubleIsNaN(int ra) { - emitWord(_encodeA(Opcode.kDoubleIsNaN, ra)); - } - - void emitDoubleIsInfinite(int ra) { - emitWord(_encodeA(Opcode.kDoubleIsInfinite, ra)); - } - void emitStoreStaticTOS(int rd) { emitWord(_encodeD(Opcode.kStoreStaticTOS, rd)); } @@ -533,130 +251,10 @@ class BytecodeAssembler { emitWord(_encodeD(Opcode.kPushStatic, rd)); } - void emitInitStaticTOS() { - emitWord(_encode0(Opcode.kInitStaticTOS)); - } - - void emitIfNeStrictTOS() { - emitWord(_encode0(Opcode.kIfNeStrictTOS)); - } - - void emitIfEqStrictTOS() { - emitWord(_encode0(Opcode.kIfEqStrictTOS)); - } - - void emitIfNeStrictNumTOS() { - emitWord(_encode0(Opcode.kIfNeStrictNumTOS)); - } - - void emitIfEqStrictNumTOS() { - emitWord(_encode0(Opcode.kIfEqStrictNumTOS)); - } - - void emitIfSmiLtTOS() { - emitWord(_encode0(Opcode.kIfSmiLtTOS)); - } - - void emitIfSmiLeTOS() { - emitWord(_encode0(Opcode.kIfSmiLeTOS)); - } - - void emitIfSmiGeTOS() { - emitWord(_encode0(Opcode.kIfSmiGeTOS)); - } - - void emitIfSmiGtTOS() { - emitWord(_encode0(Opcode.kIfSmiGtTOS)); - } - - void emitIfNeStrict(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfNeStrict, ra, rd)); - } - - void emitIfEqStrict(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfEqStrict, ra, rd)); - } - - void emitIfLe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfLe, ra, rd)); - } - - void emitIfLt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfLt, ra, rd)); - } - - void emitIfGe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfGe, ra, rd)); - } - - void emitIfGt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfGt, ra, rd)); - } - - void emitIfULe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfULe, ra, rd)); - } - - void emitIfULt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfULt, ra, rd)); - } - - void emitIfUGe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfUGe, ra, rd)); - } - - void emitIfUGt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfUGt, ra, rd)); - } - - void emitIfDNe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfDNe, ra, rd)); - } - - void emitIfDEq(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfDEq, ra, rd)); - } - - void emitIfDLe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfDLe, ra, rd)); - } - - void emitIfDLt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfDLt, ra, rd)); - } - - void emitIfDGe(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfDGe, ra, rd)); - } - - void emitIfDGt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfDGt, ra, rd)); - } - - void emitIfNeStrictNum(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfNeStrictNum, ra, rd)); - } - - void emitIfEqStrictNum(int ra, int rd) { - emitWord(_encodeAD(Opcode.kIfEqStrictNum, ra, rd)); - } - - void emitIfEqNull(int ra) { - emitWord(_encodeA(Opcode.kIfEqNull, ra)); - } - - void emitIfNeNull(int ra) { - emitWord(_encodeA(Opcode.kIfNeNull, ra)); - } - void emitCreateArrayTOS() { emitWord(_encode0(Opcode.kCreateArrayTOS)); } - void emitCreateArrayOpt(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kCreateArrayOpt, ra, rb, rc)); - } - void emitAllocate(int rd) { emitWord(_encodeD(Opcode.kAllocate, rd)); } @@ -665,154 +263,10 @@ class BytecodeAssembler { emitWord(_encode0(Opcode.kAllocateT)); } - void emitAllocateOpt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kAllocateOpt, ra, rd)); - } - - void emitAllocateTOpt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kAllocateTOpt, ra, rd)); - } - void emitStoreIndexedTOS() { emitWord(_encode0(Opcode.kStoreIndexedTOS)); } - void emitStoreIndexed(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexed, ra, rb, rc)); - } - - void emitStoreIndexedUint8(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexedUint8, ra, rb, rc)); - } - - void emitStoreIndexedExternalUint8(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexedExternalUint8, ra, rb, rc)); - } - - void emitStoreIndexedOneByteString(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexedOneByteString, ra, rb, rc)); - } - - void emitStoreIndexedUint32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexedUint32, ra, rb, rc)); - } - - void emitStoreIndexedFloat32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexedFloat32, ra, rb, rc)); - } - - void emitStoreIndexed4Float32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexed4Float32, ra, rb, rc)); - } - - void emitStoreIndexedFloat64(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexedFloat64, ra, rb, rc)); - } - - void emitStoreIndexed8Float64(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreIndexed8Float64, ra, rb, rc)); - } - - void emitNoSuchMethod() { - emitWord(_encode0(Opcode.kNoSuchMethod)); - } - - void emitTailCall() { - emitWord(_encode0(Opcode.kTailCall)); - } - - void emitTailCallOpt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kTailCallOpt, ra, rd)); - } - - void emitLoadArgDescriptor() { - emitWord(_encode0(Opcode.kLoadArgDescriptor)); - } - - void emitLoadArgDescriptorOpt(int ra) { - emitWord(_encodeA(Opcode.kLoadArgDescriptorOpt, ra)); - } - - void emitLoadFpRelativeSlot(int rx) { - emitWord(_encodeX(Opcode.kLoadFpRelativeSlot, rx)); - } - - void emitLoadFpRelativeSlotOpt(int ra, int rb, int ry) { - emitWord(_encodeABY(Opcode.kLoadFpRelativeSlotOpt, ra, rb, ry)); - } - - void emitStoreFpRelativeSlot(int rx) { - emitWord(_encodeX(Opcode.kStoreFpRelativeSlot, rx)); - } - - void emitStoreFpRelativeSlotOpt(int ra, int rb, int ry) { - emitWord(_encodeABY(Opcode.kStoreFpRelativeSlotOpt, ra, rb, ry)); - } - - void emitLoadIndexedTOS() { - emitWord(_encode0(Opcode.kLoadIndexedTOS)); - } - - void emitLoadIndexed(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexed, ra, rb, rc)); - } - - void emitLoadIndexedUint8(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedUint8, ra, rb, rc)); - } - - void emitLoadIndexedInt8(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedInt8, ra, rb, rc)); - } - - void emitLoadIndexedInt32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedInt32, ra, rb, rc)); - } - - void emitLoadIndexedUint32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedUint32, ra, rb, rc)); - } - - void emitLoadIndexedExternalUint8(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedExternalUint8, ra, rb, rc)); - } - - void emitLoadIndexedExternalInt8(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedExternalInt8, ra, rb, rc)); - } - - void emitLoadIndexedFloat32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedFloat32, ra, rb, rc)); - } - - void emitLoadIndexed4Float32(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexed4Float32, ra, rb, rc)); - } - - void emitLoadIndexedFloat64(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedFloat64, ra, rb, rc)); - } - - void emitLoadIndexed8Float64(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexed8Float64, ra, rb, rc)); - } - - void emitLoadIndexedOneByteString(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedOneByteString, ra, rb, rc)); - } - - void emitLoadIndexedTwoByteString(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadIndexedTwoByteString, ra, rb, rc)); - } - - void emitStoreField(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kStoreField, ra, rb, rc)); - } - - void emitStoreFieldExt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kStoreFieldExt, ra, rd)); - } - void emitStoreFieldTOS(int rd) { emitWord(_encodeD(Opcode.kStoreFieldTOS, rd)); } @@ -825,18 +279,6 @@ class BytecodeAssembler { emitWord(_encodeD(Opcode.kStoreContextVar, rd)); } - void emitLoadField(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadField, ra, rb, rc)); - } - - void emitLoadFieldExt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kLoadFieldExt, ra, rd)); - } - - void emitLoadUntagged(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kLoadUntagged, ra, rb, rc)); - } - void emitLoadFieldTOS(int rd) { emitWord(_encodeD(Opcode.kLoadFieldTOS, rd)); } @@ -857,10 +299,6 @@ class BytecodeAssembler { emitWord(_encode0(Opcode.kBooleanNegateTOS)); } - void emitBooleanNegate(int ra, int rd) { - emitWord(_encodeAD(Opcode.kBooleanNegate, ra, rd)); - } - void emitThrow(int ra) { emitWord(_encodeA(Opcode.kThrow, ra)); } @@ -869,10 +307,6 @@ class BytecodeAssembler { emitWord(_encodeD(Opcode.kEntry, rd)); } - void emitEntryOptimized(int ra, int rd) { - emitWord(_encodeAD(Opcode.kEntryOptimized, ra, rd)); - } - void emitFrame(int rd) { emitWord(_encodeD(Opcode.kFrame, rd)); } @@ -885,10 +319,6 @@ class BytecodeAssembler { emitWord(_encodeD(Opcode.kAllocateContext, rd)); } - void emitAllocateUninitializedContext(int ra, int rd) { - emitWord(_encodeAD(Opcode.kAllocateUninitializedContext, ra, rd)); - } - void emitCloneContext() { emitWord(_encode0(Opcode.kCloneContext)); } @@ -905,14 +335,6 @@ class BytecodeAssembler { emitWord(_encodeAD(Opcode.kInstantiateTypeArgumentsTOS, ra, rd)); } - void emitInstanceOf() { - emitWord(_encode0(Opcode.kInstanceOf)); - } - - void emitBadTypeError() { - emitWord(_encode0(Opcode.kBadTypeError)); - } - void emitAssertAssignable(int ra, int rd) { emitWord(_encodeAD(Opcode.kAssertAssignable, ra, rd)); } @@ -925,70 +347,14 @@ class BytecodeAssembler { emitWord(_encodeA(Opcode.kAssertBoolean, ra)); } - void emitTestSmi(int ra, int rd) { - emitWord(_encodeAD(Opcode.kTestSmi, ra, rd)); - } - - void emitTestCids(int ra, int rd) { - emitWord(_encodeAD(Opcode.kTestCids, ra, rd)); - } - - void emitCheckSmi(int ra) { - emitWord(_encodeA(Opcode.kCheckSmi, ra)); - } - - void emitCheckEitherNonSmi(int ra, int rd) { - emitWord(_encodeAD(Opcode.kCheckEitherNonSmi, ra, rd)); - } - - void emitCheckClassId(int ra, int rd) { - emitWord(_encodeAD(Opcode.kCheckClassId, ra, rd)); - } - - void emitCheckClassIdRange(int ra, int rd) { - emitWord(_encodeAD(Opcode.kCheckClassIdRange, ra, rd)); - } - - void emitCheckBitTest(int ra, int rd) { - emitWord(_encodeAD(Opcode.kCheckBitTest, ra, rd)); - } - - void emitCheckCids(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kCheckCids, ra, rb, rc)); - } - - void emitCheckCidsByRange(int ra, int rb, int rc) { - emitWord(_encodeABC(Opcode.kCheckCidsByRange, ra, rb, rc)); - } - void emitCheckStack() { emitWord(_encode0(Opcode.kCheckStack)); } - void emitCheckStackAlwaysExit() { - emitWord(_encode0(Opcode.kCheckStackAlwaysExit)); - } - void emitCheckFunctionTypeArgs(int ra, int rd) { emitWord(_encodeAD(Opcode.kCheckFunctionTypeArgs, ra, rd)); } - void emitDebugStep() { - emitWord(_encode0(Opcode.kDebugStep)); - } - - void emitDebugBreak(int ra) { - emitWord(_encodeA(Opcode.kDebugBreak, ra)); - } - - void emitDeopt(int ra, int rd) { - emitWord(_encodeAD(Opcode.kDeopt, ra, rd)); - } - - void emitDeoptRewind() { - emitWord(_encode0(Opcode.kDeoptRewind)); - } - void emitEntryFixed(int ra, int rd) { emitWord(_encodeAD(Opcode.kEntryFixed, ra, rd)); } diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart index b2f6179a31f..0ae7cf0310a 100644 --- a/pkg/vm/lib/bytecode/dbc.dart +++ b/pkg/vm/lib/bytecode/dbc.dart @@ -2,65 +2,58 @@ // 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. -library vm.bytecode.dbc; +/// Dart kernel bytecode instructions (described in runtime/vm/constants_kbc.h). -// List of changes from original DBC (described in runtime/vm/constants_dbc.h): -// -// 1. StoreFieldTOS, LoadFieldTOS instructions: -// D = index of constant pool entry with InstanceField tag. -// (instead of field offset in words). -// -// 2. EntryOptional instruction is revived in order to re-shuffle optional -// parameters. This DBC instruction was removed at -// https://github.com/dart-lang/sdk/commit/cf1de7d46cd88e204380e8f96a993439be56b24c -// -// 3. NativeCall instruction is modified to have 'D' format and take 1 argument: -// D = index of NativeEntry constant pool entry -// -// 4. JumpIfNoAsserts instruction is added. This instruction jumps to the given -// target if assertions are not enabled. It has the same format as Jump -// instruction. -// -// 5. StoreContextParent stores context SP[0] into `parent` field of context SP[-1]. -// -// 6. LoadContextParent loads parent from context SP[0]. -// -// 7. StoreContextVar stores value SP[0] into context SP[-1] at index D. -// -// 8. LoadContextVar loads value from context SP[0] at index D. -// -// 9. LoadTypeArgumentsField loads instantiator type arguments from an -// instance SP[0]. -// D = index of TypeArgumentsField constant pool entry corresponding -// to an instance's class. -// -// 10. InstanceCall1 and InstanceCall2 instructions are superseded by -// InstanceCall which works for any number of checked arguments. -// -// 11. EntryFixed instruction works like Entry. In addition, it checks number -// of fixed arguments. -// -// 12. JumpIfNotZeroTypeArgs instruction jumps if number of passed -// function type arguments is not zero. -// -// 13. PushNull, PushTrue, PushFalse, PushInt instructions added. -// -// 14. AssertAssignable is modified to expect arguments in same order as runtime -// call: instance, type, instantiator type args, function type args, name. -// -// 15. JumpIfEqStrict, JumpIfNeStrict, JumpIfTrue, JumpIfFalse, -// JumpIfNull, JumpIfNotNull instructions added. -// +library vm.bytecode.dbc; enum Opcode { kTrap, - kNop, - kCompile, - kHotCheck, - kIntrinsic, + + // Prologue and stack management. + kEntry, + kEntryFixed, + kEntryOptional, + kLoadConstant, + kFrame, + kCheckFunctionTypeArgs, + kCheckStack, + + // Object allocation. + kAllocate, + kAllocateT, + kCreateArrayTOS, + + // Context allocation and access. + kAllocateContext, + kCloneContext, + kLoadContextParent, + kStoreContextParent, + kLoadContextVar, + kStoreContextVar, + + // Constants. + kPushConstant, + kPushNull, + kPushTrue, + kPushFalse, + kPushInt, + + // Locals and expression stack. kDrop1, - kDropR, - kDrop, + kPush, + kPopLocal, + kStoreLocal, + + // Instance fields and arrays. + kLoadFieldTOS, + kStoreFieldTOS, + kStoreIndexedTOS, + + // Static fields. + kPushStatic, + kStoreStaticTOS, + + // Jumps. kJump, kJumpIfNoAsserts, kJumpIfNotZeroTypeArgs, @@ -70,203 +63,28 @@ enum Opcode { kJumpIfFalse, kJumpIfNull, kJumpIfNotNull, - kReturn, - kReturnTOS, - kMove, - kSwap, - kPush, - kLoadConstant, - kLoadClassId, - kLoadClassIdTOS, - kPushConstant, - kPushNull, - kPushTrue, - kPushFalse, - kPushInt, - kStoreLocal, - kPopLocal, + + // Calls. kIndirectStaticCall, - kStaticCall, kInstanceCall, - kInstanceCall1Opt, - kInstanceCall2Opt, - kPushPolymorphicInstanceCall, - kPushPolymorphicInstanceCallByRange, kNativeCall, - kOneByteStringFromCharCode, - kStringToCharCode, - kAddTOS, - kSubTOS, - kMulTOS, - kBitOrTOS, - kBitAndTOS, - kEqualTOS, - kLessThanTOS, - kGreaterThanTOS, - kSmiAddTOS, - kSmiSubTOS, - kSmiMulTOS, - kSmiBitAndTOS, - kAdd, - kSub, - kMul, - kDiv, - kMod, - kShl, - kShr, - kShlImm, - kNeg, - kBitOr, - kBitAnd, - kBitXor, - kBitNot, - kMin, - kMax, - kWriteIntoDouble, - kUnboxDouble, - kCheckedUnboxDouble, - kUnboxInt32, - kBoxInt32, - kBoxUint32, - kSmiToDouble, - kDoubleToSmi, - kDAdd, - kDSub, - kDMul, - kDDiv, - kDNeg, - kDSqrt, - kDMin, - kDMax, - kDCos, - kDSin, - kDPow, - kDMod, - kDTruncate, - kDFloor, - kDCeil, - kDoubleToFloat, - kFloatToDouble, - kDoubleIsNaN, - kDoubleIsInfinite, - kStoreStaticTOS, - kPushStatic, - kInitStaticTOS, - kIfNeStrictTOS, - kIfEqStrictTOS, - kIfNeStrictNumTOS, - kIfEqStrictNumTOS, - kIfSmiLtTOS, - kIfSmiLeTOS, - kIfSmiGeTOS, - kIfSmiGtTOS, - kIfNeStrict, - kIfEqStrict, - kIfLe, - kIfLt, - kIfGe, - kIfGt, - kIfULe, - kIfULt, - kIfUGe, - kIfUGt, - kIfDNe, - kIfDEq, - kIfDLe, - kIfDLt, - kIfDGe, - kIfDGt, - kIfNeStrictNum, - kIfEqStrictNum, - kIfEqNull, - kIfNeNull, - kCreateArrayTOS, - kCreateArrayOpt, - kAllocate, - kAllocateT, - kAllocateOpt, - kAllocateTOpt, - kStoreIndexedTOS, - kStoreIndexed, - kStoreIndexedUint8, - kStoreIndexedExternalUint8, - kStoreIndexedOneByteString, - kStoreIndexedUint32, - kStoreIndexedFloat32, - kStoreIndexed4Float32, - kStoreIndexedFloat64, - kStoreIndexed8Float64, - kNoSuchMethod, - kTailCall, - kTailCallOpt, - kLoadArgDescriptor, - kLoadArgDescriptorOpt, - kLoadFpRelativeSlot, - kLoadFpRelativeSlotOpt, - kStoreFpRelativeSlot, - kStoreFpRelativeSlotOpt, - kLoadIndexedTOS, - kLoadIndexed, - kLoadIndexedUint8, - kLoadIndexedInt8, - kLoadIndexedInt32, - kLoadIndexedUint32, - kLoadIndexedExternalUint8, - kLoadIndexedExternalInt8, - kLoadIndexedFloat32, - kLoadIndexed4Float32, - kLoadIndexedFloat64, - kLoadIndexed8Float64, - kLoadIndexedOneByteString, - kLoadIndexedTwoByteString, - kStoreField, - kStoreFieldExt, - kStoreFieldTOS, - kStoreContextParent, - kStoreContextVar, - kLoadField, - kLoadFieldExt, - kLoadUntagged, - kLoadFieldTOS, + kReturnTOS, + + // Types and type checks. + kAssertAssignable, + kAssertBoolean, + kAssertSubtype, kLoadTypeArgumentsField, - kLoadContextParent, - kLoadContextVar, - kBooleanNegateTOS, - kBooleanNegate, - kThrow, - kEntry, - kEntryFixed, - kEntryOptional, - kEntryOptimized, - kFrame, - kSetFrame, - kAllocateContext, - kAllocateUninitializedContext, - kCloneContext, - kMoveSpecial, kInstantiateType, kInstantiateTypeArgumentsTOS, - kInstanceOf, - kBadTypeError, - kAssertAssignable, - kAssertSubtype, - kAssertBoolean, - kTestSmi, - kTestCids, - kCheckSmi, - kCheckEitherNonSmi, - kCheckClassId, - kCheckClassIdRange, - kCheckBitTest, - kCheckCids, - kCheckCidsByRange, - kCheckStack, - kCheckStackAlwaysExit, - kCheckFunctionTypeArgs, - kDebugStep, - kDebugBreak, - kDeopt, - kDeoptRewind, + + // Exception handling. + kThrow, + kMoveSpecial, + kSetFrame, + + // Bool operations. + kBooleanNegateTOS, } enum Encoding { @@ -300,20 +118,66 @@ class Format { const Map BytecodeFormats = const { Opcode.kTrap: const Format( Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kNop: const Format( - Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kCompile: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kHotCheck: const Format( + Opcode.kEntry: const Format( + Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kEntryFixed: const Format( Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), - Opcode.kIntrinsic: const Format( - Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kEntryOptional: const Format( + Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]), + Opcode.kLoadConstant: const Format( + Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]), + Opcode.kFrame: const Format( + Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kCheckFunctionTypeArgs: const Format( + Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), + Opcode.kCheckStack: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kAllocate: const Format( + Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), + Opcode.kAllocateT: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kCreateArrayTOS: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kAllocateContext: const Format( + Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kCloneContext: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kLoadContextParent: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kStoreContextParent: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kLoadContextVar: const Format( + Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kStoreContextVar: const Format( + Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kPushConstant: const Format( + Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), + Opcode.kPushNull: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kPushTrue: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kPushFalse: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kPushInt: const Format( + Encoding.kX, const [Operand.imm, Operand.none, Operand.none]), Opcode.kDrop1: const Format( Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kDropR: const Format( - Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kDrop: const Format( - Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kPush: const Format( + Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]), + Opcode.kPopLocal: const Format( + Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]), + Opcode.kStoreLocal: const Format( + Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]), + Opcode.kLoadFieldTOS: const Format( + Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), + Opcode.kStoreFieldTOS: const Format( + Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), + Opcode.kStoreIndexedTOS: const Format( + Encoding.k0, const [Operand.none, Operand.none, Operand.none]), + Opcode.kPushStatic: const Format( + Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), + Opcode.kStoreStaticTOS: const Format( + Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), Opcode.kJump: const Format( Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]), Opcode.kJumpIfNoAsserts: const Format( @@ -332,399 +196,33 @@ const Map BytecodeFormats = const { Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]), Opcode.kJumpIfNotNull: const Format( Encoding.kT, const [Operand.tgt, Operand.none, Operand.none]), - Opcode.kReturn: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kReturnTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kMove: const Format( - Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]), - Opcode.kSwap: const Format( - Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]), - Opcode.kPush: const Format( - Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]), - Opcode.kLoadConstant: const Format( - Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]), - Opcode.kLoadClassId: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kLoadClassIdTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kPushConstant: const Format( - Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kPushNull: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kPushTrue: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kPushFalse: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kPushInt: const Format( - Encoding.kX, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kStoreLocal: const Format( - Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]), - Opcode.kPopLocal: const Format( - Encoding.kX, const [Operand.xeg, Operand.none, Operand.none]), Opcode.kIndirectStaticCall: const Format( Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kStaticCall: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), Opcode.kInstanceCall: const Format( Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kInstanceCall1Opt: const Format( - Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kInstanceCall2Opt: const Format( - Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kPushPolymorphicInstanceCall: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), - Opcode.kPushPolymorphicInstanceCallByRange: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), Opcode.kNativeCall: const Format( Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kOneByteStringFromCharCode: const Format( - Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]), - Opcode.kStringToCharCode: const Format( - Encoding.kAX, const [Operand.reg, Operand.xeg, Operand.none]), - Opcode.kAddTOS: const Format( + Opcode.kReturnTOS: const Format( Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kSubTOS: const Format( + Opcode.kAssertAssignable: const Format( + Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), + Opcode.kAssertBoolean: const Format( + Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), + Opcode.kAssertSubtype: const Format( Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kMulTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kBitOrTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kBitAndTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kEqualTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kLessThanTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kGreaterThanTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kSmiAddTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kSmiSubTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kSmiMulTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kSmiBitAndTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kAdd: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kSub: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kMul: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDiv: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kMod: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kShl: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kShr: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kShlImm: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]), - Opcode.kNeg: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kBitOr: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kBitAnd: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kBitXor: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kBitNot: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kMin: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kMax: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kWriteIntoDouble: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kUnboxDouble: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kCheckedUnboxDouble: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kUnboxInt32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]), - Opcode.kBoxInt32: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kBoxUint32: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kSmiToDouble: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDoubleToSmi: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDAdd: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDSub: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDMul: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDDiv: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDNeg: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDSqrt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDMin: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDMax: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDCos: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDSin: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDPow: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDMod: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kDTruncate: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDFloor: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDCeil: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDoubleToFloat: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kFloatToDouble: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kDoubleIsNaN: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kDoubleIsInfinite: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kStoreStaticTOS: const Format( - Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kPushStatic: const Format( - Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kInitStaticTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfNeStrictTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfEqStrictTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfNeStrictNumTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfEqStrictNumTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfSmiLtTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfSmiLeTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfSmiGeTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfSmiGtTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kIfNeStrict: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfEqStrict: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfLe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfLt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfGe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfGt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfULe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfULt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfUGe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfUGt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfDNe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfDEq: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfDLe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfDLt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfDGe: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfDGt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfNeStrictNum: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfEqStrictNum: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kIfEqNull: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kIfNeNull: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kCreateArrayTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kCreateArrayOpt: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kAllocate: const Format( - Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kAllocateT: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kAllocateOpt: const Format( - Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]), - Opcode.kAllocateTOpt: const Format( - Encoding.kAD, const [Operand.reg, Operand.lit, Operand.none]), - Opcode.kStoreIndexedTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kStoreIndexed: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexedUint8: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexedExternalUint8: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexedOneByteString: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexedUint32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexedFloat32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexed4Float32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexedFloat64: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreIndexed8Float64: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kNoSuchMethod: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kTailCall: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kTailCallOpt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kLoadArgDescriptor: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kLoadArgDescriptorOpt: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kLoadFpRelativeSlot: const Format( - Encoding.kX, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kLoadFpRelativeSlotOpt: const Format( - Encoding.kABY, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreFpRelativeSlot: const Format( - Encoding.kX, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kStoreFpRelativeSlotOpt: const Format( - Encoding.kABY, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kLoadIndexed: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedUint8: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedInt8: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedInt32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedUint32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedExternalUint8: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedExternalInt8: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedFloat32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexed4Float32: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedFloat64: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexed8Float64: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedOneByteString: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kLoadIndexedTwoByteString: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.reg]), - Opcode.kStoreField: const Format( - Encoding.kABC, const [Operand.reg, Operand.imm, Operand.reg]), - Opcode.kStoreFieldExt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kStoreFieldTOS: const Format( - Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kStoreContextParent: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kStoreContextVar: const Format( - Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kLoadField: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]), - Opcode.kLoadFieldExt: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kLoadUntagged: const Format( - Encoding.kABC, const [Operand.reg, Operand.reg, Operand.imm]), - Opcode.kLoadFieldTOS: const Format( - Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), Opcode.kLoadTypeArgumentsField: const Format( Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), - Opcode.kLoadContextParent: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kLoadContextVar: const Format( - Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kBooleanNegateTOS: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kBooleanNegate: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kThrow: const Format( - Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kEntry: const Format( - Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kEntryFixed: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), - Opcode.kEntryOptional: const Format( - Encoding.kABC, const [Operand.imm, Operand.imm, Operand.imm]), - Opcode.kEntryOptimized: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), - Opcode.kFrame: const Format( - Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kSetFrame: const Format( - Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kAllocateContext: const Format( - Encoding.kD, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kAllocateUninitializedContext: const Format( - Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]), - Opcode.kCloneContext: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kMoveSpecial: const Format( - Encoding.kAD, const [Operand.reg, Operand.spe, Operand.none]), Opcode.kInstantiateType: const Format( Encoding.kD, const [Operand.lit, Operand.none, Operand.none]), Opcode.kInstantiateTypeArgumentsTOS: const Format( Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kInstanceOf: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kBadTypeError: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kAssertAssignable: const Format( - Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]), - Opcode.kAssertSubtype: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kAssertBoolean: const Format( + Opcode.kThrow: const Format( Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kTestSmi: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kTestCids: const Format( - Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]), - Opcode.kCheckSmi: const Format( - Encoding.kA, const [Operand.reg, Operand.none, Operand.none]), - Opcode.kCheckEitherNonSmi: const Format( - Encoding.kAD, const [Operand.reg, Operand.reg, Operand.none]), - Opcode.kCheckClassId: const Format( - Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]), - Opcode.kCheckClassIdRange: const Format( - Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]), - Opcode.kCheckBitTest: const Format( - Encoding.kAD, const [Operand.reg, Operand.imm, Operand.none]), - Opcode.kCheckCids: const Format( - Encoding.kABC, const [Operand.reg, Operand.imm, Operand.imm]), - Opcode.kCheckCidsByRange: const Format( - Encoding.kABC, const [Operand.reg, Operand.imm, Operand.imm]), - Opcode.kCheckStack: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kCheckStackAlwaysExit: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kCheckFunctionTypeArgs: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), - Opcode.kDebugStep: const Format( - Encoding.k0, const [Operand.none, Operand.none, Operand.none]), - Opcode.kDebugBreak: const Format( + Opcode.kMoveSpecial: const Format( + Encoding.kAD, const [Operand.reg, Operand.spe, Operand.none]), + Opcode.kSetFrame: const Format( Encoding.kA, const [Operand.imm, Operand.none, Operand.none]), - Opcode.kDeopt: const Format( - Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]), - Opcode.kDeoptRewind: const Format( + Opcode.kBooleanNegateTOS: const Format( Encoding.k0, const [Operand.none, Operand.none, Operand.none]), }; diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc index a1da9ee6f9c..a51753bba96 100644 --- a/runtime/vm/compiler/assembler/disassembler_kbc.cc +++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc @@ -128,18 +128,21 @@ static void FormatA_D(char* buf, Apply(&buf, &size, pc, op2, bc, ""); } -static void FormatA_X(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op & 0xFF00) >> 8; - const int32_t bc = static_cast(op) >> 16; - Apply(&buf, &size, pc, op1, a, ", "); - Apply(&buf, &size, pc, op2, bc, ""); -} +// TODO(alexmarkov) This format is currently unused. Restore it if needed, or +// remove it once bytecode instruction set is finalized. +// +// static void FormatA_X(char* buf, +// intptr_t size, +// uword pc, +// uint32_t op, +// Fmt op1, +// Fmt op2, +// Fmt op3) { +// const int32_t a = (op & 0xFF00) >> 8; +// const int32_t bc = static_cast(op) >> 16; +// Apply(&buf, &size, pc, op1, a, ", "); +// Apply(&buf, &size, pc, op2, bc, ""); +// } static void FormatX(char* buf, intptr_t size, @@ -178,20 +181,23 @@ static void FormatA_B_C(char* buf, Apply(&buf, &size, pc, op3, c, ""); } -static void FormatA_B_Y(char* buf, - intptr_t size, - uword pc, - uint32_t op, - Fmt op1, - Fmt op2, - Fmt op3) { - const int32_t a = (op >> 8) & 0xFF; - const int32_t b = (op >> 16) & 0xFF; - const int32_t y = static_cast((op >> 24) & 0xFF); - Apply(&buf, &size, pc, op1, a, ", "); - Apply(&buf, &size, pc, op2, b, ", "); - Apply(&buf, &size, pc, op3, y, ""); -} +// TODO(alexmarkov) This format is currently unused. Restore it if needed, or +// remove it once bytecode instruction set is finalized. +// +// static void FormatA_B_Y(char* buf, +// intptr_t size, +// uword pc, +// uint32_t op, +// Fmt op1, +// Fmt op2, +// Fmt op3) { +// const int32_t a = (op >> 8) & 0xFF; +// const int32_t b = (op >> 16) & 0xFF; +// const int32_t y = static_cast((op >> 24) & 0xFF); +// Apply(&buf, &size, pc, op1, a, ", "); +// Apply(&buf, &size, pc, op2, b, ", "); +// Apply(&buf, &size, pc, op3, y, ""); +// } #define BYTECODE_FORMATTER(name, encoding, op1, op2, op3) \ static void Format##name(char* buf, intptr_t size, uword pc, uint32_t op) { \ @@ -210,11 +216,8 @@ static bool HasLoadFromPool(KBCInstr instr) { switch (KernelBytecode::DecodeOpcode(instr)) { case KernelBytecode::kLoadConstant: case KernelBytecode::kPushConstant: - case KernelBytecode::kStaticCall: case KernelBytecode::kIndirectStaticCall: case KernelBytecode::kInstanceCall: - case KernelBytecode::kInstanceCall1Opt: - case KernelBytecode::kInstanceCall2Opt: case KernelBytecode::kStoreStaticTOS: case KernelBytecode::kPushStatic: case KernelBytecode::kAllocate: diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h index c898f472c37..d3d5d985404 100644 --- a/runtime/vm/constants_kbc.h +++ b/runtime/vm/constants_kbc.h @@ -87,509 +87,6 @@ namespace dart { // // Unreachable instruction. // -// - Nop D -// -// This instruction does nothing. It may refer to an object in the constant -// pool that may be decoded by other instructions. -// -// - 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. -// -// - JumpIfNoAsserts target -// -// Jump to the given target if assertions are not enabled. -// Target is specified as offset from the PC of the jump instruction. -// -// - JumpIfNotZeroTypeArgs target -// -// Jump to the given target if number of passed function type -// arguments is not zero. -// Target is specified as offset from the PC of the jump instruction. -// -// - JumpIfEqStrict target; JumpIfNeStrict target -// -// Jump to the given target if SP[-1] is the same (JumpIfEqStrict) / -// not the same (JumpIfNeStrict) object as SP[0]. -// -// - JumpIfTrue target; JumpIfFalse target -// - JumpIfNull target; JumpIfNotNull target -// -// Jump to the given target if SP[0] is true/false/null/not null. -// -// - 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 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. -// -// - LoadConstant rA, D; PushConstant D -// -// Load value at index D from constant pool into FP[rA] or push it onto the -// stack. -// -// - PushNull -// -// Push `null` onto the stack. -// -// - PushTrue -// -// Push `true` onto the stack. -// -// - PushFalse -// -// Push `false` onto the stack. -// -// - PushInt rX -// -// Push int rX 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], which indicates whether the first argument -// is a type argument vector. -// -// - IndirectStaticCall ArgC, D -// -// Invoke the function given by the ICData in SP[0] with arguments -// SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which -// indicates whether the first argument is a type argument vector. -// -// - InstanceCall ArgC, D -// -// Lookup and invoke method using ICData in PP[D] -// with arguments SP[-(1+ArgC)], ..., SP[-1]. -// The ICData indicates whether the first argument is a type argument vector. -// -// - InstanceCallOpt ArgC, D -// -// Lookup and invoke method with N checked arguments using ICData in PP[D] -// with arguments SP[-(1+ArgC)], ..., SP[-1]. -// The ICData indicates whether the first argument is a type argument vector. -// -// - NativeCall D -// -// Invoke native function described by array at pool[D]. -// array[0] is wrapper, array[1] is function, array[2] is argc_tag. -// -// - PushPolymorphicInstanceCall ArgC, D -// -// Skips 2*D + 1 instructions and pushes a function object onto the stack -// if one can be found as follows. Otherwise skips only 2*D instructions. -// The function is looked up in the IC data encoded in the following 2*D -// Nop instructions. The Nop instructions should be arranged in pairs with -// the first being the cid, and the second being the function to push if -// the cid matches the cid in the pair. -// -// - PushPolymorphicInstanceCallByRange ArgC, D -// -// Skips 3*D + 1 instructions and pushes a function object onto the stack -// if one can be found as follows. Otherwise skips only 3*D instructions. -// The function is looked up in the IC data encoded in the following 3*D -// Nop instructions. The Nop instructions should be arranged in triples with -// the first being the start cid, the second being the number of cids, and -// the third being the function to push if the cid is in the range given -// by the first two Nop instructions. -// -// - OneByteStringFromCharCode rA, rX -// -// Load the one-character symbol with the char code given by the Smi -// in FP[rX] into FP[rA]. -// -// - StringToCharCode rA, rX -// -// Load and smi-encode the single char code of the string in FP[rX] into -// FP[rA]. If the string's length is not 1, load smi -1 instead. -// -// - 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] 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). -// -// - Add, Sub, Mul, Div, Mod, Shl, Shr rA, rB, rC -// -// Arithmetic operations on Smis. FP[rA] <- FP[rB] op FP[rC]. -// If these instructions can trigger a deoptimization, the following -// instruction should be Deopt. If no deoptimization should be triggered, -// the immediately following instruction is skipped. These instructions -// expect their operands to be Smis, but don't check that they are. -// -// - SmiTOS -// -// Performs SP[0] SP[-1], pops operands and pushes result on the stack. -// Assumes SP[0] and SP[-1] are both smis and the result is a Smi. -// -// - ShlImm rA, rB, rC -// -// FP[rA] <- FP[rB] << rC. Shifts the Smi in FP[rB] left by rC. rC is -// assumed to be a legal positive number by which left-shifting is possible. -// -// - Min, Max rA, rB, rC -// -// FP[rA] <- {min, max}(FP[rB], FP[rC]). Assumes that FP[rB], and FP[rC] are -// Smis. -// -// - Neg rA , rD -// -// FP[rA] <- -FP[rD]. Assumes FP[rD] is a Smi. If there is no overflow the -// immediately following instruction is skipped. -// -// - DMin, DMax, DAdd, DSub, DMul, DDiv, DPow, DMod rA, rB, rC -// -// Arithmetic operations on unboxed doubles. FP[rA] <- FP[rB] op FP[rC]. -// -// - DNeg, DCos, DSin, DSqrt rA, rD -// -// FP[rA] <- op(FP[rD]). Assumes FP[rD] is an unboxed double. -// -// - DTruncate, DFloor, DCeil rA, rD -// -// Applies trunc(), floor(), or ceil() to the unboxed double in FP[rD], and -// stores the result in FP[rA]. -// -// - DoubleToFloat, FloatToDouble rA, rD -// -// Convert the unboxed float or double in FP[rD] as indicated, and store the -// result in FP[rA]. -// -// - DoubleIsNaN rA, rD -// -// If the unboxed double in FP[rD] is a NaN, then writes Bool::True().raw() -// into FP[rA], and Bool::False().raw() otherwise. -// -// - DoubleIsInfinite rA, rD -// -// If the unboxed double in FP[rD] is + or - infinity, then -// writes Bool::True().raw() into FP[rA], and Bool::False().raw() otherwise. -// -// - BitOr, BitAnd, BitXor rA, rB, rC -// -// FP[rA] <- FP[rB] op FP[rC]. These instructions expect their operands to be -// Smis, but don't check that they are. -// -// - BitNot rA, rD -// -// FP[rA] <- ~FP[rD]. As above, assumes FP[rD] is a Smi. -// -// - WriteIntoDouble rA, rD -// -// Box the double in FP[rD] using the box in FP[rA]. -// -// - UnboxDouble rA, rD -// -// Unbox the double in FP[rD] into FP[rA]. Assumes FP[rD] is a double. -// -// - CheckedUnboxDouble rA, rD -// -// Unboxes FP[rD] into FP[rA] and skips the following instruction unless -// FP[rD] is not a double or a Smi. When FP[rD] is a Smi, converts it to a -// double. -// -// - UnboxInt32 rA, rB, C -// -// Unboxes the integer in FP[rB] into FP[rA]. If C == 1, the value may be -// truncated. If FP[rA] is successfully unboxed the following instruction is -// skipped. -// -// - BoxInt32 rA, rD -// -// Boxes the unboxed signed 32-bit integer in FP[rD] into FP[rA]. -// -// - BoxUint32 rA, rD -// -// Boxes the unboxed unsigned 32-bit integer in FP[rD] into FP[rA]. -// -// - SmiToDouble rA, rD -// -// Convert the Smi in FP[rD] to an unboxed double in FP[rA]. -// -// - DoubleToSmi rA, rD -// -// If the unboxed double in FP[rD] can be converted to a Smi in FP[rA], then -// this instruction does so, and skips the following instruction. Otherwise, -// the following instruction is not skipped. -// -// - 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. -// -// - If(Num)TOS -// If(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 -// RawObject pointers. -// -// Used to implement conditional jump: -// -// IfNeStrictTOS -// Jump T ;; jump if not equal -// -// - IfNull rA -// -// Cond is Eq or Ne. Skips the next instruction unless the given condition -// holds. -// -// - If rA, rD -// -// Cond is Le, Lt, Ge, Gt, unsigned variants ULe, ULt, UGe, UGt, and -// unboxed double variants DEq, DNe, DLe, DLt, DGe, DGt. -// Skips the next instruction unless FP[rA] FP[rD]. Assumes that -// FP[rA] and FP[rD] are Smis or unboxed doubles as indicated by . -// -// - IfSmiTOS -// -// Cond is Lt, Le, Ge, Gt. -// Skips the next instruction unless SP[-1] SP[-0]. -// It is expected both SP[-1] and SP[-0] are Smis. -// -// - CreateArrayTOS -// -// Allocate array of length SP[0] with type arguments SP[-1]. -// -// - CreateArrayOpt rA, rB, rC -// -// Try to allocate a new array where FP[rB] is the length, and FP[rC] is the -// type. If allocation is successful, the result is stored in FP[rA], and -// the next four instructions, which should be the -// (Push type; Push length; AllocateTOS; PopLocal) slow path are skipped. -// -// - Allocate D -// -// Allocate object of class PP[D] with no type arguments. -// -// - AllocateOpt rA, D -// -// Try allocating an object with tags in PP[D] with no type arguments. -// If allocation is successful, the result is stored in FP[rA], and -// the next two instructions, which should be the (Allocate class; PopLocal) -// slow path are skipped -// -// - AllocateT -// -// Allocate object of class SP[0] with type arguments SP[-1]. -// -// - AllocateTOpt rA, D -// -// Similar to AllocateOpt with the difference that the offset of the -// type arguments in the resulting object is taken from the D field of the -// following Nop instruction, and on success 4 instructions are skipped and -// the object at the top of the stack is popped. -// -// - 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. -// -// - StoreIndexed rA, rB, rC -// -// Store FP[rC] into array FP[rA] at index FP[rB]. No typechecking is done. -// FP[rA] is assumed to be a RawArray, FP[rB] to be a smi. -// -// - StoreIndexed{N}{Type} rA, rB, rC -// -// Where Type is Float32, Float64, Uint8, or OneByteString -// Where N is '', '4', or '8'. N may only be '4' for Float32 and '8' for -// Float64. -// -// Store the unboxed double or tagged Smi in FP[rC] into the typed data array -// at FP[rA] at index FP[rB]. If N is not '', the index is assumed to be -// already scaled by N. -// -// - StoreIndexedExternalUint8 rA, rB, rC -// -// Similar to StoreIndexedUint8 but FP[rA] is an external typed data aray. -// -// - NoSuchMethod -// -// Performs noSuchmethod handling code. -// -// - TailCall -// -// Unwinds the current frame, populates the arguments descriptor register -// with SP[-1] and tail calls the code in SP[-0]. -// -// - TailCallOpt rA, rD -// -// Unwinds the current frame, populates the arguments descriptor register -// with rA and tail calls the code in rD. -// -// - LoadArgDescriptor -// -// Load the caller-provoided argument descriptor and pushes it onto the -// stack. -// -// - LoadArgDescriptorOpt rA -// -// Load the caller-provoided argument descriptor into [rA]. -// -// - LoadFpRelativeSlot rD -// -// Loads from FP using the negative index of SP[-0]+rD. -// It is assumed that SP[-0] is a Smi. -// -// - LoadFpRelativeSlotOpt rA, rB, rY -// -// Loads from FP using the negative index of FP[rB]+rY and stores the result -// into rA. -// It is assumed that rY is a Smi. -// -// - StoreFpRelativeSlot rD -// -// Stores SP[-0] by indexing into FP using the negative index of SP[-1]+rD. -// It is assumed that SP[-1] is a Smi. -// -// - StoreFpRelativeSlotOpt rA, rB, rY -// -// Stores rA by indexing into FP using the the negative index of FP[rB]+rY. -// It is assumed that rY is a Smi. -// -// - LoadIndexedTOS -// -// Loads from array SP[-1] at index SP[-0]. -// It is assumed that SP[-0] is a Smi. -// -// - LoadIndexed rA, rB, rC -// -// Loads from array FP[rB] at index FP[rC] into FP[rA]. No typechecking is -// done. FP[rB] is assumed to be a RawArray, and to contain a Smi at FP[rC]. -// -// - LoadIndexed{N}{Type} rA, rB, rC -// -// Where Type is Float32, Float64, OneByteString, TwoByteString, Uint8, -// Int8, and N is '', '4', or '8'. N may only be '4' for Float32, and may -// only be '8' for Float64. -// -// Loads from typed data array FP[rB] at index FP[rC] into an unboxed double, -// or tagged Smi in FP[rA] as indicated by the type in the name. If N is not -// '', the index is assumed to be already scaled by N. -// -// - LoadIndexedExternal{Int8, Uint8} rA, rB, rC -// -// Loads from the external typed data array FP[rB] at index FP[rC] into -// FP[rA]. No typechecking is done. -// -// - StoreField rA, B, rC -// -// Store value FP[rC] into object FP[rA] at offset (in words) B. -// -// - StoreFieldExt rA, rD -// -// Store value FP[rD] into object FP[rA] at offset (in words) -// stored in the following Nop instruction. Used to access fields with -// large offsets. -// -// - StoreFieldTOS D -// -// Store value SP[0] into object SP[-1] at offset (in words) PP[D]. -// -// - StoreContextParent -// -// Store context SP[0] into `parent` field of context SP[-1]. -// -// - StoreContextVar D -// -// Store value SP[0] into context SP[-1] at index D. -// -// - LoadField rA, rB, C -// -// Load value at offset (in words) C from object FP[rB] into FP[rA]. -// -// - LoadFieldExt rA, rD -// -// Load value from object FP[rD] at offset (in words) stored in the -// following Nop instruction into FP[rA]. Used to access fields with -// large offsets. -// -// - LoadUntagged rA, rB, C -// -// Like LoadField, but assumes that FP[rB] is untagged. -// -// - LoadFieldTOS D -// -// Push value at offset (in words) PP[D] from object SP[0]. -// -// - LoadTypeArgumentsField D -// -// Load instantiator type arguments from an instance SP[0]. -// PP[D] = offset (in words) of type arguments field corresponding -// to an instance's class. -// -// - LoadContextParent -// -// Load parent from context SP[0]. -// -// - LoadContextVar D -// -// Load value from context SP[0] at index D. -// -// - BooleanNegateTOS -// -// SP[0] = !SP[0] -// -// - BooleanNegate rA, rD -// -// FP[rA] = !FP[rD] -// -// - Throw A -// -// Throw (Rethrow if A != 0) exception. Exception object and stack object -// are taken from TOS. -// // - Entry rD // // Function prologue for the function @@ -626,64 +123,164 @@ namespace dart { // local variables this is done by a separate bytecode Frame, which should // follow EntryOptional and its LoadConstant instructions. // -// - EntryOptimized rD +// - LoadConstant rA, D // -// Function prologue for optimized functions. -// rD - 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. +// Used in conjunction with EntryOptional instruction to describe names and +// default values of optional parameters. // // - Frame D // // Reserve and initialize with null space for D local variables. // -// - SetFrame A +// - CheckFunctionTypeArgs A, D // -// Reinitialize SP assuming that current frame has size A. -// Used to drop temporaries from the stack in the exception handler. +// Check for a passed-in type argument vector of length A and +// store it at FP[D]. +// +// - CheckStack +// +// Compare SP against isolate stack limit and call StackOverflow handler if +// necessary. +// +// - Allocate D +// +// Allocate object of class PP[D] with no type arguments. +// +// - AllocateT +// +// Allocate object of class SP[0] with type arguments SP[-1]. +// +// - CreateArrayTOS +// +// Allocate array of length SP[0] with type arguments SP[-1]. // // - AllocateContext D // // Allocate Context object assuming for D context variables. // -// - AllocateUninitializedContext rA, D -// -// Allocates an uninitialized context for D variables, and places the result -// in FP[rA]. On success, skips the next 2 instructions, which should be the -// slow path (AllocateContext D; PopLocal rA). -// // - CloneContext // // Clone context stored in TOS. // -// - MoveSpecial rA, D +// - LoadContextParent // -// 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. +// Load parent from context SP[0]. // -// - InstantiateType D +// - StoreContextParent // -// Instantiate type PP[D] with instantiator type arguments SP[-1] and -// function type arguments SP[0]. +// Store context SP[0] into `parent` field of context SP[-1]. // -// - InstantiateTypeArgumentsTOS D +// - LoadContextVar D // -// Instantiate type arguments PP[D] with instantiator type arguments SP[-1] -// and function type arguments SP[0]. +// Load value from context SP[0] at index D. // -// - InstanceOf +// - StoreContextVar D // -// Test if instance SP[-4] with instantiator type arguments SP[-3] and -// function type arguments SP[-2] is a subtype of type SP[-1] using -// SubtypeTestCache SP[0], with result placed at top of stack. +// Store value SP[0] into context SP[-1] at index D. +// +// - PushConstant D +// +// Push value at index D from constant pool onto the stack. +// +// - PushNull +// +// Push `null` onto the stack. +// +// - PushTrue +// +// Push `true` onto the stack. +// +// - PushFalse +// +// Push `false` onto the stack. +// +// - PushInt rX +// +// Push int rX onto the stack. +// +// - Drop1 +// +// Drop 1 value from the stack +// +// - Push rX +// +// Push FP[rX] to the stack. +// +// - StoreLocal rX; PopLocal rX +// +// Store top of the stack into FP[rX] and pop it if needed. +// +// - LoadFieldTOS D +// +// Push value at offset (in words) PP[D] from object SP[0]. +// +// - StoreFieldTOS D +// +// Store value SP[0] into object SP[-1] at offset (in words) PP[D]. +// +// - 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. +// +// - PushStatic +// +// Pushes value of the static field PP[D] on to the stack. +// +// - StoreStaticTOS D +// +// Stores TOS into the static field PP[D]. +// +// - Jump target +// +// Jump to the given target. Target is specified as offset from the PC of the +// jump instruction. +// +// - JumpIfNoAsserts target +// +// Jump to the given target if assertions are not enabled. +// Target is specified as offset from the PC of the jump instruction. +// +// - JumpIfNotZeroTypeArgs target +// +// Jump to the given target if number of passed function type +// arguments is not zero. +// Target is specified as offset from the PC of the jump instruction. +// +// - JumpIfEqStrict target; JumpIfNeStrict target +// +// Jump to the given target if SP[-1] is the same (JumpIfEqStrict) / +// not the same (JumpIfNeStrict) object as SP[0]. +// +// - JumpIfTrue target; JumpIfFalse target +// - JumpIfNull target; JumpIfNotNull target +// +// Jump to the given target if SP[0] is true/false/null/not null. +// +// - IndirectStaticCall ArgC, D +// +// Invoke the function given by the ICData in SP[0] with arguments +// SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which +// indicates whether the first argument is a type argument vector. +// +// - InstanceCall ArgC, D +// +// Lookup and invoke method using ICData in PP[D] +// with arguments SP[-(1+ArgC)], ..., SP[-1]. +// The ICData indicates whether the first argument is a type argument vector. +// +// - NativeCall D +// +// Invoke native function described by array at pool[D]. +// array[0] is wrapper, array[1] is function, array[2] is argc_tag. +// +// - ReturnTOS +// +// Return to the caller using 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. // // - AssertAssignable A, D // @@ -694,6 +291,10 @@ namespace dart { // // Instance remains on stack. Other arguments are consumed. // +// - AssertBoolean A +// +// Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0). +// // - AssertSubtype // // Assert that one type is a subtype of another. Throws a TypeError @@ -707,113 +308,41 @@ namespace dart { // // All 5 arguments are consumed from the stack and no results is pushed. // -// - BadTypeError +// - LoadTypeArgumentsField D // -// If SP[-4] is non-null, throws a BadType error by calling into the runtime. -// Assumes that the stack is arranged the same as for AssertAssignable. +// Load instantiator type arguments from an instance SP[0]. +// PP[D] = offset (in words) of type arguments field corresponding +// to an instance's class. // -// - AssertBoolean A +// - InstantiateType D // -// Assert that TOS is a boolean (A = 1) or that TOS is not null (A = 0). +// Instantiate type PP[D] with instantiator type arguments SP[-1] and +// function type arguments SP[0]. // -// - TestSmi rA, rD +// - InstantiateTypeArgumentsTOS D // -// If FP[rA] & FP[rD] != 0, then skip the next instruction. FP[rA] and FP[rD] -// must be Smis. +// Instantiate type arguments PP[D] with instantiator type arguments SP[-1] +// and function type arguments SP[0]. // -// - TestCids rA, D +// - Throw A // -// The next D instructions must be Nops whose D field encodes a class id. If -// the class id of FP[rA] matches, jump to PC + N + 1 if the matching Nop's -// A != 0 or PC + N + 2 if the matching Nop's A = 0. If no match is found, -// jump to PC + N. +// Throw (Rethrow if A != 0) exception. Exception object and stack object +// are taken from TOS. // -// - CheckSmi rA +// - MoveSpecial rA, D // -// If FP[rA] is a Smi, then skip the next instruction. +// 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. // -// - CheckEitherNonSmi rA, rD +// - SetFrame A // -// If either FP[rA] or FP[rD] is not a Smi, then skip the next instruction. +// Reinitialize SP assuming that current frame has size A. +// Used to drop temporaries from the stack in the exception handler. // -// - CheckClassId rA, D +// - BooleanNegateTOS // -// If the class id in FP[rA] matches the class id D, then skip the -// following instruction. -// -// - CheckClassIdRange rA, D -// -// Next instruction is a Nop with S, the size of the class-id range. -// If the class id in FP[rA] is between the D D + S, then skip the -// following instruction. -// -// - CheckBitTest rA, D -// -// Skips the next 3 instructions if the object at FP[rA] is a valid class for -// a dense switch with low cid encoded in the following Nop instruction, and -// the cid mask encoded in the Nop instruction after that, or if D == 1 and -// FP[rA] is a Smi. Skips 2 instructions otherwise. -// -// - CheckCids rA, rB, rC -// -// Skips rC + 1 instructions if the object at FP[rA] is a Smi and -// rB == 1, or if FP[rA]'s cid is found in the array of cids encoded by the -// following rC Nop instructions. Otherwise skips only rC instructions. -// -// - CheckCidsByRange rA, rB, rC -// -// Skips rC + 1 instructions if the object at FP[rA] is a Smi and rB == -// 1, or if FP[rA]'s cid is found in the array of cid ranges encoded by the -// following rC Nop instructions. The cid ranges from a inclusive to b -// exclusive are coded in pairs of (a, b - a). Otherwise skips only 2 -// instructions. -// -// - CheckStack -// -// Compare SP against isolate stack limit and call StackOverflow handler if -// necessary. -// -// - CheckStackAlwaysExit -// -// Unconditionally call StackOverflow handler. -// -// - CheckFunctionTypeArgs A, D -// -// Check for a passed-in type argument vector of length A and -// store it at FP[D]. -// -// - 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. -// -// - 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]. -// -// - Deopt ArgC, D -// -// If D != 0 then trigger eager deoptimization with deopt id (D - 1). -// If D == 0 then trigger lazy deoptimization. -// -// The meaning of operand ArgC (encoded as A operand) matches that of an -// ArgC operand in call instructions. This is needed because we could -// potentially patch calls instructions with a lazy 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 second call with Deopt +// SP[0] = !SP[0] // // BYTECODE LIST FORMAT // @@ -839,13 +368,36 @@ namespace dart { // #define KERNEL_BYTECODES_LIST(V) \ V(Trap, 0, ___, ___, ___) \ - V(Nop, A_D, num, lit, ___) \ - V(Compile, 0, ___, ___, ___) \ - V(HotCheck, A_D, num, num, ___) \ - V(Intrinsic, A, num, ___, ___) \ + V(Entry, D, num, ___, ___) \ + V(EntryFixed, A_D, num, num, ___) \ + V(EntryOptional, A_B_C, num, num, num) \ + V(LoadConstant, A_D, reg, lit, ___) \ + V(Frame, D, num, ___, ___) \ + V(CheckFunctionTypeArgs, A_D, num, num, ___) \ + V(CheckStack, 0, ___, ___, ___) \ + V(Allocate, D, lit, ___, ___) \ + V(AllocateT, 0, ___, ___, ___) \ + V(CreateArrayTOS, 0, ___, ___, ___) \ + V(AllocateContext, D, num, ___, ___) \ + V(CloneContext, 0, ___, ___, ___) \ + V(LoadContextParent, 0, ___, ___, ___) \ + V(StoreContextParent, 0, ___, ___, ___) \ + V(LoadContextVar, D, num, ___, ___) \ + V(StoreContextVar, D, num, ___, ___) \ + V(PushConstant, D, lit, ___, ___) \ + V(PushNull, 0, ___, ___, ___) \ + V(PushTrue, 0, ___, ___, ___) \ + V(PushFalse, 0, ___, ___, ___) \ + V(PushInt, X, num, ___, ___) \ V(Drop1, 0, ___, ___, ___) \ - V(DropR, A, num, ___, ___) \ - V(Drop, A, num, ___, ___) \ + V(Push, X, xeg, ___, ___) \ + V(PopLocal, X, xeg, ___, ___) \ + V(StoreLocal, X, xeg, ___, ___) \ + V(LoadFieldTOS, D, lit, ___, ___) \ + V(StoreFieldTOS, D, lit, ___, ___) \ + V(StoreIndexedTOS, 0, ___, ___, ___) \ + V(PushStatic, D, lit, ___, ___) \ + V(StoreStaticTOS, D, lit, ___, ___) \ V(Jump, T, tgt, ___, ___) \ V(JumpIfNoAsserts, T, tgt, ___, ___) \ V(JumpIfNotZeroTypeArgs, T, tgt, ___, ___) \ @@ -855,203 +407,20 @@ namespace dart { V(JumpIfFalse, T, tgt, ___, ___) \ V(JumpIfNull, T, tgt, ___, ___) \ V(JumpIfNotNull, T, tgt, ___, ___) \ - 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, ___) \ - V(LoadClassIdTOS, 0, ___, ___, ___) \ - V(PushConstant, D, lit, ___, ___) \ - V(PushNull, 0, ___, ___, ___) \ - V(PushTrue, 0, ___, ___, ___) \ - V(PushFalse, 0, ___, ___, ___) \ - V(PushInt, X, num, ___, ___) \ - V(StoreLocal, X, xeg, ___, ___) \ - V(PopLocal, X, xeg, ___, ___) \ V(IndirectStaticCall, A_D, num, num, ___) \ - V(StaticCall, A_D, num, num, ___) \ V(InstanceCall, A_D, num, num, ___) \ - V(InstanceCall1Opt, A_D, num, num, ___) \ - V(InstanceCall2Opt, A_D, num, num, ___) \ - V(PushPolymorphicInstanceCall, A_D, num, num, ___) \ - V(PushPolymorphicInstanceCallByRange, A_D, num, num, ___) \ V(NativeCall, D, lit, ___, ___) \ - V(OneByteStringFromCharCode, A_X, reg, xeg, ___) \ - V(StringToCharCode, A_X, reg, xeg, ___) \ - 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(SmiAddTOS, 0, ___, ___, ___) \ - V(SmiSubTOS, 0, ___, ___, ___) \ - V(SmiMulTOS, 0, ___, ___, ___) \ - V(SmiBitAndTOS, 0, ___, ___, ___) \ - V(Add, A_B_C, reg, reg, reg) \ - V(Sub, A_B_C, reg, reg, reg) \ - V(Mul, A_B_C, reg, reg, reg) \ - V(Div, A_B_C, reg, reg, reg) \ - V(Mod, A_B_C, reg, reg, reg) \ - V(Shl, A_B_C, reg, reg, reg) \ - V(Shr, A_B_C, reg, reg, reg) \ - V(ShlImm, A_B_C, reg, reg, num) \ - V(Neg, A_D, reg, reg, ___) \ - V(BitOr, A_B_C, reg, reg, reg) \ - V(BitAnd, A_B_C, reg, reg, reg) \ - V(BitXor, A_B_C, reg, reg, reg) \ - V(BitNot, A_D, reg, reg, ___) \ - V(Min, A_B_C, reg, reg, reg) \ - V(Max, A_B_C, reg, reg, reg) \ - V(WriteIntoDouble, A_D, reg, reg, ___) \ - V(UnboxDouble, A_D, reg, reg, ___) \ - V(CheckedUnboxDouble, A_D, reg, reg, ___) \ - V(UnboxInt32, A_B_C, reg, reg, num) \ - V(BoxInt32, A_D, reg, reg, ___) \ - V(BoxUint32, A_D, reg, reg, ___) \ - V(SmiToDouble, A_D, reg, reg, ___) \ - V(DoubleToSmi, A_D, reg, reg, ___) \ - V(DAdd, A_B_C, reg, reg, reg) \ - V(DSub, A_B_C, reg, reg, reg) \ - V(DMul, A_B_C, reg, reg, reg) \ - V(DDiv, A_B_C, reg, reg, reg) \ - V(DNeg, A_D, reg, reg, ___) \ - V(DSqrt, A_D, reg, reg, ___) \ - V(DMin, A_B_C, reg, reg, reg) \ - V(DMax, A_B_C, reg, reg, reg) \ - V(DCos, A_D, reg, reg, ___) \ - V(DSin, A_D, reg, reg, ___) \ - V(DPow, A_B_C, reg, reg, reg) \ - V(DMod, A_B_C, reg, reg, reg) \ - V(DTruncate, A_D, reg, reg, ___) \ - V(DFloor, A_D, reg, reg, ___) \ - V(DCeil, A_D, reg, reg, ___) \ - V(DoubleToFloat, A_D, reg, reg, ___) \ - V(FloatToDouble, A_D, reg, reg, ___) \ - V(DoubleIsNaN, A, reg, ___, ___) \ - V(DoubleIsInfinite, A, reg, ___, ___) \ - V(StoreStaticTOS, D, lit, ___, ___) \ - V(PushStatic, D, lit, ___, ___) \ - V(InitStaticTOS, 0, ___, ___, ___) \ - V(IfNeStrictTOS, 0, ___, ___, ___) \ - V(IfEqStrictTOS, 0, ___, ___, ___) \ - V(IfNeStrictNumTOS, 0, ___, ___, ___) \ - V(IfEqStrictNumTOS, 0, ___, ___, ___) \ - V(IfSmiLtTOS, 0, ___, ___, ___) \ - V(IfSmiLeTOS, 0, ___, ___, ___) \ - V(IfSmiGeTOS, 0, ___, ___, ___) \ - V(IfSmiGtTOS, 0, ___, ___, ___) \ - V(IfNeStrict, A_D, reg, reg, ___) \ - V(IfEqStrict, A_D, reg, reg, ___) \ - V(IfLe, A_D, reg, reg, ___) \ - V(IfLt, A_D, reg, reg, ___) \ - V(IfGe, A_D, reg, reg, ___) \ - V(IfGt, A_D, reg, reg, ___) \ - V(IfULe, A_D, reg, reg, ___) \ - V(IfULt, A_D, reg, reg, ___) \ - V(IfUGe, A_D, reg, reg, ___) \ - V(IfUGt, A_D, reg, reg, ___) \ - V(IfDNe, A_D, reg, reg, ___) \ - V(IfDEq, A_D, reg, reg, ___) \ - V(IfDLe, A_D, reg, reg, ___) \ - V(IfDLt, A_D, reg, reg, ___) \ - V(IfDGe, A_D, reg, reg, ___) \ - V(IfDGt, A_D, reg, reg, ___) \ - V(IfNeStrictNum, A_D, reg, reg, ___) \ - V(IfEqStrictNum, A_D, reg, reg, ___) \ - V(IfEqNull, A, reg, ___, ___) \ - V(IfNeNull, A, reg, ___, ___) \ - V(CreateArrayTOS, 0, ___, ___, ___) \ - V(CreateArrayOpt, A_B_C, reg, reg, reg) \ - V(Allocate, D, lit, ___, ___) \ - V(AllocateT, 0, ___, ___, ___) \ - V(AllocateOpt, A_D, reg, lit, ___) \ - V(AllocateTOpt, A_D, reg, lit, ___) \ - V(StoreIndexedTOS, 0, ___, ___, ___) \ - V(StoreIndexed, A_B_C, reg, reg, reg) \ - V(StoreIndexedUint8, A_B_C, reg, reg, reg) \ - V(StoreIndexedExternalUint8, A_B_C, reg, reg, reg) \ - V(StoreIndexedOneByteString, A_B_C, reg, reg, reg) \ - V(StoreIndexedUint32, A_B_C, reg, reg, reg) \ - V(StoreIndexedFloat32, A_B_C, reg, reg, reg) \ - V(StoreIndexed4Float32, A_B_C, reg, reg, reg) \ - V(StoreIndexedFloat64, A_B_C, reg, reg, reg) \ - V(StoreIndexed8Float64, A_B_C, reg, reg, reg) \ - V(NoSuchMethod, 0, ___, ___, ___) \ - V(TailCall, 0, ___, ___, ___) \ - V(TailCallOpt, A_D, reg, reg, ___) \ - V(LoadArgDescriptor, 0, ___, ___, ___) \ - V(LoadArgDescriptorOpt, A, reg, ___, ___) \ - V(LoadFpRelativeSlot, X, reg, ___, ___) \ - V(LoadFpRelativeSlotOpt, A_B_Y, reg, reg, reg) \ - V(StoreFpRelativeSlot, X, reg, ___, ___) \ - V(StoreFpRelativeSlotOpt, A_B_Y, reg, reg, reg) \ - V(LoadIndexedTOS, 0, ___, ___, ___) \ - V(LoadIndexed, A_B_C, reg, reg, reg) \ - V(LoadIndexedUint8, A_B_C, reg, reg, reg) \ - V(LoadIndexedInt8, A_B_C, reg, reg, reg) \ - V(LoadIndexedInt32, A_B_C, reg, reg, reg) \ - V(LoadIndexedUint32, A_B_C, reg, reg, reg) \ - V(LoadIndexedExternalUint8, A_B_C, reg, reg, reg) \ - V(LoadIndexedExternalInt8, A_B_C, reg, reg, reg) \ - V(LoadIndexedFloat32, A_B_C, reg, reg, reg) \ - V(LoadIndexed4Float32, A_B_C, reg, reg, reg) \ - V(LoadIndexedFloat64, A_B_C, reg, reg, reg) \ - V(LoadIndexed8Float64, A_B_C, reg, reg, reg) \ - V(LoadIndexedOneByteString, A_B_C, reg, reg, reg) \ - V(LoadIndexedTwoByteString, A_B_C, reg, reg, reg) \ - V(StoreField, A_B_C, reg, num, reg) \ - V(StoreFieldExt, A_D, reg, reg, ___) \ - V(StoreFieldTOS, D, lit, ___, ___) \ - V(StoreContextParent, 0, ___, ___, ___) \ - V(StoreContextVar, D, num, ___, ___) \ - V(LoadField, A_B_C, reg, reg, num) \ - V(LoadFieldExt, A_D, reg, reg, ___) \ - V(LoadUntagged, A_B_C, reg, reg, num) \ - V(LoadFieldTOS, D, lit, ___, ___) \ + V(ReturnTOS, 0, ___, ___, ___) \ + V(AssertAssignable, A_D, num, lit, ___) \ + V(AssertBoolean, A, num, ___, ___) \ + V(AssertSubtype, 0, ___, ___, ___) \ V(LoadTypeArgumentsField, D, lit, ___, ___) \ - V(LoadContextParent, 0, ___, ___, ___) \ - V(LoadContextVar, D, num, ___, ___) \ - V(BooleanNegateTOS, 0, ___, ___, ___) \ - V(BooleanNegate, A_D, reg, reg, ___) \ - V(Throw, A, num, ___, ___) \ - V(Entry, D, num, ___, ___) \ - V(EntryFixed, A_D, 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, ___, ___) \ - V(AllocateUninitializedContext, A_D, reg, num, ___) \ - V(CloneContext, 0, ___, ___, ___) \ - V(MoveSpecial, A_D, reg, num, ___) \ V(InstantiateType, D, lit, ___, ___) \ V(InstantiateTypeArgumentsTOS, A_D, num, lit, ___) \ - V(InstanceOf, 0, ___, ___, ___) \ - V(BadTypeError, 0, ___, ___, ___) \ - V(AssertAssignable, A_D, num, lit, ___) \ - V(AssertSubtype, 0, ___, ___, ___) \ - V(AssertBoolean, A, num, ___, ___) \ - V(TestSmi, A_D, reg, reg, ___) \ - V(TestCids, A_D, reg, num, ___) \ - V(CheckSmi, A, reg, ___, ___) \ - V(CheckEitherNonSmi, A_D, reg, reg, ___) \ - V(CheckClassId, A_D, reg, num, ___) \ - V(CheckClassIdRange, A_D, reg, num, ___) \ - V(CheckBitTest, A_D, reg, num, ___) \ - V(CheckCids, A_B_C, reg, num, num) \ - V(CheckCidsByRange, A_B_C, reg, num, num) \ - V(CheckStack, 0, ___, ___, ___) \ - V(CheckStackAlwaysExit, 0, ___, ___, ___) \ - V(CheckFunctionTypeArgs, A_D, num, num, ___) \ - V(DebugStep, 0, ___, ___, ___) \ - V(DebugBreak, A, num, ___, ___) \ - V(Deopt, A_D, num, num, ___) \ - V(DeoptRewind, 0, ___, ___, ___) + V(Throw, A, num, ___, ___) \ + V(MoveSpecial, A_D, reg, num, ___) \ + V(SetFrame, A, num, ___, num) \ + V(BooleanNegateTOS, 0, ___, ___, ___) // clang-format on @@ -1171,29 +540,8 @@ class KernelBytecode { DART_FORCE_INLINE static bool IsCallOpcode(KBCInstr instr) { switch (DecodeOpcode(instr)) { - case KernelBytecode::kStaticCall: case KernelBytecode::kIndirectStaticCall: case KernelBytecode::kInstanceCall: - case KernelBytecode::kInstanceCall1Opt: - case KernelBytecode::kInstanceCall2Opt: - case KernelBytecode::kDebugBreak: - return true; - - default: - return false; - } - } - - DART_FORCE_INLINE static bool IsFastSmiOpcode(KBCInstr instr) { - switch (DecodeOpcode(instr)) { - case KernelBytecode::kAddTOS: - case KernelBytecode::kSubTOS: - case KernelBytecode::kMulTOS: - case KernelBytecode::kBitOrTOS: - case KernelBytecode::kBitAndTOS: - case KernelBytecode::kEqualTOS: - case KernelBytecode::kLessThanTOS: - case KernelBytecode::kGreaterThanTOS: return true; default: diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc index fd862fa7f8b..2d0bdde1362 100644 --- a/runtime/vm/interpreter.cc +++ b/runtime/vm/interpreter.cc @@ -631,186 +631,6 @@ void Interpreter::Exit(Thread* thread, #endif } -// TODO(vegorov): Investigate advantages of using -// __builtin_s{add,sub,mul}_overflow() intrinsics here and below. -// Note that they may clobber the output location even when there is overflow: -// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html -DART_FORCE_INLINE static bool SignedAddWithOverflow(int32_t lhs, - int32_t rhs, - intptr_t* out) { - intptr_t res = 1; -#if defined(HOST_ARCH_IA32) - asm volatile( - "add %2, %1\n" - "jo 1f;\n" - "xor %0, %0\n" - "mov %1, 0(%3)\n" - "1: " - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_X64) - int64_t tmp; - asm volatile( - "addl %[rhs], %[lhs]\n" - "jo 1f;\n" - "xor %[res], %[res]\n" - "movslq %[lhs], %[tmp]\n" - "mov %[tmp], 0(%[out])\n" - "1: " - : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp) - : [rhs] "r"(rhs), [out] "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM) - asm volatile( - "adds %1, %1, %2;\n" - "bvs 1f;\n" - "mov %0, #0;\n" - "str %1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM64) - asm volatile( - "adds %w1, %w1, %w2;\n" - "bvs 1f;\n" - "sxtw %x1, %w1;\n" - "mov %0, #0;\n" - "str %x1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#else -#error "Unsupported platform" -#endif - return (res != 0); -} - -DART_FORCE_INLINE static bool SignedSubWithOverflow(int32_t lhs, - int32_t rhs, - intptr_t* out) { - intptr_t res = 1; -#if defined(HOST_ARCH_IA32) - asm volatile( - "sub %2, %1\n" - "jo 1f;\n" - "xor %0, %0\n" - "mov %1, 0(%3)\n" - "1: " - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_X64) - int64_t tmp; - asm volatile( - "subl %[rhs], %[lhs]\n" - "jo 1f;\n" - "xor %[res], %[res]\n" - "movslq %[lhs], %[tmp]\n" - "mov %[tmp], 0(%[out])\n" - "1: " - : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp) - : [rhs] "r"(rhs), [out] "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM) - asm volatile( - "subs %1, %1, %2;\n" - "bvs 1f;\n" - "mov %0, #0;\n" - "str %1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM64) - asm volatile( - "subs %w1, %w1, %w2;\n" - "bvs 1f;\n" - "sxtw %x1, %w1;\n" - "mov %0, #0;\n" - "str %x1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#else -#error "Unsupported platform" -#endif - return (res != 0); -} - -DART_FORCE_INLINE static bool SignedMulWithOverflow(int32_t lhs, - int32_t rhs, - intptr_t* out) { - intptr_t res = 1; -#if defined(HOST_ARCH_IA32) - asm volatile( - "imul %2, %1\n" - "jo 1f;\n" - "xor %0, %0\n" - "mov %1, 0(%3)\n" - "1: " - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#elif defined(HOST_ARCH_X64) - int64_t tmp; - asm volatile( - "imull %[rhs], %[lhs]\n" - "jo 1f;\n" - "xor %[res], %[res]\n" - "movslq %[lhs], %[tmp]\n" - "mov %[tmp], 0(%[out])\n" - "1: " - : [res] "+r"(res), [lhs] "+r"(lhs), [tmp] "=&r"(tmp) - : [rhs] "r"(rhs), [out] "r"(out) - : "cc"); -#elif defined(HOST_ARCH_ARM) - asm volatile( - "smull %1, ip, %1, %2;\n" - "cmp ip, %1, ASR #31;\n" - "bne 1f;\n" - "mov %0, $0;\n" - "str %1, [%3, #0]\n" - "1:" - : "+r"(res), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc", "r12"); -#elif defined(HOST_ARCH_ARM64) - int64_t prod_lo = 0; - asm volatile( - "smull %x1, %w2, %w3\n" - "asr %x2, %x1, #63\n" - "cmp %x2, %x1, ASR #31;\n" - "bne 1f;\n" - "mov %0, #0;\n" - "str %x1, [%4, #0]\n" - "1:" - : "=r"(res), "+r"(prod_lo), "+r"(lhs) - : "r"(rhs), "r"(out) - : "cc"); -#else -#error "Unsupported platform" -#endif - return (res != 0); -} - -DART_FORCE_INLINE static bool AreBothSmis(intptr_t a, intptr_t b) { - return ((a | b) & kHeapObjectTag) == 0; -} - -#define SMI_MUL(lhs, rhs, pres) SignedMulWithOverflow((lhs), (rhs) >> 1, pres) -#define SMI_COND(cond, lhs, rhs, pres) \ - ((*(pres) = ((lhs cond rhs) ? true_value : false_value)), false) -#define SMI_EQ(lhs, rhs, pres) SMI_COND(==, lhs, rhs, pres) -#define SMI_LT(lhs, rhs, pres) SMI_COND(<, lhs, rhs, pres) -#define SMI_GT(lhs, rhs, pres) SMI_COND(>, lhs, rhs, pres) -#define SMI_BITOR(lhs, rhs, pres) ((*(pres) = (lhs | rhs)), false) -#define SMI_BITAND(lhs, rhs, pres) ((*(pres) = ((lhs) & (rhs))), false) -#define SMI_BITXOR(lhs, rhs, pres) ((*(pres) = ((lhs) ^ (rhs))), false) - void Interpreter::CallRuntime(Thread* thread, RawObject** base, RawObject** exit_frame, @@ -1468,54 +1288,6 @@ DART_FORCE_INLINE void Interpreter::PrepareForTailCall( USE(rD) #define DECODE_A_X rD = (static_cast(op) >> KernelBytecode::kDShift); -#define SMI_FASTPATH_ICDATA_INC \ - do { \ - ASSERT(KernelBytecode::IsCallOpcode(*pc)); \ - const uint16_t kidx = KernelBytecode::DecodeD(*pc); \ - const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); \ - RawObject** entries = icdata->ptr()->ic_data_->ptr()->data(); \ - InterpreterHelpers::IncrementICUsageCount(entries, 0, 2); \ - } while (0); - -// Declare bytecode handler for a smi operation (e.g. AddTOS) with the -// given result type and the given behavior specified as a function -// that takes left and right operands and result slot and returns -// true if fast-path succeeds. -#define SMI_FASTPATH_TOS(ResultT, Func) \ - { \ - const intptr_t lhs = reinterpret_cast(SP[-1]); \ - const intptr_t rhs = reinterpret_cast(SP[-0]); \ - ResultT* slot = reinterpret_cast(SP - 1); \ - if (LIKELY(!thread->isolate()->single_step()) && \ - LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) { \ - SMI_FASTPATH_ICDATA_INC; \ - /* Fast path succeeded. Skip the generic call that follows. */ \ - pc++; \ - /* We dropped 2 arguments and push result */ \ - SP--; \ - } \ - } - -// Skip the next instruction if there is no overflow. -#define SMI_OP_CHECK(ResultT, Func) \ - { \ - const intptr_t lhs = reinterpret_cast(FP[rB]); \ - const intptr_t rhs = reinterpret_cast(FP[rC]); \ - ResultT* slot = reinterpret_cast(&FP[rA]); \ - if (LIKELY(!Func(lhs, rhs, slot))) { \ - /* Success. Skip the instruction that follows. */ \ - pc++; \ - } \ - } - -// Do not check for overflow. -#define SMI_OP_NOCHECK(ResultT, Func) \ - { \ - const intptr_t lhs = reinterpret_cast(FP[rB]); \ - const intptr_t rhs = reinterpret_cast(FP[rC]); \ - ResultT* slot = reinterpret_cast(&FP[rA]); \ - Func(lhs, rhs, slot); \ - } // Exception handling helper. Gets handler FP and PC from the Interpreter where // they were stored by Interpreter::Longjmp and proceeds to execute the handler. @@ -2008,16 +1780,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(EntryOptimized, A_D); - const uint16_t num_registers = rD; - - // Reserve space for registers used by the optimized code. - SP = FP + num_registers - 1; - - DISPATCH(); - } - { BYTECODE(Frame, A_D); // Initialize locals with null and increment SP. @@ -2036,78 +1798,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(Compile, 0); - FP[0] = argdesc_; - FP[1] = FrameFunction(FP); - FP[2] = 0; - - UNIMPLEMENTED(); // TODO(regis): Revisit. - - Exit(thread, FP, FP + 3, pc); - NativeArguments args(thread, 1, FP + 1, FP + 2); - INVOKE_RUNTIME(DRT_CompileFunction, args); - { - // Function should be compiled now, dispatch to its entry point. - RawCode* code = FrameFunction(FP)->ptr()->code_; - InterpreterHelpers::SetFrameCode(FP, code); - pp_ = code->ptr()->object_pool_; - pc = reinterpret_cast(code->ptr()->entry_point_); - pc_ = reinterpret_cast(pc); // For the profiler. - argdesc_ = static_cast(FP[0]); - } - DISPATCH(); - } - - { - BYTECODE(HotCheck, A_D); - const uint8_t increment = rA; - const uint16_t threshold = rD; - RawFunction* f = FrameFunction(FP); - int32_t counter = f->ptr()->usage_counter_; - // Note: we don't increment usage counter in the prologue of optimized - // functions. - if (increment) { - counter += increment; - f->ptr()->usage_counter_ = counter; - } - if (UNLIKELY(counter >= threshold)) { - FP[0] = f; - FP[1] = 0; - - // Save the args desriptor which came in. - FP[2] = argdesc_; - - UNIMPLEMENTED(); // TODO(regis): Revisit. - - // Make the DRT_OptimizeInvokedFunction see a stub as its caller for - // consistency with the other architectures, and to avoid needing to - // generate a stackmap for the HotCheck pc. - const StubEntry* stub = StubCode::OptimizeFunction_entry(); - FP[kKBCPcMarkerSlotFromFp] = stub->code(); - pc = reinterpret_cast(stub->EntryPoint()); - - Exit(thread, FP, FP + 3, pc); - NativeArguments args(thread, 1, /*argv=*/FP, /*retval=*/FP + 1); - INVOKE_RUNTIME(DRT_OptimizeInvokedFunction, args); - { - // DRT_OptimizeInvokedFunction returns the code object to execute. - ASSERT(FP[1]->GetClassId() == kFunctionCid); - RawFunction* function = static_cast(FP[1]); - RawCode* code = function->ptr()->code_; - InterpreterHelpers::SetFrameCode(FP, code); - - // Restore args descriptor which came in. - argdesc_ = Array::RawCast(FP[2]); - - pp_ = code->ptr()->object_pool_; - pc = reinterpret_cast(function->ptr()->entry_point_); - pc_ = reinterpret_cast(pc); // For the profiler. - } - } - DISPATCH(); - } - { BYTECODE(CheckStack, A); { @@ -2134,16 +1824,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(CheckStackAlwaysExit, A); - { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_StackOverflow, args); - } - DISPATCH(); - } - { BYTECODE(CheckFunctionTypeArgs, A_D); const uint16_t declared_type_args_len = rA; @@ -2166,38 +1846,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(DebugStep, A); - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } - DISPATCH(); - } - - { - BYTECODE(DebugBreak, A); -#if !defined(PRODUCT) - { - const uint32_t original_bc = - static_cast(reinterpret_cast( - thread->isolate()->debugger()->GetPatchedStubAddress( - reinterpret_cast(pc)))); - - SP[1] = null_value; - Exit(thread, FP, SP + 2, pc); - NativeArguments args(thread, 0, NULL, SP + 1); - INVOKE_RUNTIME(DRT_BreakpointRuntimeHandler, args) - DISPATCH_OP(original_bc); - } -#else - // There should be no debug breaks in product mode. - UNREACHABLE(); -#endif - DISPATCH(); - } - { BYTECODE(InstantiateType, A_D); // Stack: instantiator type args, function type args @@ -2277,20 +1925,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(Drop, 0); - SP -= rA; - DISPATCH(); - } - - { - BYTECODE(DropR, 0); - RawObject* result = SP[0]; - SP -= rA; - SP[0] = result; - DISPATCH(); - } - { BYTECODE(LoadConstant, A_D); FP[rA] = LOAD_CONSTANT(rD); @@ -2333,20 +1967,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(Move, A_X); - FP[rA] = FP[rD]; - DISPATCH(); - } - - { - BYTECODE(Swap, A_X); - RawObject* tmp = FP[rD]; - FP[rD] = FP[rA]; - FP[rA] = tmp; - DISPATCH(); - } - { BYTECODE(StoreLocal, A_X); FP[rD] = *SP; @@ -2371,12 +1991,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(BooleanNegate, A_D); - FP[rA] = (FP[rD] == true_value) ? false_value : true_value; - DISPATCH(); - } - { BYTECODE(IndirectStaticCall, A_D); @@ -2407,18 +2021,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(StaticCall, A_D); - const uint16_t argc = rA; - RawObject** call_base = SP - argc; - RawObject** call_top = SP; // *SP contains function - argdesc_ = static_cast(LOAD_CONSTANT(rD)); - if (!Invoke(thread, call_base, call_top, &pc, &FP, &SP)) { - HANDLE_EXCEPTION; - } - DISPATCH(); - } - { BYTECODE(InstanceCall, A_D); @@ -2457,90 +2059,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(InstanceCall1Opt, A_D); - - { - const uint16_t argc = rA; - const uint16_t kidx = rD; - - RawObject** call_base = SP - argc + 1; - RawObject** call_top = SP + 1; - - RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); - InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP)); - if (!InstanceCall1(thread, icdata, call_base, call_top, &pc, &FP, &SP, - true /* optimized */)) { - HANDLE_EXCEPTION; - } - } - - DISPATCH(); - } - - { - BYTECODE(InstanceCall2Opt, A_D); - - { - const uint16_t argc = rA; - const uint16_t kidx = rD; - - RawObject** call_base = SP - argc + 1; - RawObject** call_top = SP + 1; - - RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx)); - InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP)); - if (!InstanceCall2(thread, icdata, call_base, call_top, &pc, &FP, &SP, - true /* optimized */)) { - HANDLE_EXCEPTION; - } - } - - DISPATCH(); - } - - { - BYTECODE(PushPolymorphicInstanceCall, A_D); - const uint8_t argc = rA; - const intptr_t cids_length = rD; - RawObject** args = SP - argc + 1; - const intptr_t receiver_cid = InterpreterHelpers::GetClassId(args[0]); - for (intptr_t i = 0; i < 2 * cids_length; i += 2) { - const intptr_t icdata_cid = KernelBytecode::DecodeD(*(pc + i)); - if (receiver_cid == icdata_cid) { - RawFunction* target = RAW_CAST( - Function, LOAD_CONSTANT(KernelBytecode::DecodeD(*(pc + i + 1)))); - *++SP = target; - pc++; - break; - } - } - pc += 2 * cids_length; - DISPATCH(); - } - - { - BYTECODE(PushPolymorphicInstanceCallByRange, A_D); - const uint8_t argc = rA; - const intptr_t cids_length = rD; - RawObject** args = SP - argc + 1; - const intptr_t receiver_cid = InterpreterHelpers::GetClassId(args[0]); - for (intptr_t i = 0; i < 3 * cids_length; i += 3) { - // Note unsigned types to get an unsigned range compare. - const uintptr_t cid_start = KernelBytecode::DecodeD(*(pc + i)); - const uintptr_t cids = KernelBytecode::DecodeD(*(pc + i + 1)); - if (receiver_cid - cid_start < cids) { - RawFunction* target = RAW_CAST( - Function, LOAD_CONSTANT(KernelBytecode::DecodeD(*(pc + i + 2)))); - *++SP = target; - pc++; - break; - } - } - pc += 3 * cids_length; - DISPATCH(); - } - { BYTECODE(NativeCall, __D); RawTypedData* data = static_cast(LOAD_CONSTANT(rD)); @@ -2706,779 +2224,12 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(OneByteStringFromCharCode, A_X); - const intptr_t char_code = Smi::Value(RAW_CAST(Smi, FP[rD])); - ASSERT(char_code >= 0); - ASSERT(char_code <= 255); - RawString** strings = Symbols::PredefinedAddress(); - const intptr_t index = char_code + Symbols::kNullCharCodeSymbolOffset; - FP[rA] = strings[index]; - DISPATCH(); - } - - { - BYTECODE(StringToCharCode, A_X); - RawOneByteString* str = RAW_CAST(OneByteString, FP[rD]); - if (str->ptr()->length_ == Smi::New(1)) { - FP[rA] = Smi::New(str->ptr()->data()[0]); - } else { - FP[rA] = Smi::New(-1); - } - DISPATCH(); - } - - { - BYTECODE(AddTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SignedAddWithOverflow); - DISPATCH(); - } - { - BYTECODE(SubTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SignedSubWithOverflow); - DISPATCH(); - } - { - BYTECODE(MulTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SMI_MUL); - DISPATCH(); - } - { - BYTECODE(BitOrTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SMI_BITOR); - DISPATCH(); - } - { - BYTECODE(BitAndTOS, A_B_C); - SMI_FASTPATH_TOS(intptr_t, SMI_BITAND); - DISPATCH(); - } - { - BYTECODE(EqualTOS, A_B_C); - SMI_FASTPATH_TOS(RawObject*, SMI_EQ); - DISPATCH(); - } - { - BYTECODE(LessThanTOS, A_B_C); - SMI_FASTPATH_TOS(RawObject*, SMI_LT); - DISPATCH(); - } - { - BYTECODE(GreaterThanTOS, A_B_C); - SMI_FASTPATH_TOS(RawObject*, SMI_GT); - DISPATCH(); - } - { - BYTECODE(SmiAddTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) + Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(SmiSubTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) - Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(SmiMulTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) * Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(SmiBitAndTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - SP--; - SP[0] = Smi::New(Smi::Value(left) & Smi::Value(right)); - DISPATCH(); - } - { - BYTECODE(Add, A_B_C); - SMI_OP_CHECK(intptr_t, SignedAddWithOverflow); - DISPATCH(); - } - { - BYTECODE(Sub, A_B_C); - SMI_OP_CHECK(intptr_t, SignedSubWithOverflow); - DISPATCH(); - } - { - BYTECODE(Mul, A_B_C); - SMI_OP_CHECK(intptr_t, SMI_MUL); - DISPATCH(); - } - { - BYTECODE(Neg, A_D); - const intptr_t value = reinterpret_cast(FP[rD]); - intptr_t* out = reinterpret_cast(&FP[rA]); - if (LIKELY(!SignedSubWithOverflow(0, value, out))) { - pc++; - } - DISPATCH(); - } - { - BYTECODE(BitOr, A_B_C); - SMI_OP_NOCHECK(intptr_t, SMI_BITOR); - DISPATCH(); - } - { - BYTECODE(BitAnd, A_B_C); - SMI_OP_NOCHECK(intptr_t, SMI_BITAND); - DISPATCH(); - } - { - BYTECODE(BitXor, A_B_C); - SMI_OP_NOCHECK(intptr_t, SMI_BITXOR); - DISPATCH(); - } - { - BYTECODE(BitNot, A_D); - const intptr_t value = reinterpret_cast(FP[rD]); - *reinterpret_cast(&FP[rA]) = ~value & (~kSmiTagMask); - DISPATCH(); - } - - { - BYTECODE(Div, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]); - if (rhs != 0) { - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t res = (lhs >> kSmiTagSize) / (rhs >> kSmiTagSize); - const intptr_t untaggable = 0x40000000L; - if (res != untaggable) { - *reinterpret_cast(&FP[rA]) = res << kSmiTagSize; - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(Mod, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]); - if (rhs != 0) { - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t res = ((lhs >> kSmiTagSize) % (rhs >> kSmiTagSize)) - << kSmiTagSize; - *reinterpret_cast(&FP[rA]) = - (res < 0) ? ((rhs < 0) ? (res - rhs) : (res + rhs)) : res; - pc++; - } - DISPATCH(); - } - - { - BYTECODE(Shl, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]) >> kSmiTagSize; - const int kBitsPerInt32 = 32; - if (static_cast(rhs) < kBitsPerInt32) { - const int32_t lhs = reinterpret_cast(FP[rB]); - const int32_t res = lhs << rhs; - if (lhs == (res >> rhs)) { - *reinterpret_cast(&FP[rA]) = static_cast(res); - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(Shr, A_B_C); - const intptr_t rhs = reinterpret_cast(FP[rC]) >> kSmiTagSize; - if (rhs >= 0) { - const intptr_t shift_amount = (rhs >= 32) ? (32 - 1) : rhs; - const intptr_t lhs = reinterpret_cast(FP[rB]) >> kSmiTagSize; - *reinterpret_cast(&FP[rA]) = (lhs >> shift_amount) - << kSmiTagSize; - pc++; - } - DISPATCH(); - } - - { - BYTECODE(ShlImm, A_B_C); - const uint8_t shift = rC; - const intptr_t lhs = reinterpret_cast(FP[rB]); - FP[rA] = reinterpret_cast(lhs << shift); - DISPATCH(); - } - - { - BYTECODE(Min, A_B_C); - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t rhs = reinterpret_cast(FP[rC]); - FP[rA] = reinterpret_cast((lhs < rhs) ? lhs : rhs); - DISPATCH(); - } - - { - BYTECODE(Max, A_B_C); - const intptr_t lhs = reinterpret_cast(FP[rB]); - const intptr_t rhs = reinterpret_cast(FP[rC]); - FP[rA] = reinterpret_cast((lhs > rhs) ? lhs : rhs); - DISPATCH(); - } - - { - BYTECODE(UnboxInt32, A_B_C); - const intptr_t box_cid = InterpreterHelpers::GetClassId(FP[rB]); - const bool may_truncate = rC == 1; - if (box_cid == kSmiCid) { - const intptr_t value = reinterpret_cast(FP[rB]) >> kSmiTagSize; - const int32_t value32 = static_cast(value); - if (may_truncate || (value == static_cast(value32))) { - FP[rA] = reinterpret_cast(value); - pc++; - } - } else if (box_cid == kMintCid) { - RawMint* mint = RAW_CAST(Mint, FP[rB]); - const int64_t value = mint->ptr()->value_; - const int32_t value32 = static_cast(value); - if (may_truncate || (value == static_cast(value32))) { - FP[rA] = reinterpret_cast(value); - pc++; - } - } - DISPATCH(); - } - -#if defined(ARCH_IS_64_BIT) - { - BYTECODE(WriteIntoDouble, A_D); - const double value = bit_cast(FP[rD]); - RawDouble* box = RAW_CAST(Double, FP[rA]); - box->ptr()->value_ = value; - DISPATCH(); - } - - { - BYTECODE(UnboxDouble, A_D); - const RawDouble* box = RAW_CAST(Double, FP[rD]); - FP[rA] = bit_cast(box->ptr()->value_); - DISPATCH(); - } - - { - BYTECODE(CheckedUnboxDouble, A_D); - const intptr_t box_cid = InterpreterHelpers::GetClassId(FP[rD]); - if (box_cid == kSmiCid) { - const intptr_t value = reinterpret_cast(FP[rD]) >> kSmiTagSize; - const double result = static_cast(value); - FP[rA] = bit_cast(result); - pc++; - } else if (box_cid == kDoubleCid) { - const RawDouble* box = RAW_CAST(Double, FP[rD]); - FP[rA] = bit_cast(box->ptr()->value_); - pc++; - } - DISPATCH(); - } - - { - BYTECODE(DoubleToSmi, A_D); - const double value = bit_cast(FP[rD]); - if (!isnan(value)) { - const intptr_t result = static_cast(value); - if ((result <= Smi::kMaxValue) && (result >= Smi::kMinValue)) { - FP[rA] = reinterpret_cast(result << kSmiTagSize); - pc++; - } - } - DISPATCH(); - } - - { - BYTECODE(SmiToDouble, A_D); - const intptr_t value = reinterpret_cast(FP[rD]) >> kSmiTagSize; - const double result = static_cast(value); - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DAdd, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(lhs + rhs); - DISPATCH(); - } - - { - BYTECODE(DSub, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(lhs - rhs); - DISPATCH(); - } - - { - BYTECODE(DMul, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(lhs * rhs); - DISPATCH(); - } - - { - BYTECODE(DDiv, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - const double result = lhs / rhs; - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DNeg, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(-value); - DISPATCH(); - } - - { - BYTECODE(DSqrt, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(sqrt(value)); - DISPATCH(); - } - - { - BYTECODE(DSin, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(sin(value)); - DISPATCH(); - } - - { - BYTECODE(DCos, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(cos(value)); - DISPATCH(); - } - - { - BYTECODE(DPow, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - const double result = pow(lhs, rhs); - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DMod, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - const double result = DartModulo(lhs, rhs); - FP[rA] = bit_cast(result); - DISPATCH(); - } - - { - BYTECODE(DMin, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(fmin(lhs, rhs)); - DISPATCH(); - } - - { - BYTECODE(DMax, A_B_C); - const double lhs = bit_cast(FP[rB]); - const double rhs = bit_cast(FP[rC]); - FP[rA] = bit_cast(fmax(lhs, rhs)); - DISPATCH(); - } - - { - BYTECODE(DTruncate, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(trunc(value)); - DISPATCH(); - } - - { - BYTECODE(DFloor, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(floor(value)); - DISPATCH(); - } - - { - BYTECODE(DCeil, A_D); - const double value = bit_cast(FP[rD]); - FP[rA] = bit_cast(ceil(value)); - DISPATCH(); - } - - { - BYTECODE(DoubleToFloat, A_D); - const double value = bit_cast(FP[rD]); - const float valuef = static_cast(value); - *reinterpret_cast(&FP[rA]) = valuef; - DISPATCH(); - } - - { - BYTECODE(FloatToDouble, A_D); - const float valuef = *reinterpret_cast(&FP[rD]); - const double value = static_cast(valuef); - FP[rA] = bit_cast(value); - DISPATCH(); - } - - { - BYTECODE(DoubleIsNaN, A); - const double v = bit_cast(FP[rA]); - if (!isnan(v)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(DoubleIsInfinite, A); - const double v = bit_cast(FP[rA]); - if (!isinf(v)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat32, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rB], FP[rC]); - const uint32_t value = *reinterpret_cast(data); - const uint64_t value64 = value; - FP[rA] = reinterpret_cast(value64); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed4Float32, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - const uint32_t value = - reinterpret_cast(array->ptr()->data())[Smi::Value(index)]; - const uint64_t value64 = value; // sign extend to clear high bits. - FP[rA] = reinterpret_cast(value64); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat64, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rB], FP[rC]); - *reinterpret_cast(&FP[rA]) = *reinterpret_cast(data); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed8Float64, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rB]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - const int64_t value = - reinterpret_cast(array->ptr()->data())[Smi::Value(index)]; - FP[rA] = reinterpret_cast(value); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat32, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rA], FP[rB]); - const uint64_t value = reinterpret_cast(FP[rC]); - const uint32_t value32 = value; - *reinterpret_cast(data) = value32; - DISPATCH(); - } - - { - BYTECODE(StoreIndexed4Float32, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - const uint64_t value = reinterpret_cast(FP[rC]); - const uint32_t value32 = value; - reinterpret_cast(array->ptr()->data())[Smi::Value(index)] = - value32; - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat64, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rA], FP[rB]); - *reinterpret_cast(data) = reinterpret_cast(FP[rC]); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed8Float64, A_B_C); - ASSERT(RawObject::IsTypedDataClassId(FP[rA]->GetClassId())); - RawTypedData* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - const int64_t value = reinterpret_cast(FP[rC]); - reinterpret_cast(array->ptr()->data())[Smi::Value(index)] = value; - DISPATCH(); - } - - { - BYTECODE(BoxInt32, A_D); - // Casts sign-extend high 32 bits from low 32 bits. - const intptr_t value = reinterpret_cast(FP[rD]); - const int32_t value32 = static_cast(value); - FP[rA] = Smi::New(static_cast(value32)); - DISPATCH(); - } - - { - BYTECODE(BoxUint32, A_D); - // Casts to zero out high 32 bits. - const uintptr_t value = reinterpret_cast(FP[rD]); - const uint32_t value32 = static_cast(value); - FP[rA] = Smi::New(static_cast(value32)); - DISPATCH(); - } -#else // defined(ARCH_IS_64_BIT) - { - BYTECODE(WriteIntoDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(UnboxDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(CheckedUnboxDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DoubleToSmi, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(SmiToDouble, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DAdd, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DSub, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DMul, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DDiv, A_B_C); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DNeg, A_D); - UNIMPLEMENTED(); - DISPATCH(); - } - - { - BYTECODE(DSqrt, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DSin, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DCos, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DPow, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DMod, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DMin, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DMax, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DTruncate, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DFloor, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DCeil, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DoubleToFloat, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(FloatToDouble, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DoubleIsNaN, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(DoubleIsInfinite, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed4Float32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedFloat64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(LoadIndexed8Float64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed4Float32, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedFloat64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(StoreIndexed8Float64, A_B_C); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(BoxInt32, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(BoxUint32, A_D); - UNREACHABLE(); - DISPATCH(); - } -#endif // defined(ARCH_IS_64_BIT) - // Return and return like instructions (Intrinsic). { RawObject* result; // result to return to the caller. - BYTECODE(Intrinsic, A); - // Try invoking intrinsic handler. If it succeeds (returns true) - // then just return the value it returned to the caller. - result = null_value; - if (!intrinsics_[rA](thread, FP, &result)) { - DISPATCH(); - } - goto ReturnImpl; - - BYTECODE(Return, A); - result = FP[rA]; - goto ReturnImpl; - BYTECODE(ReturnTOS, 0); result = *SP; - // Fall through to the ReturnImpl. - - ReturnImpl: // Restore caller PC. pc = SavedCallerPC(FP); pc_ = reinterpret_cast(pc); // For the profiler. @@ -3540,38 +2291,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(StoreField, A_B_C); - const uint16_t offset_in_words = rB; - const uint16_t value_reg = rC; - - RawInstance* instance = reinterpret_cast(FP[rA]); - RawObject* value = FP[value_reg]; - - // TODO(regis): Implement cid guard. - ASSERT(!thread->isolate()->use_field_guards()); - - instance->StorePointer( - reinterpret_cast(instance->ptr()) + offset_in_words, value, - thread); - DISPATCH(); - } - - { - BYTECODE(StoreFieldExt, A_D); - // The offset is stored in the following nop-instruction which is skipped. - const uint16_t offset_in_words = KernelBytecode::DecodeD(*pc++); - RawInstance* instance = reinterpret_cast(FP[rA]); - RawObject* value = FP[rD]; - - UNREACHABLE(); // TODO(regis): unused, remove. - - instance->StorePointer( - reinterpret_cast(instance->ptr()) + offset_in_words, value, - thread); - DISPATCH(); - } - { BYTECODE(StoreFieldTOS, __D); const uword offset_in_words = @@ -3620,34 +2339,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(LoadField, A_B_C); - const uint16_t instance_reg = rB; - const uint16_t offset_in_words = rC; - RawInstance* instance = reinterpret_cast(FP[instance_reg]); - FP[rA] = reinterpret_cast(instance->ptr())[offset_in_words]; - DISPATCH(); - } - - { - BYTECODE(LoadFieldExt, A_D); - // The offset is stored in the following nop-instruction which is skipped. - const uint16_t offset_in_words = KernelBytecode::DecodeD(*pc++); - const uint16_t instance_reg = rD; - RawInstance* instance = reinterpret_cast(FP[instance_reg]); - FP[rA] = reinterpret_cast(instance->ptr())[offset_in_words]; - DISPATCH(); - } - - { - BYTECODE(LoadUntagged, A_B_C); - const uint16_t instance_reg = rB; - const uint16_t offset_in_words = rC; - RawInstance* instance = reinterpret_cast(FP[instance_reg]); - FP[rA] = reinterpret_cast(instance)[offset_in_words]; - DISPATCH(); - } - { BYTECODE(LoadFieldTOS, __D); const uword offset_in_words = @@ -3684,45 +2375,8 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(InitStaticTOS, 0); - UNREACHABLE(); // Not used. TODO(regis): Remove this bytecode. - RawField* field = static_cast(*SP--); - RawObject* value = field->ptr()->value_.static_value_; - if ((value == Object::sentinel().raw()) || - (value == Object::transition_sentinel().raw())) { - // Note: SP[1] already contains the field object. - SP[2] = 0; - Exit(thread, FP, SP + 3, pc); - NativeArguments args(thread, 1, SP + 1, SP + 2); - INVOKE_RUNTIME(DRT_InitStaticField, args); - } - DISPATCH(); - } - // TODO(vegorov) allocation bytecodes can benefit from the new-space // allocation fast-path that does not transition into the runtime system. - { - BYTECODE(AllocateUninitializedContext, A_D); - const uint16_t num_context_variables = rD; - const intptr_t instance_size = Context::InstanceSize(num_context_variables); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - uint32_t tags = 0; - tags = RawObject::ClassIdTag::update(kContextCid, tags); - tags = RawObject::SizeTag::update(instance_size, tags); - tags = RawObject::NewBit::update(true, tags); - // Also writes 0 in the hash_ field of the header. - *reinterpret_cast(start + Array::tags_offset()) = tags; - *reinterpret_cast(start + Context::num_variables_offset()) = - num_context_variables; - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - pc += 2; - } - DISPATCH(); - } - { BYTECODE(AllocateContext, A_D); const uint16_t num_context_variables = rD; @@ -3747,26 +2401,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(AllocateOpt, A_D); - uint32_t tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))); - const intptr_t instance_size = RawObject::SizeTag::decode(tags); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - // Writes both the tags and the initial identity hash on 64 bit platforms. - tags = RawObject::NewBit::update(true, tags); - *reinterpret_cast(start + Instance::tags_offset()) = tags; - for (intptr_t current_offset = sizeof(RawInstance); - current_offset < instance_size; current_offset += kWordSize) { - *reinterpret_cast(start + current_offset) = null_value; - } - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - pc += 2; - } - DISPATCH(); - } - { BYTECODE(Allocate, A_D); SP[1] = 0; // Space for the result. @@ -3779,30 +2413,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(AllocateTOpt, A_D); - uint32_t tags = Smi::Value(RAW_CAST(Smi, LOAD_CONSTANT(rD))); - const intptr_t instance_size = RawObject::SizeTag::decode(tags); - const uword start = - thread->heap()->new_space()->TryAllocateInTLAB(thread, instance_size); - if (LIKELY(start != 0)) { - RawObject* type_args = SP[0]; - const intptr_t type_args_offset = KernelBytecode::DecodeD(*pc); - // Writes both the tags and the initial identity hash on 64 bit platforms. - tags = RawObject::NewBit::update(true, tags); - *reinterpret_cast(start + Instance::tags_offset()) = tags; - for (intptr_t current_offset = sizeof(RawInstance); - current_offset < instance_size; current_offset += kWordSize) { - *reinterpret_cast(start + current_offset) = null_value; - } - *reinterpret_cast(start + type_args_offset) = type_args; - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - SP -= 1; // Consume the type arguments on the stack. - pc += 4; - } - DISPATCH(); - } - { BYTECODE(AllocateT, 0); SP[1] = SP[-0]; // Class object. @@ -3814,46 +2424,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(CreateArrayOpt, A_B_C); - if (LIKELY(!FP[rB]->IsHeapObject())) { - const intptr_t length = Smi::Value(RAW_CAST(Smi, FP[rB])); - if (LIKELY(static_cast(length) <= Array::kMaxElements)) { - const intptr_t fixed_size_plus_alignment_padding = - sizeof(RawArray) + kObjectAlignment - 1; - const intptr_t instance_size = - (fixed_size_plus_alignment_padding + length * kWordSize) & - ~(kObjectAlignment - 1); - const uword start = thread->heap()->new_space()->TryAllocateInTLAB( - thread, instance_size); - if (LIKELY(start != 0)) { - const intptr_t cid = kArrayCid; - uword tags = 0; - if (LIKELY(instance_size <= RawObject::SizeTag::kMaxSizeTag)) { - tags = RawObject::SizeTag::update(instance_size, tags); - } - tags = RawObject::ClassIdTag::update(cid, tags); - tags = RawObject::NewBit::update(true, tags); - // Writes both the tags and the initial identity hash on 64 bit - // platforms. - *reinterpret_cast(start + Instance::tags_offset()) = tags; - *reinterpret_cast(start + Array::length_offset()) = - FP[rB]; - *reinterpret_cast( - start + Array::type_arguments_offset()) = FP[rC]; - RawObject** data = - reinterpret_cast(start + Array::data_offset()); - for (intptr_t i = 0; i < length; i++) { - data[i] = null_value; - } - FP[rA] = reinterpret_cast(start + kHeapObjectTag); - pc += 4; - } - } - } - DISPATCH(); - } - { BYTECODE(CreateArrayTOS, 0); SP[1] = SP[-0]; // Length. @@ -3865,107 +2435,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(InstanceOf, 0); - // Stack: instance, instantiator type args, function type args, type, cache - RawInstance* instance = static_cast(SP[-4]); - RawTypeArguments* instantiator_type_arguments = - static_cast(SP[-3]); - RawTypeArguments* function_type_arguments = - static_cast(SP[-2]); - RawAbstractType* type = static_cast(SP[-1]); - RawSubtypeTestCache* cache = static_cast(SP[0]); - - if (cache != null_value) { - const intptr_t cid = InterpreterHelpers::GetClassId(instance); - - RawTypeArguments* instance_type_arguments = - static_cast(null_value); - RawObject* instance_cid_or_function; - RawTypeArguments* parent_function_type_arguments; - RawTypeArguments* delayed_function_type_arguments; - if (cid == kClosureCid) { - RawClosure* closure = static_cast(instance); - instance_type_arguments = closure->ptr()->instantiator_type_arguments_; - parent_function_type_arguments = - closure->ptr()->function_type_arguments_; - delayed_function_type_arguments = - closure->ptr()->delayed_type_arguments_; - instance_cid_or_function = closure->ptr()->function_; - } else { - instance_cid_or_function = Smi::New(cid); - - RawClass* instance_class = thread->isolate()->class_table()->At(cid); - if (instance_class->ptr()->num_type_arguments_ < 0) { - goto InstanceOfCallRuntime; - } else if (instance_class->ptr()->num_type_arguments_ > 0) { - instance_type_arguments = reinterpret_cast( - instance->ptr())[instance_class->ptr() - ->type_arguments_field_offset_in_words_]; - } - parent_function_type_arguments = - static_cast(null_value); - delayed_function_type_arguments = - static_cast(null_value); - } - - for (RawObject** entries = cache->ptr()->cache_->ptr()->data(); - entries[0] != null_value; - entries += SubtypeTestCache::kTestEntryLength) { - if ((entries[SubtypeTestCache::kInstanceClassIdOrFunction] == - instance_cid_or_function) && - (entries[SubtypeTestCache::kInstanceTypeArguments] == - instance_type_arguments) && - (entries[SubtypeTestCache::kInstantiatorTypeArguments] == - instantiator_type_arguments) && - (entries[SubtypeTestCache::kFunctionTypeArguments] == - function_type_arguments) && - (entries[SubtypeTestCache::kInstanceParentFunctionTypeArguments] == - parent_function_type_arguments) && - (entries[SubtypeTestCache::kInstanceDelayedFunctionTypeArguments] == - delayed_function_type_arguments)) { - SP[-4] = entries[SubtypeTestCache::kTestResult]; - goto InstanceOfOk; - } - } - } - - // clang-format off - InstanceOfCallRuntime: - { - SP[1] = instance; - SP[2] = type; - SP[3] = instantiator_type_arguments; - SP[4] = function_type_arguments; - SP[5] = cache; - Exit(thread, FP, SP + 6, pc); - NativeArguments native_args(thread, 5, SP + 1, SP - 4); - INVOKE_RUNTIME(DRT_Instanceof, native_args); - } - // clang-format on - - InstanceOfOk: - SP -= 4; - DISPATCH(); - } - - { - BYTECODE(BadTypeError, 0); - // Stack: instance, instantiator type args, function type args, type, name - RawObject** args = SP - 4; - if (args[0] != null_value) { - SP[1] = args[0]; // instance. - SP[2] = args[4]; // name. - SP[3] = args[3]; // type. - Exit(thread, FP, SP + 4, pc); - NativeArguments native_args(thread, 3, SP + 1, SP - 4); - INVOKE_RUNTIME(DRT_BadTypeError, native_args); - UNREACHABLE(); - } - SP -= 4; - DISPATCH(); - } - { BYTECODE(AssertAssignable, A_D); // Stack: instance, type, instantiator type args, function type args, name @@ -4040,464 +2509,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(TestSmi, A_D); - intptr_t left = reinterpret_cast(RAW_CAST(Smi, FP[rA])); - intptr_t right = reinterpret_cast(RAW_CAST(Smi, FP[rD])); - if ((left & right) != 0) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(TestCids, A_D); - const intptr_t cid = InterpreterHelpers::GetClassId(FP[rA]); - const intptr_t num_cases = rD; - for (intptr_t i = 0; i < num_cases; i++) { - ASSERT(KernelBytecode::DecodeOpcode(pc[i]) == KernelBytecode::kNop); - intptr_t test_target = KernelBytecode::DecodeA(pc[i]); - intptr_t test_cid = KernelBytecode::DecodeD(pc[i]); - if (cid == test_cid) { - if (test_target != 0) { - pc += 1; // Match true. - } else { - pc += 2; // Match false. - } - break; - } - } - pc += num_cases; - DISPATCH(); - } - - { - BYTECODE(CheckSmi, 0); - intptr_t obj = reinterpret_cast(FP[rA]); - if ((obj & kSmiTagMask) == kSmiTag) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(CheckEitherNonSmi, A_D); - const intptr_t obj1 = reinterpret_cast(FP[rA]); - const intptr_t obj2 = reinterpret_cast(FP[rD]); - const intptr_t tag = (obj1 | obj2) & kSmiTagMask; - if (tag != kSmiTag) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(CheckClassId, A_D); - const intptr_t actual_cid = - reinterpret_cast(FP[rA]) >> kSmiTagSize; - const intptr_t desired_cid = rD; - pc += (actual_cid == desired_cid) ? 1 : 0; - DISPATCH(); - } - - { - BYTECODE(CheckClassIdRange, A_D); - const intptr_t actual_cid = - reinterpret_cast(FP[rA]) >> kSmiTagSize; - const uintptr_t cid_start = rD; - const uintptr_t cid_range = KernelBytecode::DecodeD(*pc); - // Unsigned comparison. Skip either just the nop or both the nop and the - // following instruction. - pc += (actual_cid - cid_start <= cid_range) ? 2 : 1; - DISPATCH(); - } - - { - BYTECODE(CheckBitTest, A_D); - const intptr_t raw_value = reinterpret_cast(FP[rA]); - const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag); - const intptr_t cid_min = KernelBytecode::DecodeD(*pc); - const intptr_t cid_mask = Smi::Value( - RAW_CAST(Smi, LOAD_CONSTANT(KernelBytecode::DecodeD(*(pc + 1))))); - if (LIKELY(!is_smi)) { - const intptr_t cid_max = Utils::HighestBit(cid_mask) + cid_min; - const intptr_t cid = InterpreterHelpers::GetClassId(FP[rA]); - // The cid is in-bounds, and the bit is set in the mask. - if ((cid >= cid_min) && (cid <= cid_max) && - ((cid_mask & (1 << (cid - cid_min))) != 0)) { - pc += 3; - } else { - pc += 2; - } - } else { - const bool may_be_smi = (rD == 1); - pc += (may_be_smi ? 3 : 2); - } - DISPATCH(); - } - - { - BYTECODE(CheckCids, A_B_C); - const intptr_t raw_value = reinterpret_cast(FP[rA]); - const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag); - const bool may_be_smi = (rB == 1); - const intptr_t cids_length = rC; - if (LIKELY(!is_smi)) { - const intptr_t cid = InterpreterHelpers::GetClassId(FP[rA]); - for (intptr_t i = 0; i < cids_length; i++) { - const intptr_t desired_cid = KernelBytecode::DecodeD(*(pc + i)); - if (cid == desired_cid) { - pc++; - break; - } - } - pc += cids_length; - } else { - pc += cids_length; - pc += (may_be_smi ? 1 : 0); - } - DISPATCH(); - } - - { - BYTECODE(CheckCidsByRange, A_B_C); - const intptr_t raw_value = reinterpret_cast(FP[rA]); - const bool is_smi = ((raw_value & kSmiTagMask) == kSmiTag); - const bool may_be_smi = (rB == 1); - const intptr_t cids_length = rC; - if (LIKELY(!is_smi)) { - const intptr_t cid = InterpreterHelpers::GetClassId(FP[rA]); - for (intptr_t i = 0; i < cids_length; i += 2) { - // Note unsigned type to get unsigned range check below. - const uintptr_t cid_start = KernelBytecode::DecodeD(*(pc + i)); - const uintptr_t cids = KernelBytecode::DecodeD(*(pc + i + 1)); - if (cid - cid_start < cids) { - pc++; - break; - } - } - pc += cids_length; - } else { - pc += cids_length; - pc += (may_be_smi ? 1 : 0); - } - DISPATCH(); - } - - { - BYTECODE(IfEqStrictTOS, 0); - SP -= 2; - if (SP[1] != SP[2]) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrictTOS, 0); - SP -= 2; - if (SP[1] == SP[2]) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfEqStrictNumTOS, 0); - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } - - SP -= 2; - if (!InterpreterHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrictNumTOS, 0); - if (thread->isolate()->single_step()) { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_SingleStepHandler, args); - } - - SP -= 2; - if (InterpreterHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfSmiLtTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) < Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfSmiLeTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) <= Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfSmiGeTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) >= Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfSmiGtTOS, 0); - RawSmi* left = Smi::RawCast(SP[-1]); - RawSmi* right = Smi::RawCast(SP[-0]); - if (!(Smi::Value(left) > Smi::Value(right))) { - pc++; - } - SP -= 2; - DISPATCH(); - } - - { - BYTECODE(IfEqStrict, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (lhs != rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrict, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (lhs == rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfLe, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs > rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfLt, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs >= rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfGe, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs < rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfGt, A_D); - const intptr_t lhs = reinterpret_cast(FP[rA]); - const intptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs <= rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfULe, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs > rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfULt, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs >= rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfUGe, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs < rhs) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfUGt, A_D); - const uintptr_t lhs = reinterpret_cast(FP[rA]); - const uintptr_t rhs = reinterpret_cast(FP[rD]); - if (lhs <= rhs) { - pc++; - } - DISPATCH(); - } - -#if defined(ARCH_IS_64_BIT) - { - BYTECODE(IfDEq, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs == rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDNe, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs != rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDLe, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs <= rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDLt, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs < rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDGe, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs >= rhs) ? 0 : 1; - DISPATCH(); - } - - { - BYTECODE(IfDGt, A_D); - const double lhs = bit_cast(FP[rA]); - const double rhs = bit_cast(FP[rD]); - pc += (lhs > rhs) ? 0 : 1; - DISPATCH(); - } -#else // defined(ARCH_IS_64_BIT) - { - BYTECODE(IfDEq, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDNe, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDLe, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDLt, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDGe, A_D); - UNREACHABLE(); - DISPATCH(); - } - - { - BYTECODE(IfDGt, A_D); - UNREACHABLE(); - DISPATCH(); - } -#endif // defined(ARCH_IS_64_BIT) - - { - BYTECODE(IfEqStrictNum, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (!InterpreterHelpers::IsStrictEqualWithNumberCheck(lhs, rhs)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeStrictNum, A_D); - RawObject* lhs = FP[rA]; - RawObject* rhs = FP[rD]; - if (InterpreterHelpers::IsStrictEqualWithNumberCheck(lhs, rhs)) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfEqNull, A); - if (FP[rA] != null_value) { - pc++; - } - DISPATCH(); - } - - { - BYTECODE(IfNeNull, A_D); - if (FP[rA] == null_value) { - pc++; - } - DISPATCH(); - } - { BYTECODE(Jump, 0); LOAD_JUMP_TARGET(); @@ -4574,21 +2585,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(LoadClassId, A_D); - const uint16_t object_reg = rD; - RawObject* obj = static_cast(FP[object_reg]); - FP[rA] = InterpreterHelpers::GetClassIdAsSmi(obj); - DISPATCH(); - } - - { - BYTECODE(LoadClassIdTOS, 0); - RawObject* obj = static_cast(SP[0]); - SP[0] = InterpreterHelpers::GetClassIdAsSmi(obj); - DISPATCH(); - } - { BYTECODE(StoreIndexedTOS, 0); SP -= 3; @@ -4601,238 +2597,6 @@ RawObject* Interpreter::Call(RawFunction* function, DISPATCH(); } - { - BYTECODE(StoreIndexed, A_B_C); - RawArray* array = RAW_CAST(Array, FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - RawObject* value = FP[rC]; - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - array->StorePointer(array->ptr()->data() + Smi::Value(index), value, - thread); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUint8, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rA], FP[rB]); - *data = Smi::Value(RAW_CAST(Smi, FP[rC])); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedExternalUint8, A_B_C); - uint8_t* array = reinterpret_cast(FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - RawSmi* value = RAW_CAST(Smi, FP[rC]); - array[Smi::Value(index)] = Smi::Value(value); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedOneByteString, A_B_C); - RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - RawSmi* value = RAW_CAST(Smi, FP[rC]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - array->ptr()->data()[Smi::Value(index)] = Smi::Value(value); - DISPATCH(); - } - - { - BYTECODE(StoreIndexedUint32, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rA], FP[rB]); - const uintptr_t value = reinterpret_cast(FP[rC]); - *reinterpret_cast(data) = static_cast(value); - DISPATCH(); - } - - { - BYTECODE(TailCall, 0); - RawCode* code = RAW_CAST(Code, SP[-0]); - RawImmutableArray* args_desc = RAW_CAST(ImmutableArray, SP[-1]); - PrepareForTailCall(code, args_desc, FP, &SP, &pc); - DISPATCH(); - } - - { - BYTECODE(TailCallOpt, A_D); - RawImmutableArray* args_desc = RAW_CAST(ImmutableArray, FP[rA]); - RawCode* code = RAW_CAST(Code, FP[rD]); - PrepareForTailCall(code, args_desc, FP, &SP, &pc); - DISPATCH(); - } - - { - BYTECODE(LoadArgDescriptor, 0); - SP++; - SP[0] = argdesc_; - DISPATCH(); - } - - { - BYTECODE(LoadArgDescriptorOpt, A); - FP[rA] = argdesc_; - DISPATCH(); - } - - { - BYTECODE(NoSuchMethod, 0); - goto ClosureNoSuchMethod; - } - - { - BYTECODE(LoadFpRelativeSlot, A_X); - RawSmi* index = RAW_CAST(Smi, SP[-0]); - const int16_t offset = rD; - SP[-0] = FP[-(Smi::Value(index) + offset)]; - DISPATCH(); - } - - { - BYTECODE(LoadFpRelativeSlotOpt, A_B_Y); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const int8_t offset = rY; - FP[rA] = FP[-(Smi::Value(index) + offset)]; - DISPATCH(); - } - - { - BYTECODE(StoreFpRelativeSlot, A_X); - RawSmi* index = RAW_CAST(Smi, SP[-1]); - const int16_t offset = rD; - FP[-(Smi::Value(index) + offset) - 0] = SP[-0]; - SP--; - DISPATCH(); - } - - { - BYTECODE(StoreFpRelativeSlotOpt, A_B_Y); - RawSmi* index = RAW_CAST(Smi, FP[rB]); - const int8_t offset = rY; - FP[-(Smi::Value(index) + offset) - 0] = FP[rA]; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedTOS, 0); - // Currently this instruction is only emitted if it's safe to do. - ASSERT(!SP[0]->IsHeapObject()); - ASSERT(SP[-1]->IsArray() || SP[-1]->IsImmutableArray()); - - const intptr_t index_scale = rA; - RawSmi* index = RAW_CAST(Smi, SP[-0]); - RawArray* array = Array::RawCast(SP[-1]); - - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - SP[-1] = array->ptr()->data()[Smi::Value(index) << index_scale]; - SP--; - DISPATCH(); - } - - { - BYTECODE(LoadIndexed, A_B_C); - RawObject* obj = FP[rB]; - ASSERT(obj->IsArray() || obj->IsImmutableArray()); - RawArray* array = reinterpret_cast(obj); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - FP[rA] = array->ptr()->data()[Smi::Value(index)]; - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUint8, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rB], FP[rC]); - FP[rA] = Smi::New(*data); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedInt8, A_B_C); - uint8_t* data = InterpreterHelpers::GetTypedData(FP[rB], FP[rC]); - FP[rA] = Smi::New(*reinterpret_cast(data)); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedUint32, A_B_C); - const uint8_t* data = InterpreterHelpers::GetTypedData(FP[rB], FP[rC]); - const uint32_t value = *reinterpret_cast(data); - FP[rA] = reinterpret_cast(value); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedInt32, A_B_C); - const uint8_t* data = InterpreterHelpers::GetTypedData(FP[rB], FP[rC]); - const int32_t value = *reinterpret_cast(data); - FP[rA] = reinterpret_cast(value); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedExternalUint8, A_B_C); - uint8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - FP[rA] = Smi::New(data[Smi::Value(index)]); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedExternalInt8, A_B_C); - int8_t* data = reinterpret_cast(FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - FP[rA] = Smi::New(data[Smi::Value(index)]); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedOneByteString, A_B_C); - RawOneByteString* array = RAW_CAST(OneByteString, FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]); - DISPATCH(); - } - - { - BYTECODE(LoadIndexedTwoByteString, A_B_C); - RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]); - RawSmi* index = RAW_CAST(Smi, FP[rC]); - ASSERT(InterpreterHelpers::CheckIndex(index, array->ptr()->length_)); - FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]); - DISPATCH(); - } - - { - BYTECODE(Deopt, A_D); - const bool is_lazy = rD == 0; - if (!Deoptimize(thread, &pc, &FP, &SP, is_lazy)) { - HANDLE_EXCEPTION; - } - DISPATCH(); - } - - { - BYTECODE(DeoptRewind, 0); - pc = reinterpret_cast(thread->resume_pc()); - if (!Deoptimize(thread, &pc, &FP, &SP, false /* eager */)) { - HANDLE_EXCEPTION; - } - { - Exit(thread, FP, SP + 1, pc); - NativeArguments args(thread, 0, NULL, NULL); - INVOKE_RUNTIME(DRT_RewindPostDeopt, args); - } - UNREACHABLE(); // DRT_RewindPostDeopt does not exit normally. - DISPATCH(); - } - - { - BYTECODE(Nop, 0); - DISPATCH(); - } - { BYTECODE(Trap, 0); UNIMPLEMENTED();