diff options
Diffstat (limited to 'src')
30 files changed, 529 insertions, 1018 deletions
diff --git a/src/assembler_arm.h b/src/assembler_arm.h index bad30238a5..20728450d8 100644 --- a/src/assembler_arm.h +++ b/src/assembler_arm.h @@ -197,6 +197,10 @@ class Assembler { public: Assembler() : buffer_() {} + InstructionSet GetInstructionSet() const { + return kArm; + } + // Data-processing instructions. void and_(Register rd, Register rn, ShifterOperand so, Condition cond = AL); diff --git a/src/assembler_x86.cc b/src/assembler_x86.cc index 78a20c0ee3..83a4f36fa8 100644 --- a/src/assembler_x86.cc +++ b/src/assembler_x86.cc @@ -44,7 +44,6 @@ void Assembler::InitializeMemoryWithBreakpoints(byte* data, size_t length) { memset(reinterpret_cast<void*>(data), Instr::kBreakPointInstruction, length); } - void Assembler::call(Register reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitUint8(0xFF); diff --git a/src/assembler_x86.h b/src/assembler_x86.h index afccc4d247..52a120236a 100644 --- a/src/assembler_x86.h +++ b/src/assembler_x86.h @@ -200,6 +200,10 @@ class Assembler { Assembler() : buffer_() {} ~Assembler() {} + InstructionSet GetInstructionSet() const { + return kX86; + } + /* * Emit Machine Instructions. */ diff --git a/src/class_linker.h b/src/class_linker.h index ad293833cf..13754db1de 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -61,6 +61,8 @@ class ClassLinker { void VisitRoots(Heap::RootVistor* root_visitor, void* arg) const; + const DexFile& FindDexFile(const DexCache* dex_cache) const; + private: ClassLinker() : classes_lock_(Mutex::Create("ClassLinker::Lock")), @@ -101,8 +103,6 @@ class ClassLinker { Class* CreateArrayClass(const StringPiece& descriptor, ClassLoader* class_loader); - const DexFile& FindDexFile(const DexCache* dex_cache) const; - DexCache* FindDexCache(const DexFile* dex_file) const; void AppendToBootClassPath(const DexFile* dex_file); diff --git a/src/common_test.h b/src/common_test.h index 685e627297..d562226427 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -277,7 +277,62 @@ static const char kStaticLeafMethodsDex[] = "AAwAAADgAAAABQAAAA4AAABwAQAABgAAAAEAAADgAQAAASAAAA0AAAAAAgAAARAAAAsAAAA4AwAA" "AiAAABYAAACuAwAAAyAAAA0AAABXBAAAACAAAAEAAAC3BAAAABAAAAEAAAD0BAAA"; -static inline DexFile* OpenDexFileBase64(const char* base64, const std::string& location) { +//class Fibonacci { +// +// static int fibonacci(int n) { +// if (n == 0) { +// return 0; +// } +// int x = 1; +// int y = 1; +// for (int i = 3; i <= n; i++) { +// int z = x + y; +// x = y; +// y = z; +// } +// return y; +// } +// +// public static void main(String[] args) { +// try { +// if (args.length == 1) { +// int x = Integer.parseInt(args[0]); +// int y = fibonacci(x); /* to warm up cache */ +// System.out.printf("fibonacci(%d)=%d\n", x, y); +// y = fibonacci(x +1); +// System.out.printf("fibonacci(%d)=%d\n", x, y); +// } +// } catch (NumberFormatException ex) {} +// } +//} +static const char kFibonacciDex[] = +"ZGV4CjAzNQBaslnMUQxaXYgC3gD9FGHjVb8cHZ60G8ckBQAAcAAAAHhWNBIAAAAAAAAAAIQEAAAa" +"AAAAcAAAAAsAAADYAAAABgAAAAQBAAABAAAATAEAAAcAAABUAQAAAgAAAIwBAABYAwAAzAEAAPoC" +"AAACAwAAEgMAABUDAAAZAwAAHQMAACoDAAAuAwAAMwMAAEoDAABfAwAAggMAAJYDAACqAwAAvgMA" +"AMsDAADOAwAA0gMAAOcDAAD8AwAABwQAABoEAAAgBAAAJQQAAC8EAAA3BAAAAgAAAAUAAAAIAAAA" +"CQAAAAoAAAALAAAADAAAAA0AAAAPAAAAEQAAABIAAAADAAAAAAAAANwCAAAEAAAAAAAAAOQCAAAH" +"AAAAAgAAAOwCAAAGAAAAAwAAANwCAAAPAAAACAAAAAAAAAAQAAAACAAAAPQCAAAHAAIAFgAAAAEA" +"BAAAAAAAAQAAABMAAAABAAUAFQAAAAIAAgAYAAAAAwABABcAAAADAAMAGQAAAAUABAAAAAAABQAA" +"AAEAAAD/////AAAAAA4AAAAAAAAAaAQAAAAAAAABAAAAAAAAAAUAAAAAAAAAAQAAAAAAAAByBAAA" +"AAAAAAEAAQAAAAAAQAQAAAEAAAAOAAAAAQABAAEAAABFBAAABAAAAHAQBgAAAA4ABQABAAAAAABK" +"BAAAEwAAABIROQQEABIADwASMAESARMBAQEwNkH6/7AC2AEBAQEjAQIBMCj4AAAIAAEAAwABAFcE" +"AABIAAAAEhEhcDMQQwASAEYABwBxEAQAAAAKAHEQAQAAAAoBYgIAABoDFAASJCNECQASBXEQBQAA" +"AAwGTQYEBRIVcRAFAAEADAFNAQQFbjADADIE2AEAAXEQAQABAAoBYgIAABoDFAASJCNECQASBXEQ" +"BQAAAAwATQAEBRIQcRAFAAEADAFNAQQAbjADADIEDgANACj+AQAAAEQAAQABAQRGAQAAAAAAAAAB" +"AAAABgAAAAIAAAAGAAkAAQAAAAoABjxpbml0PgAORmlib25hY2NpLmphdmEAAUkAAklJAAJJTAAL" +"TEZpYm9uYWNjaTsAAkxJAANMTEwAFUxqYXZhL2lvL1ByaW50U3RyZWFtOwATTGphdmEvbGFuZy9J" +"bnRlZ2VyOwAhTGphdmEvbGFuZy9OdW1iZXJGb3JtYXRFeGNlcHRpb247ABJMamF2YS9sYW5nL09i" +"amVjdDsAEkxqYXZhL2xhbmcvU3RyaW5nOwASTGphdmEvbGFuZy9TeXN0ZW07AAtPYmplY3QuamF2" +"YQABVgACVkwAE1tMamF2YS9sYW5nL09iamVjdDsAE1tMamF2YS9sYW5nL1N0cmluZzsACWZpYm9u" +"YWNjaQARZmlib25hY2NpKCVkKT0lZAoABG1haW4AA291dAAIcGFyc2VJbnQABnByaW50ZgAHdmFs" +"dWVPZgADAAcOAAEABw4ADwEABx0tJgJ7HXgcAB4BAAcdPHhLARgPaQEYERwAAAABAAaBgATMAwAA" +"AwAAgIAE4AMBCPgDAQmwBA0AAAAAAAAAAQAAAAAAAAABAAAAGgAAAHAAAAACAAAACwAAANgAAAAD" +"AAAABgAAAAQBAAAEAAAAAQAAAEwBAAAFAAAABwAAAFQBAAAGAAAAAgAAAIwBAAABIAAABAAAAMwB" +"AAABEAAABAAAANwCAAACIAAAGgAAAPoCAAADIAAABAAAAEAEAAAAIAAAAgAAAGgEAAAAEAAAAQAA" +"AIQEAAA="; + +static inline DexFile* OpenDexFileBase64(const char* base64, + const std::string& location) { CHECK(base64 != NULL); size_t length; byte* dex_bytes = DecodeBase64(base64, &length); diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h index 02b5dfa810..643e7953c8 100644 --- a/src/compiler/CompilerIR.h +++ b/src/compiler/CompilerIR.h @@ -18,6 +18,7 @@ #define ART_SRC_COMPILER_COMPILER_IR_H_ #include "codegen/Optimizer.h" +#include <vector> typedef enum RegisterClass { kCoreReg, @@ -197,8 +198,7 @@ typedef struct CompilationUnit { int totalSize; // header + code size AssemblerStatus assemblerStatus; // Success or fix and retry int assemblerRetries; - unsigned char* codeBuffer; - void* baseAddr; + std::vector<short>codeBuffer; bool printMe; bool printMeVerbose; bool hasClassLiterals; // Contains class ptrs used as literals diff --git a/src/compiler/Dalvik.h b/src/compiler/Dalvik.h index 4e93c9c47d..a9ddcd85d3 100644 --- a/src/compiler/Dalvik.h +++ b/src/compiler/Dalvik.h @@ -24,12 +24,14 @@ #include <stdint.h> #include <stdio.h> #include <assert.h> -#include "../logging.h" +#include "logging.h" +#include "object.h" +#include "thread.h" +#include "class_linker.h" +#include "dex_cache.h" +#include "utils.h" // From Common.h -#define MIN(x,y) (((x) < (y)) ? (x) : (y)) -#define MAX(x,y) (((x) > (y)) ? (x) : (y)) - typedef uint8_t u1; typedef uint16_t u2; typedef uint32_t u4; @@ -40,667 +42,27 @@ typedef int32_t s4; typedef int64_t s8; typedef unsigned long long u8; -struct Object; - -union JValue { - u1 z; - s1 b; - u2 c; - s2 s; - s4 i; - s8 j; - float f; - double d; - Object* l; -}; - - -// From libdex/DexOpcodes.h -#define kNumPackedOpcodes 0x200 -#define kPackedSwitchSignature 0x0100 -#define kSparseSwitchSignature 0x0200 -#define kArrayDataSignature 0x0300 -enum Opcode { - // BEGIN(libdex-opcode-enum); GENERATED AUTOMATICALLY BY opcode-gen - OP_NOP = 0x00, - OP_MOVE = 0x01, - OP_MOVE_FROM16 = 0x02, - OP_MOVE_16 = 0x03, - OP_MOVE_WIDE = 0x04, - OP_MOVE_WIDE_FROM16 = 0x05, - OP_MOVE_WIDE_16 = 0x06, - OP_MOVE_OBJECT = 0x07, - OP_MOVE_OBJECT_FROM16 = 0x08, - OP_MOVE_OBJECT_16 = 0x09, - OP_MOVE_RESULT = 0x0a, - OP_MOVE_RESULT_WIDE = 0x0b, - OP_MOVE_RESULT_OBJECT = 0x0c, - OP_MOVE_EXCEPTION = 0x0d, - OP_RETURN_VOID = 0x0e, - OP_RETURN = 0x0f, - OP_RETURN_WIDE = 0x10, - OP_RETURN_OBJECT = 0x11, - OP_CONST_4 = 0x12, - OP_CONST_16 = 0x13, - OP_CONST = 0x14, - OP_CONST_HIGH16 = 0x15, - OP_CONST_WIDE_16 = 0x16, - OP_CONST_WIDE_32 = 0x17, - OP_CONST_WIDE = 0x18, - OP_CONST_WIDE_HIGH16 = 0x19, - OP_CONST_STRING = 0x1a, - OP_CONST_STRING_JUMBO = 0x1b, - OP_CONST_CLASS = 0x1c, - OP_MONITOR_ENTER = 0x1d, - OP_MONITOR_EXIT = 0x1e, - OP_CHECK_CAST = 0x1f, - OP_INSTANCE_OF = 0x20, - OP_ARRAY_LENGTH = 0x21, - OP_NEW_INSTANCE = 0x22, - OP_NEW_ARRAY = 0x23, - OP_FILLED_NEW_ARRAY = 0x24, - OP_FILLED_NEW_ARRAY_RANGE = 0x25, - OP_FILL_ARRAY_DATA = 0x26, - OP_THROW = 0x27, - OP_GOTO = 0x28, - OP_GOTO_16 = 0x29, - OP_GOTO_32 = 0x2a, - OP_PACKED_SWITCH = 0x2b, - OP_SPARSE_SWITCH = 0x2c, - OP_CMPL_FLOAT = 0x2d, - OP_CMPG_FLOAT = 0x2e, - OP_CMPL_DOUBLE = 0x2f, - OP_CMPG_DOUBLE = 0x30, - OP_CMP_LONG = 0x31, - OP_IF_EQ = 0x32, - OP_IF_NE = 0x33, - OP_IF_LT = 0x34, - OP_IF_GE = 0x35, - OP_IF_GT = 0x36, - OP_IF_LE = 0x37, - OP_IF_EQZ = 0x38, - OP_IF_NEZ = 0x39, - OP_IF_LTZ = 0x3a, - OP_IF_GEZ = 0x3b, - OP_IF_GTZ = 0x3c, - OP_IF_LEZ = 0x3d, - OP_UNUSED_3E = 0x3e, - OP_UNUSED_3F = 0x3f, - OP_UNUSED_40 = 0x40, - OP_UNUSED_41 = 0x41, - OP_UNUSED_42 = 0x42, - OP_UNUSED_43 = 0x43, - OP_AGET = 0x44, - OP_AGET_WIDE = 0x45, - OP_AGET_OBJECT = 0x46, - OP_AGET_BOOLEAN = 0x47, - OP_AGET_BYTE = 0x48, - OP_AGET_CHAR = 0x49, - OP_AGET_SHORT = 0x4a, - OP_APUT = 0x4b, - OP_APUT_WIDE = 0x4c, - OP_APUT_OBJECT = 0x4d, - OP_APUT_BOOLEAN = 0x4e, - OP_APUT_BYTE = 0x4f, - OP_APUT_CHAR = 0x50, - OP_APUT_SHORT = 0x51, - OP_IGET = 0x52, - OP_IGET_WIDE = 0x53, - OP_IGET_OBJECT = 0x54, - OP_IGET_BOOLEAN = 0x55, - OP_IGET_BYTE = 0x56, - OP_IGET_CHAR = 0x57, - OP_IGET_SHORT = 0x58, - OP_IPUT = 0x59, - OP_IPUT_WIDE = 0x5a, - OP_IPUT_OBJECT = 0x5b, - OP_IPUT_BOOLEAN = 0x5c, - OP_IPUT_BYTE = 0x5d, - OP_IPUT_CHAR = 0x5e, - OP_IPUT_SHORT = 0x5f, - OP_SGET = 0x60, - OP_SGET_WIDE = 0x61, - OP_SGET_OBJECT = 0x62, - OP_SGET_BOOLEAN = 0x63, - OP_SGET_BYTE = 0x64, - OP_SGET_CHAR = 0x65, - OP_SGET_SHORT = 0x66, - OP_SPUT = 0x67, - OP_SPUT_WIDE = 0x68, - OP_SPUT_OBJECT = 0x69, - OP_SPUT_BOOLEAN = 0x6a, - OP_SPUT_BYTE = 0x6b, - OP_SPUT_CHAR = 0x6c, - OP_SPUT_SHORT = 0x6d, - OP_INVOKE_VIRTUAL = 0x6e, - OP_INVOKE_SUPER = 0x6f, - OP_INVOKE_DIRECT = 0x70, - OP_INVOKE_STATIC = 0x71, - OP_INVOKE_INTERFACE = 0x72, - OP_UNUSED_73 = 0x73, - OP_INVOKE_VIRTUAL_RANGE = 0x74, - OP_INVOKE_SUPER_RANGE = 0x75, - OP_INVOKE_DIRECT_RANGE = 0x76, - OP_INVOKE_STATIC_RANGE = 0x77, - OP_INVOKE_INTERFACE_RANGE = 0x78, - OP_UNUSED_79 = 0x79, - OP_UNUSED_7A = 0x7a, - OP_NEG_INT = 0x7b, - OP_NOT_INT = 0x7c, - OP_NEG_LONG = 0x7d, - OP_NOT_LONG = 0x7e, - OP_NEG_FLOAT = 0x7f, - OP_NEG_DOUBLE = 0x80, - OP_INT_TO_LONG = 0x81, - OP_INT_TO_FLOAT = 0x82, - OP_INT_TO_DOUBLE = 0x83, - OP_LONG_TO_INT = 0x84, - OP_LONG_TO_FLOAT = 0x85, - OP_LONG_TO_DOUBLE = 0x86, - OP_FLOAT_TO_INT = 0x87, - OP_FLOAT_TO_LONG = 0x88, - OP_FLOAT_TO_DOUBLE = 0x89, - OP_DOUBLE_TO_INT = 0x8a, - OP_DOUBLE_TO_LONG = 0x8b, - OP_DOUBLE_TO_FLOAT = 0x8c, - OP_INT_TO_BYTE = 0x8d, - OP_INT_TO_CHAR = 0x8e, - OP_INT_TO_SHORT = 0x8f, - OP_ADD_INT = 0x90, - OP_SUB_INT = 0x91, - OP_MUL_INT = 0x92, - OP_DIV_INT = 0x93, - OP_REM_INT = 0x94, - OP_AND_INT = 0x95, - OP_OR_INT = 0x96, - OP_XOR_INT = 0x97, - OP_SHL_INT = 0x98, - OP_SHR_INT = 0x99, - OP_USHR_INT = 0x9a, - OP_ADD_LONG = 0x9b, - OP_SUB_LONG = 0x9c, - OP_MUL_LONG = 0x9d, - OP_DIV_LONG = 0x9e, - OP_REM_LONG = 0x9f, - OP_AND_LONG = 0xa0, - OP_OR_LONG = 0xa1, - OP_XOR_LONG = 0xa2, - OP_SHL_LONG = 0xa3, - OP_SHR_LONG = 0xa4, - OP_USHR_LONG = 0xa5, - OP_ADD_FLOAT = 0xa6, - OP_SUB_FLOAT = 0xa7, - OP_MUL_FLOAT = 0xa8, - OP_DIV_FLOAT = 0xa9, - OP_REM_FLOAT = 0xaa, - OP_ADD_DOUBLE = 0xab, - OP_SUB_DOUBLE = 0xac, - OP_MUL_DOUBLE = 0xad, - OP_DIV_DOUBLE = 0xae, - OP_REM_DOUBLE = 0xaf, - OP_ADD_INT_2ADDR = 0xb0, - OP_SUB_INT_2ADDR = 0xb1, - OP_MUL_INT_2ADDR = 0xb2, - OP_DIV_INT_2ADDR = 0xb3, - OP_REM_INT_2ADDR = 0xb4, - OP_AND_INT_2ADDR = 0xb5, - OP_OR_INT_2ADDR = 0xb6, - OP_XOR_INT_2ADDR = 0xb7, - OP_SHL_INT_2ADDR = 0xb8, - OP_SHR_INT_2ADDR = 0xb9, - OP_USHR_INT_2ADDR = 0xba, - OP_ADD_LONG_2ADDR = 0xbb, - OP_SUB_LONG_2ADDR = 0xbc, - OP_MUL_LONG_2ADDR = 0xbd, - OP_DIV_LONG_2ADDR = 0xbe, - OP_REM_LONG_2ADDR = 0xbf, - OP_AND_LONG_2ADDR = 0xc0, - OP_OR_LONG_2ADDR = 0xc1, - OP_XOR_LONG_2ADDR = 0xc2, - OP_SHL_LONG_2ADDR = 0xc3, - OP_SHR_LONG_2ADDR = 0xc4, - OP_USHR_LONG_2ADDR = 0xc5, - OP_ADD_FLOAT_2ADDR = 0xc6, - OP_SUB_FLOAT_2ADDR = 0xc7, - OP_MUL_FLOAT_2ADDR = 0xc8, - OP_DIV_FLOAT_2ADDR = 0xc9, - OP_REM_FLOAT_2ADDR = 0xca, - OP_ADD_DOUBLE_2ADDR = 0xcb, - OP_SUB_DOUBLE_2ADDR = 0xcc, - OP_MUL_DOUBLE_2ADDR = 0xcd, - OP_DIV_DOUBLE_2ADDR = 0xce, - OP_REM_DOUBLE_2ADDR = 0xcf, - OP_ADD_INT_LIT16 = 0xd0, - OP_RSUB_INT = 0xd1, - OP_MUL_INT_LIT16 = 0xd2, - OP_DIV_INT_LIT16 = 0xd3, - OP_REM_INT_LIT16 = 0xd4, - OP_AND_INT_LIT16 = 0xd5, - OP_OR_INT_LIT16 = 0xd6, - OP_XOR_INT_LIT16 = 0xd7, - OP_ADD_INT_LIT8 = 0xd8, - OP_RSUB_INT_LIT8 = 0xd9, - OP_MUL_INT_LIT8 = 0xda, - OP_DIV_INT_LIT8 = 0xdb, - OP_REM_INT_LIT8 = 0xdc, - OP_AND_INT_LIT8 = 0xdd, - OP_OR_INT_LIT8 = 0xde, - OP_XOR_INT_LIT8 = 0xdf, - OP_SHL_INT_LIT8 = 0xe0, - OP_SHR_INT_LIT8 = 0xe1, - OP_USHR_INT_LIT8 = 0xe2, - OP_IGET_VOLATILE = 0xe3, - OP_IPUT_VOLATILE = 0xe4, - OP_SGET_VOLATILE = 0xe5, - OP_SPUT_VOLATILE = 0xe6, - OP_IGET_OBJECT_VOLATILE = 0xe7, - OP_IGET_WIDE_VOLATILE = 0xe8, - OP_IPUT_WIDE_VOLATILE = 0xe9, - OP_SGET_WIDE_VOLATILE = 0xea, - OP_SPUT_WIDE_VOLATILE = 0xeb, - OP_BREAKPOINT = 0xec, - OP_THROW_VERIFICATION_ERROR = 0xed, - OP_EXECUTE_INLINE = 0xee, - OP_EXECUTE_INLINE_RANGE = 0xef, - OP_INVOKE_OBJECT_INIT_RANGE = 0xf0, - OP_RETURN_VOID_BARRIER = 0xf1, - OP_IGET_QUICK = 0xf2, - OP_IGET_WIDE_QUICK = 0xf3, - OP_IGET_OBJECT_QUICK = 0xf4, - OP_IPUT_QUICK = 0xf5, - OP_IPUT_WIDE_QUICK = 0xf6, - OP_IPUT_OBJECT_QUICK = 0xf7, - OP_INVOKE_VIRTUAL_QUICK = 0xf8, - OP_INVOKE_VIRTUAL_QUICK_RANGE = 0xf9, - OP_INVOKE_SUPER_QUICK = 0xfa, - OP_INVOKE_SUPER_QUICK_RANGE = 0xfb, - OP_IPUT_OBJECT_VOLATILE = 0xfc, - OP_SGET_OBJECT_VOLATILE = 0xfd, - OP_SPUT_OBJECT_VOLATILE = 0xfe, -}; +//Skip old DexFile.h +#define LIBDEX_DEXFILE_H_ +//Skip old vm/Common.h +#define DALVIK_COMMON_H_ +//Make inlines inline +#define DEX_INLINE inline +#include "DexOpcodes.h" +#include "InstrUtils.h" + +typedef art::JValue JValue; +typedef art::Thread Thread; +typedef art::Class Class; +typedef art::Array Array; +typedef art::Method Method; +typedef art::Object Object; +typedef art::Field Field; +typedef art::String String; // From alloc/CardTable.h #define GC_CARD_SHIFT 7 -// From all/Alloc.h -/* flags for dvmMalloc */ -enum { - ALLOC_DEFAULT = 0x00, - ALLOC_DONT_TRACK = 0x01, /* don't add to internal tracking list */ - ALLOC_NON_MOVING = 0x02, -}; - - -// From oo/Object.h -struct ClassObject; -struct ArrayObject; -struct DvmDex; -struct Method; - -struct Object { - ClassObject* clazz; - u4 lock; - Method** vtable; - int vtableCount; - u4 accessFlags; -}; - -struct ArrayObject : Object { - u4 length; - u8 contents[1]; -}; - -struct ClassObject : Object { - const char* descriptor; - DvmDex* pDvmDex; - ClassObject* super; -}; - -// From InstrUtils.h -enum InstructionFormat { - kFmt00x = 0, // unknown format (also used for "breakpoint" opcode) - kFmt10x, // op - kFmt12x, // op vA, vB - kFmt11n, // op vA, #+B - kFmt11x, // op vAA - kFmt10t, // op +AA - kFmt20bc, // [opt] op AA, thing@BBBB - kFmt20t, // op +AAAA - kFmt22x, // op vAA, vBBBB - kFmt21t, // op vAA, +BBBB - kFmt21s, // op vAA, #+BBBB - kFmt21h, // op vAA, #+BBBB00000[00000000] - kFmt21c, // op vAA, thing@BBBB - kFmt23x, // op vAA, vBB, vCC - kFmt22b, // op vAA, vBB, #+CC - kFmt22t, // op vA, vB, +CCCC - kFmt22s, // op vA, vB, #+CCCC - kFmt22c, // op vA, vB, thing@CCCC - kFmt22cs, // [opt] op vA, vB, field offset CCCC - kFmt30t, // op +AAAAAAAA - kFmt32x, // op vAAAA, vBBBB - kFmt31i, // op vAA, #+BBBBBBBB - kFmt31t, // op vAA, +BBBBBBBB - kFmt31c, // op vAA, string@BBBBBBBB - kFmt35c, // op {vC,vD,vE,vF,vG}, thing@BBBB - kFmt35ms, // [opt] invoke-virtual+super - kFmt3rc, // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB - kFmt3rms, // [opt] invoke-virtual+super/range - kFmt51l, // op vAA, #+BBBBBBBBBBBBBBBB - kFmt35mi, // [opt] inline invoke - kFmt3rmi, // [opt] inline invoke/range - kFmt33x, // exop vAA, vBB, vCCCC - kFmt32s, // exop vAA, vBB, #+CCCC - kFmt40sc, // [opt] exop AAAA, thing@BBBBBBBB - kFmt41c, // exop vAAAA, thing@BBBBBBBB - kFmt52c, // exop vAAAA, vBBBB, thing@CCCCCCCC - kFmt5rc, // exop {vCCCC .. v(CCCC+AAAA-1)}, thing@BBBBBBBB -}; - -enum InstructionIndexType { - kIndexUnknown = 0, - kIndexNone, // has no index - kIndexVaries, // "It depends." Used for throw-verification-error - kIndexTypeRef, // type reference index - kIndexStringRef, // string reference index - kIndexMethodRef, // method reference index - kIndexFieldRef, // field reference index - kIndexInlineMethod, // inline method index (for inline linked methods) - kIndexVtableOffset, // vtable offset (for static linked methods) - kIndexFieldOffset // field offset (for static linked fields) -}; - -typedef u1 InstructionWidth; - -typedef u1 OpcodeFlags; -enum OpcodeFlagsBits { - kInstrCanBranch = 1, // conditional or unconditional branch - kInstrCanContinue = 1 << 1, // flow can continue to next statement - kInstrCanSwitch = 1 << 2, // switch statement - kInstrCanThrow = 1 << 3, // could cause an exception to be thrown - kInstrCanReturn = 1 << 4, // returns, no additional statements - kInstrInvoke = 1 << 5, // a flavor of invoke -}; - -struct InstructionInfoTables { - u1* formats; /* InstructionFormat elements */ - u1* indexTypes; /* InstructionIndexType elements */ - OpcodeFlags* flags; - InstructionWidth* widths; -}; - -extern InstructionInfoTables gDexOpcodeInfo; - -struct DecodedInstruction { - u4 vA; - u4 vB; - u8 vB_wide; /* for kFmt51l */ - u4 vC; - u4 arg[5]; /* vC/D/E/F/G in invoke or filled-new-array */ - Opcode opcode; - InstructionIndexType indexType; -}; - -#define DEX_INLINE inline -#define INLINE inline - -DEX_INLINE size_t dexGetWidthFromOpcode(Opcode opcode) -{ - assert((u4) opcode < kNumPackedOpcodes); - return gDexOpcodeInfo.widths[opcode]; -} - -size_t dexGetWidthFromInstruction(const u2* insns); - -DEX_INLINE OpcodeFlags dexGetFlagsFromOpcode(Opcode opcode) -{ - assert((u4) opcode < kNumPackedOpcodes); - return gDexOpcodeInfo.flags[opcode]; -} - -DEX_INLINE bool dexIsGoto(OpcodeFlags flags) -{ - return (flags & (kInstrCanBranch | kInstrCanContinue)) == kInstrCanBranch; -} - -DEX_INLINE InstructionFormat dexGetFormatFromOpcode(Opcode opcode) -{ - assert((u4) opcode < kNumPackedOpcodes); - return (InstructionFormat) gDexOpcodeInfo.formats[opcode]; -} - -DEX_INLINE InstructionIndexType dexGetIndexTypeFromOpcode(Opcode opcode) -{ - assert((u4) opcode < kNumPackedOpcodes); - return (InstructionIndexType) gDexOpcodeInfo.indexTypes[opcode]; -} - -void dexDecodeInstruction(const u2* insns, DecodedInstruction* pDec); - -// From DexOpcodes -const char* dexGetOpcodeName(Opcode op); - -DEX_INLINE Opcode dexOpcodeFromCodeUnit(u2 codeUnit) { - int lowByte = codeUnit & 0xff; - if (lowByte != 0xff) { - return (Opcode) lowByte; - } else { - return (Opcode) ((codeUnit >> 8) | 0x100); - } -} - -// From DexFile -struct DexFile; -struct DexTry { - u4 startAddr; /* start address, in 16-bit code units */ - u2 insnCount; /* instruction count, in 16-bit code units */ - u2 handlerOff; /* offset in encoded handler data to handlers */ -}; -struct DexCode { - u2 registersSize; - u2 insSize; - u2 outsSize; - u2 triesSize; - u4 debugInfoOff; /* file offset to debug info stream */ - u4 insnsSize; /* size of the insns array, in u2 units */ - u2 insns[1]; -}; - -DEX_INLINE const DexTry* dexGetTries(const DexCode* pCode) { - const u2* insnsEnd = &pCode->insns[pCode->insnsSize]; - - // Round to four bytes. - if ((((u4) insnsEnd) & 3) != 0) { - insnsEnd++; - } - - return (const DexTry*) insnsEnd; -} - -enum { - ACC_PUBLIC = 0x00000001, // class, field, method, ic - ACC_PRIVATE = 0x00000002, // field, method, ic - ACC_PROTECTED = 0x00000004, // field, method, ic - ACC_STATIC = 0x00000008, // field, method, ic - ACC_FINAL = 0x00000010, // class, field, method, ic - ACC_SYNCHRONIZED = 0x00000020, // method (only allowed on natives) - ACC_SUPER = 0x00000020, // class (not used in Dalvik) - ACC_VOLATILE = 0x00000040, // field - ACC_BRIDGE = 0x00000040, // method (1.5) - ACC_TRANSIENT = 0x00000080, // field - ACC_VARARGS = 0x00000080, // method (1.5) - ACC_NATIVE = 0x00000100, // method - ACC_INTERFACE = 0x00000200, // class, ic - ACC_ABSTRACT = 0x00000400, // class, method, ic - ACC_STRICT = 0x00000800, // method - ACC_SYNTHETIC = 0x00001000, // field, method, ic - ACC_ANNOTATION = 0x00002000, // class, ic (1.5) - ACC_ENUM = 0x00004000, // class, field, ic (1.5) - ACC_CONSTRUCTOR = 0x00010000, // method (Dalvik only) - ACC_DECLARED_SYNCHRONIZED = - 0x00020000, // method (Dalvik only) - ACC_CLASS_MASK = - (ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT - | ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM), - ACC_INNER_CLASS_MASK = - (ACC_CLASS_MASK | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC), - ACC_FIELD_MASK = - (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL - | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM), - ACC_METHOD_MASK = - (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL - | ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE - | ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR - | ACC_DECLARED_SYNCHRONIZED), -}; - -// From DexProto -struct DexProto { - const DexFile* dexFile; /* file the idx refers to */ - u4 protoIdx; /* index into proto_ids table of dexFile */ -}; -char* dexProtoCopyMethodDescriptor(const DexProto* pProto); - -// From DexCatch.h -struct DexCatchHandler { - u4 typeIdx; /* type index of the caught exception type */ - u4 address; /* handler address */ -}; -struct DexCatchIterator { - const u1* pEncodedData; - bool catchesAll; - u4 countRemaining; - DexCatchHandler handler; -}; -bool dexFindCatchHandler(DexCatchIterator *pIterator, - const DexCode* pCode, u4 address); -DexCatchHandler* dexCatchIteratorNext(DexCatchIterator* pIterator); -u4 dexGetFirstHandlerOffset(const DexCode* pCode); -u4 dexGetHandlersSize(const DexCode* pCode); -u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator, - const DexCode* pCode); -void dexCatchIteratorInit(DexCatchIterator* pIterator, - const DexCode* pCode, u4 offset); - - - -// From DvmDex.h -struct Field; -struct StringObject; -struct DvmDex { - struct Method** pResMethods; - struct ClassObject** pResClasses; - struct Field** pResFields; - struct StringObject** pResStrings; -}; - -// from oo/Object.h -struct Method { - ClassObject* clazz; - u2 methodIndex; - u2 registersSize; - u2 outsSize; - u2 insSize; - u4 accessFlags; - const char* name; - const char* shorty; - DexProto prototype; - void* compiledInsns; - DvmDex* pDvmDex; - u2* insns; - struct Method** pResMethods; -}; - -struct Field { - ClassObject* clazz; /* class in which the field is declared */ - const char* name; - const char* signature; /* e.g. "I", "[C", "Landroid/os/Debug;" */ - u4 accessFlags; -}; - -struct InstField : Field { - int byteOffset; -}; -/* - * Static field. - */ -struct StaticField : Field { - JValue value; /* initially set from DEX for primitives */ -}; - -INLINE bool dvmIsVolatileField(const Field* field) { - return (field->accessFlags & ACC_VOLATILE) != 0; -} - -INLINE bool dvmIsBytecodeMethod(const Method* method) { - return (method->accessFlags & (ACC_NATIVE | ACC_ABSTRACT)) == 0; -} - -INLINE const DexCode* dvmGetMethodCode(const Method* meth) { - if (dvmIsBytecodeMethod(meth)) { - return (const DexCode*) - (((const u1*) meth->insns) - offsetof(DexCode, insns)); - } else { - return NULL; - } -} - -// From Thread.h -struct Thread { - - u4 threadId; - u1* cardTable; - Object* exception; - - /* Runtime support function pointers */ - void* (*pMemcpy)(void*, const void*, size_t); - float (*pI2f)(int); - int (*pF2iz)(float); - float (*pD2f)(double); - double (*pF2d)(float); - double (*pI2d)(int); - int (*pD2iz)(double); - float (*pL2f)(long); - double (*pL2d)(long); - s8 (*pArtF2l)(float); - s8 (*pArtD2l)(double); - float (*pFadd)(float, float); - float (*pFsub)(float, float); - float (*pFdiv)(float, float); - float (*pFmul)(float, float); - float (*pFmodf)(float, float); - double (*pDadd)(double, double); - double (*pDsub)(double, double); - double (*pDdiv)(double, double); - double (*pDmul)(double, double); - double (*pFmod)(double, double); - int (*pIdivmod)(int, int); - int (*pIdiv)(int, int); - long long (*pLdivmod)(long long, long long); - bool (*pArtUnlockObject)(struct Thread*, struct Object*); - bool (*pArtCanPutArrayElementNoThrow)(const ClassObject*, - const ClassObject*); - int (*pArtInstanceofNonTrivialNoThrow) - (const ClassObject*, const ClassObject*); - int (*pArtInstanceofNonTrivial) (const ClassObject*, const ClassObject*); - ArrayObject* (*pArtAllocArrayByClass)(ClassObject*, size_t, int); - Method* (*pArtFindInterfaceMethodInCache)(ClassObject*, u4, const Method*, - DvmDex*); - bool (*pArtUnlockObjectNoThrow)(Thread*, Object*); - void (*pArtLockObjectNoThrow)(Thread*, Object*); - Object* (*pArtAllocObjectNoThrow)(ClassObject*, int); - void (*pArtThrowException)(Thread*, Object*); - bool (*pArtHandleFillArrayDataNoThrow)(ArrayObject*, const u2*); - -}; - -// From Sync.h -#define LW_LOCK_OWNER_SHIFT 3 -#define LW_HASH_STATE_SHIFT 1 -#define LW_HASH_STATE_MASK 0x3 -#define LW_SHAPE_THIN 0 - - #include "Compiler.h" #endif diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc index 41bf8bc110..5cfddc0546 100644 --- a/src/compiler/Dataflow.cc +++ b/src/compiler/Dataflow.cc @@ -2092,11 +2092,11 @@ bool oatDoSSAConversion(CompilationUnit* cUnit, BasicBlock* bb) * blocks. */ bb->dataFlowInfo->dalvikToSSAMap = - (int *)oatNew(sizeof(int) * cUnit->method->registersSize, + (int *)oatNew(sizeof(int) * cUnit->method->num_registers_, false); memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap, - sizeof(int) * cUnit->method->registersSize); + sizeof(int) * cUnit->method->num_registers_); return true; } @@ -2184,7 +2184,7 @@ bool oatDoConstantPropagation(CompilationUnit* cUnit, BasicBlock* bb) void oatInitializeSSAConversion(CompilationUnit* cUnit) { int i; - int numDalvikReg = cUnit->method->registersSize; + int numDalvikReg = cUnit->method->num_registers_; cUnit->ssaToDalvikMap = (GrowableList *)oatNew(sizeof(GrowableList), false); diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc index b5d4e3f7f1..7d38faaec6 100644 --- a/src/compiler/Frontend.cc +++ b/src/compiler/Frontend.cc @@ -17,6 +17,7 @@ #include "Dalvik.h" #include "CompilerInternals.h" #include "Dataflow.h" +#include "constants.h" static inline bool contentIsInsn(const u2* codePtr) { u2 instr = *codePtr; @@ -185,21 +186,15 @@ static BasicBlock *findBlock(CompilationUnit* cUnit, /* Dump the CFG into a DOT graph */ void oatDumpCFG(CompilationUnit* cUnit, const char* dirPrefix) { - const Method* method = cUnit->method; FILE* file; - char* signature = dexProtoCopyMethodDescriptor(&method->prototype); + std::string name = art::PrettyMethod(cUnit->method, true); char startOffset[80]; sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset); char* fileName = (char *) oatNew( - strlen(dirPrefix) + - strlen(method->clazz->descriptor) + - strlen(method->name) + - strlen(signature) + - strlen(startOffset) + - strlen(".dot") + 1, true); - sprintf(fileName, "%s%s%s%s%s.dot", dirPrefix, - method->clazz->descriptor, method->name, signature, startOffset); - free(signature); + strlen(dirPrefix) + + name.length() + + strlen(".dot") + 1, true); + sprintf(fileName, "%s%s%s.dot", dirPrefix, name.c_str(), startOffset); /* * Convert the special characters into a filesystem- and shell-friendly @@ -397,6 +392,9 @@ static bool verifyPredInfo(CompilationUnit* cUnit, BasicBlock* bb) /* Identify code range in try blocks and set up the empty catch blocks */ static void processTryCatchBlocks(CompilationUnit* cUnit) { + + UNIMPLEMENTED(WARNING) << "Need to finish processTryCatchBlocks()"; +#if 0 const Method* meth = cUnit->method; const DexCode *pCode = dvmGetMethodCode(meth); int triesSize = pCode->triesSize; @@ -450,6 +448,7 @@ static void processTryCatchBlocks(CompilationUnit* cUnit) offset = dexCatchIteratorGetEndOffset(&iterator, pCode); } +#endif } /* Process instructions with the kInstrCanBranch flag */ @@ -612,6 +611,8 @@ static void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, ArenaBitVector* tryBlockAddr, const u2* codePtr, const u2* codeEnd) { + UNIMPLEMENTED(WARNING) << "Need to complete processCanThrow"; +#if 0 const Method* method = cUnit->method; const DexCode* dexCode = dvmGetMethodCode(method); @@ -688,17 +689,22 @@ static void processCanThrow(CompilationUnit* cUnit, BasicBlock* curBlock, } } } +#endif } /* * Compile a method. */ -bool oatCompileMethod(Method* method, OatInstructionSetType insnSet) +bool oatCompileMethod(Method* method, art::InstructionSet insnSet) { CompilationUnit cUnit; - const DexCode* dexCode = dvmGetMethodCode(method); - const u2* codePtr = dexCode->insns; - const u2* codeEnd = dexCode->insns + dexCode->insnsSize; + art::ClassLinker* class_linker = art::Runtime::Current()->GetClassLinker(); + const art::DexFile& dex_file = class_linker->FindDexFile( + method->GetDeclaringClass()->GetDexCache()); + const art::DexFile::CodeItem* code_item = + dex_file.GetCodeItem(method->code_off_); + const u2* codePtr = code_item->insns_; + const u2* codeEnd = code_item->insns_ + code_item->insns_size_; int numBlocks = 0; unsigned int curOffset = 0; @@ -709,9 +715,9 @@ bool oatCompileMethod(Method* method, OatInstructionSetType insnSet) memset(&cUnit, 0, sizeof(cUnit)); cUnit.method = method; - cUnit.instructionSet = insnSet; - cUnit.insns = dexCode->insns; - cUnit.insnsSize = dexCode->insnsSize; + cUnit.instructionSet = (OatInstructionSetType)insnSet; + cUnit.insns = code_item->insns_; + cUnit.insnsSize = code_item->insns_size_; #if 1 cUnit.printMe = true; cUnit.printMeVerbose = true; @@ -842,7 +848,7 @@ bool oatCompileMethod(Method* method, OatInstructionSetType insnSet) } /* Adjust this value accordingly once inlining is performed */ - cUnit.numDalvikRegisters = cUnit.method->registersSize; + cUnit.numDalvikRegisters = cUnit.method->num_registers_; /* Verify if all blocks are connected as claimed */ @@ -880,8 +886,12 @@ bool oatCompileMethod(Method* method, OatInstructionSetType insnSet) } } - method->compiledInsns = (void*)((int)cUnit.baseAddr | 1); - method->pResMethods = method->clazz->pDvmDex->pResMethods; + method->SetCode((const art::byte*)&cUnit.codeBuffer[0], + cUnit.codeBuffer.size() * 2, art::kThumb2); + method->SetFrameSize(cUnit.frameSize); + method->SetCoreSpillMask(cUnit.coreSpillMask); + method->SetFpSpillMask(cUnit.fpSpillMask); + // TODO: Transmit mapping table to caller #if 0 oatDumpCFG(&cUnit, "/sdcard/cfg/"); diff --git a/src/compiler/HackStubs.cc b/src/compiler/HackStubs.cc deleted file mode 100644 index 9bdd73304a..0000000000 --- a/src/compiler/HackStubs.cc +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "Dalvik.h" - -/* Hacky stubs for old-word functionality */ -InstructionInfoTables gDexOpcodeInfo; - -const char* dexGetOpcodeName(Opcode op) { return NULL; } - -void dexDecodeInstruction(unsigned short const* insns, - DecodedInstruction* pDec) {} - -char* dexProtoCopyMethodDescriptor(DexProto const* gProto) {return NULL;} - -u4 dexGetFirstHandlerOffset(DexCode const* pCode) { return 0; } - -u4 dexGetHandlersSize(DexCode const* pCode) { return 0; } - -void dexCatchIteratorInit(DexCatchIterator* pIterator, - DexCode const* pCode, unsigned int offset) {} - -DexCatchHandler* dexCatchIteratorNext(DexCatchIterator* pCode) { return NULL; } - -u4 dexCatchIteratorGetEndOffset(DexCatchIterator* pIterator, - DexCode const* pCode) { return 0; } - -bool dexFindCatchHandler(DexCatchIterator* pIterator, DexCode const* pCode, - unsigned int address) { return false; } diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc index dbc93b9bb6..c8b7632931 100644 --- a/src/compiler/Ralloc.cc +++ b/src/compiler/Ralloc.cc @@ -119,9 +119,9 @@ void oatSimpleRegAlloc(CompilationUnit* cUnit) } /* Figure out the frame size */ - cUnit->numIns = cUnit->method->insSize; - cUnit->numRegs = cUnit->method->registersSize - cUnit->numIns; - cUnit->numOuts = cUnit->method->outsSize; + cUnit->numIns = cUnit->method->num_ins_; + cUnit->numRegs = cUnit->method->num_registers_ - cUnit->numIns; + cUnit->numOuts = cUnit->method->num_outs_; cUnit->numPadding = (STACK_ALIGN_WORDS - (cUnit->numSpills + cUnit->numRegs + cUnit->numOuts + 2)) & (STACK_ALIGN_WORDS-1); diff --git a/src/compiler/SSATransformation.cc b/src/compiler/SSATransformation.cc index a843d51452..42e855de29 100644 --- a/src/compiler/SSATransformation.cc +++ b/src/compiler/SSATransformation.cc @@ -107,8 +107,8 @@ static void computeDefBlockMatrix(CompilationUnit* cUnit) * Also set the incoming parameters as defs in the entry block. * Only need to handle the parameters for the outer method. */ - int inReg = cUnit->method->registersSize - cUnit->method->insSize; - for (; inReg < cUnit->method->registersSize; inReg++) { + int inReg = cUnit->method->num_registers_ - cUnit->method->num_ins_; + for (; inReg < cUnit->method->num_registers_; inReg++) { oatSetBit(cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id); } diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc index b4dd80c7bd..9c010b53b1 100644 --- a/src/compiler/Utility.cc +++ b/src/compiler/Utility.cc @@ -164,8 +164,7 @@ void oatDumpCompilationUnit(CompilationUnit* cUnit) "Catch Block" }; - LOG(INFO) << "Compiling " << cUnit->method->clazz->descriptor << " " << - cUnit->method->name; + LOG(INFO) << "Compiling " << art::PrettyMethod(cUnit->method, true); LOG(INFO) << cUnit->insns << " insns"; LOG(INFO) << cUnit->numBlocks << " blocks in total"; GrowableListIterator iterator; diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc index 16a0200f71..2f3af44c16 100644 --- a/src/compiler/codegen/arm/ArchUtility.cc +++ b/src/compiler/codegen/arm/ArchUtility.cc @@ -318,8 +318,7 @@ void oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr) switch(lir->opcode) { case kArmPseudoMethodEntry: LOG(INFO) << "-------- method entry " << - cUnit->method->clazz->descriptor << ":" << - cUnit->method->name; + art::PrettyMethod(cUnit->method, true); break; case kArmPseudoMethodExit: LOG(INFO) << "-------- Method_Exit"; @@ -390,8 +389,8 @@ void oatCodegenDump(CompilationUnit* cUnit) { const Method *method = cUnit->method; LOG(INFO) << "/*"; - LOG(INFO) << "Dumping LIR insns for " << method->clazz->descriptor << - ":" << method->name; + LOG(INFO) << "Dumping LIR insns for " << + art::PrettyMethod(cUnit->method, true); LIR* lirInsn; ArmLIR* armLIR; int insnsSize = cUnit->insnsSize; @@ -408,7 +407,7 @@ void oatCodegenDump(CompilationUnit* cUnit) " bytes, Dalvik size is " << insnsSize * 2; LOG(INFO) << "expansion factor: " << (float)cUnit->totalSize / (float)(insnsSize * 2); - for (int i = 0; i < method->registersSize; i++) { + for (int i = 0; i < method->num_registers_; i++) { RegLocation loc = cUnit->regLocation[i]; char buf[100]; if (loc.fpLocation == kLocPhysReg) { @@ -425,41 +424,42 @@ void oatCodegenDump(CompilationUnit* cUnit) } for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) { - oatDumpLIRInsn(cUnit, lirInsn, (unsigned char*) cUnit->baseAddr); + oatDumpLIRInsn(cUnit, lirInsn, 0); } for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) { armLIR = (ArmLIR*) lirInsn; char buf[100]; - snprintf(buf, 100, "%p (%04x): .class (%s)", - (char*)cUnit->baseAddr + armLIR->generic.offset, - armLIR->generic.offset, + snprintf(buf, 100, "%x (%04x): .class (%s)", + armLIR->generic.offset, armLIR->generic.offset, ((CallsiteInfo *) armLIR->operands[0])->classDescriptor); LOG(INFO) << buf; } for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) { armLIR = (ArmLIR*) lirInsn; char buf[100]; - snprintf(buf, 100, "%p (%04x): .word (%#x)", - (char*)cUnit->baseAddr + armLIR->generic.offset, - armLIR->generic.offset, + snprintf(buf, 100, "%x (%04x): .word (%#x)", + armLIR->generic.offset, armLIR->generic.offset, armLIR->operands[0]); LOG(INFO) << buf; } int linebreak = 0; + std::string signature = method->GetSignature()->ToModifiedUtf8(); + std::string name = method->GetName()->ToModifiedUtf8(); + std::string descriptor = method->GetDeclaringClass()->GetDescriptor()-> + ToModifiedUtf8(); + char buf[100]; LOG(INFO) << "*/"; - sprintf(buf,"\n u1 %s%s_%s_code[] = {", - cUnit->method->clazz->descriptor, cUnit->method->name, - cUnit->method->shorty); + sprintf(buf,"\n u1 %s%s_%s_code[] = {", descriptor.c_str(), + name.c_str(), signature.c_str()); for (unsigned int i = 0; i < strlen(buf); i++) if (buf[i] == ';') buf[i] = '_'; LOG(INFO) << buf; strcpy(buf," "); - for (int i = 0; i < cUnit->totalSize; i++) { - sprintf(buf+strlen(buf),"0x%02x,", - ((u1*)cUnit->baseAddr)[i]); + for (int i = 0; i < cUnit->totalSize/2; i++) { + sprintf(buf+strlen(buf),"0x%04x,", cUnit->codeBuffer[i]); if (++linebreak == 8) { linebreak = 0; LOG(INFO) << buf; @@ -478,8 +478,8 @@ void oatCodegenDump(CompilationUnit* cUnit) LOG(FATAL) << "Null table"; } sprintf(buf,"\n MappingTable %s%s_%s_mappingTable[%d] = {", - cUnit->method->clazz->descriptor, cUnit->method->name, - cUnit->method->shorty, cUnit->mappingTableSize); + descriptor.c_str(), name.c_str(), signature.c_str(), + cUnit->mappingTableSize); for (unsigned int i = 0; i < strlen(buf); i++) if (buf[i] == ';') buf[i] = '_'; LOG(INFO) << buf; diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc index 2fc1603b61..0a0c9bc458 100644 --- a/src/compiler/codegen/arm/ArmRallocUtil.cc +++ b/src/compiler/codegen/arm/ArmRallocUtil.cc @@ -86,7 +86,7 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb, for (i=0; i< ssaRep->numUses; i++) { int origSreg = DECODE_REG( oatConvertSSARegToDalvik(cUnit, ssaRep->uses[i])); - assert(origSreg < cUnit->method->registersSize); + assert(origSreg < cUnit->method->num_registers_); bool fpUse = ssaRep->fpUse ? ssaRep->fpUse[i] : false; if (fp == fpUse) { counts[origSreg].count++; @@ -99,7 +99,7 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb, } int origSreg = DECODE_REG( oatConvertSSARegToDalvik(cUnit, ssaRep->defs[i])); - assert(origSreg < cUnit->method->registersSize); + assert(origSreg < cUnit->method->num_registers_); bool fpDef = ssaRep->fpDef ? ssaRep->fpDef[i] : false; if (fp == fpDef) { counts[origSreg].count++; @@ -131,8 +131,8 @@ static void dumpCounts(const RefCounts* arr, int size, const char* msg) */ extern void oatDoPromotion(CompilationUnit* cUnit) { - int numRegs = cUnit->method->registersSize; - int numIns = cUnit->method->insSize; + int numRegs = cUnit->method->num_registers_; + int numIns = cUnit->method->num_ins_; /* * Because ins don't have explicit definitions, we need to type @@ -140,10 +140,9 @@ extern void oatDoPromotion(CompilationUnit* cUnit) */ if (numIns > 0) { int sReg = numRegs - numIns; - const char *shorty = cUnit->method->shorty; - shorty++; // Move past return type; - while (*shorty) { - char arg = *shorty++; + const art::StringPiece& shorty = cUnit->method->GetShorty(); + for (int i = 1; i < shorty.size(); i++) { + char arg = shorty[i]; // Is it wide? if ((arg == 'D') || (arg == 'J')) { cUnit->regLocation[sReg].wide = true; diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc index a601286fa1..9981d64ac1 100644 --- a/src/compiler/codegen/arm/Assemble.cc +++ b/src/compiler/codegen/arm/Assemble.cc @@ -965,13 +965,23 @@ ArmEncodingMap EncodingMap[kArmLast] = { */ #define PADDING_MOV_R5_R5 0x1C2D +static void pushWord(std::vector<short>&buf, int data) { + buf.push_back( (data >> 16) & 0xffff); + buf.push_back( data & 0xffff); +} + +void alignBuffer(std::vector<short>&buf, size_t offset) { + while (buf.size() < (offset/2)) + buf.push_back(0); +} + /* Write the numbers in the constant to the output stream */ static void installLiteralPools(CompilationUnit* cUnit) { - int* dataPtr = (int*) ((char*) cUnit->baseAddr + cUnit->dataOffset); + alignBuffer(cUnit->codeBuffer, cUnit->dataOffset); ArmLIR* dataLIR = (ArmLIR*) cUnit->literalList; while (dataLIR) { - *dataPtr++ = dataLIR->operands[0]; + pushWord(cUnit->codeBuffer, dataLIR->operands[0]); dataLIR = NEXT_LIR(dataLIR); } } @@ -985,7 +995,7 @@ static void installSwitchTables(CompilationUnit* cUnit) SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext( &iterator); if (tabRec == NULL) break; - int* dataPtr = (int*)((char*)cUnit->baseAddr + tabRec->offset); + alignBuffer(cUnit->codeBuffer, tabRec->offset); int bxOffset = tabRec->bxInst->generic.offset + 4; if (cUnit->printMe) { LOG(INFO) << "Switch table for offset 0x" /*<< hex*/ << bxOffset; @@ -999,8 +1009,9 @@ static void installSwitchTables(CompilationUnit* cUnit) std::hex << keys[elems] << ", disp: 0x" << std::hex << disp; } - *dataPtr++ = keys[elems]; - *dataPtr++ = tabRec->targets[elems]->generic.offset - bxOffset; + pushWord(cUnit->codeBuffer, keys[elems]); + pushWord(cUnit->codeBuffer, + tabRec->targets[elems]->generic.offset - bxOffset); } } else { assert(tabRec->table[0] == kPackedSwitchSignature); @@ -1010,7 +1021,8 @@ static void installSwitchTables(CompilationUnit* cUnit) LOG(INFO) << " Case[" << elems << "] disp: 0x" << std::hex << disp; } - *dataPtr++ = tabRec->targets[elems]->generic.offset - bxOffset; + pushWord(cUnit->codeBuffer, + tabRec->targets[elems]->generic.offset - bxOffset); } } } @@ -1025,8 +1037,10 @@ static void installFillArrayData(CompilationUnit* cUnit) FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext( &iterator); if (tabRec == NULL) break; - char* dataPtr = (char*)cUnit->baseAddr + tabRec->offset; - memcpy(dataPtr, (char*)tabRec->table, tabRec->size); + alignBuffer(cUnit->codeBuffer, tabRec->offset); + cUnit->codeBuffer.reserve(cUnit->codeBuffer.size() + (tabRec->size/2)); + memcpy(&cUnit->codeBuffer[tabRec->offset/2], + (char*)tabRec->table, tabRec->size); } } @@ -1038,7 +1052,6 @@ static void installFillArrayData(CompilationUnit* cUnit) static AssemblerStatus assembleInstructions(CompilationUnit* cUnit, intptr_t startAddr) { - short* bufferAddr = (short*) cUnit->codeBuffer; ArmLIR* lir; AssemblerStatus res = kSuccess; // Assume success @@ -1047,7 +1060,7 @@ static AssemblerStatus assembleInstructions(CompilationUnit* cUnit, if ((lir->opcode == kArmPseudoPseudoAlign4) && /* 1 means padding is needed */ (lir->operands[0] == 1)) { - *bufferAddr++ = PADDING_MOV_R5_R5; + cUnit->codeBuffer.push_back(PADDING_MOV_R5_R5); } continue; } @@ -1394,9 +1407,9 @@ static AssemblerStatus assembleInstructions(CompilationUnit* cUnit, } } if (encoder->size == 2) { - *bufferAddr++ = (bits >> 16) & 0xffff; + cUnit->codeBuffer.push_back((bits >> 16) & 0xffff); } - *bufferAddr++ = bits & 0xffff; + cUnit->codeBuffer.push_back(bits & 0xffff); } return res; } @@ -1526,23 +1539,6 @@ void assignOffsets(CompilationUnit* cUnit) void oatAssembleLIR(CompilationUnit* cUnit) { assignOffsets(cUnit); - -#ifdef TESTMODE -//For testing - caller will allocate buffer - int testSize = 1024 * 1024; - int fd = ashmem_create_region("dalvik-test-code-cache",testSize); - if (fd < 0) { - LOG(FATAL) << "Coudln't create ashmem region"; - } - cUnit->baseAddr = cUnit->codeBuffer = (unsigned char *) - mmap(NULL, testSize, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE, fd, 0); - close(fd); - if (cUnit->baseAddr == MAP_FAILED) { - LOG(FATAL) << "Failed to mmap the test region: " << strerror(errno); - } -#endif - /* * Assemble here. Note that we generate code with optimistic assumptions * and if found now to work, we'll have to redo the sequence and retry. @@ -1559,6 +1555,7 @@ void oatAssembleLIR(CompilationUnit* cUnit) } // Redo offsets and try again assignOffsets(cUnit); + cUnit->codeBuffer.clear(); } } diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc index 417fdca622..b8dcdb2c67 100644 --- a/src/compiler/codegen/arm/MethodCodegenDriver.cc +++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc @@ -14,12 +14,6 @@ * limitations under the License. */ -//#define TESTMODE - -#ifdef TESTMODE -#include "CalloutHelper.h" -#endif - static const RegLocation badLoc = {kLocDalvikFrame, 0, 0, INVALID_REG, INVALID_REG, INVALID_SREG, 0, kLocDalvikFrame, INVALID_REG, INVALID_REG, @@ -31,8 +25,8 @@ static void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, RegLocation rlSrc) { oatFlushAllRegs(cUnit); /* All temps to home location */ - void* classPtr = (void*) - (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]); + Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedClass(mir->dalvikInsn.vC); if (classPtr == NULL) { LOG(FATAL) << "Unexpected null passPtr"; } else { @@ -41,14 +35,8 @@ static void genNewArray(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, } // FIXME: need this to throw errNegativeArraySize genRegImmCheck(cUnit, kArmCondMi, r1, 0, mir->offset, NULL); -#ifdef TESTMODE -// Hack until we get rSELF setup - loadConstant(cUnit, rLR, (int)dvmAllocArrayByClass); -#else loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocArrayByClass), rLR); -#endif - loadConstant(cUnit, r2, ALLOC_DONT_TRACK); newLIR1(cUnit, kThumbBlxR, rLR); // (arrayClass, length, allocFlags) storeValue(cUnit, rlDest, retLoc); } @@ -72,8 +60,8 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) typeIndex = dInsn->vC; } oatFlushAllRegs(cUnit); /* All temps to home location */ - void* classPtr = (void*) - (cUnit->method->clazz->pDvmDex->pResClasses[typeIndex]); + Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedClass(typeIndex); if (classPtr == NULL) { LOG(FATAL) << "Unexpected null passPtr"; } else { @@ -88,14 +76,8 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) * the above mentioned bad cases of 'D', 'J' or !('L' | '[' | 'I'). * That will keep us from wasting space generating an inline check here. */ -#ifdef TESTMODE -// Hack until we get rSELF setup - loadConstant(cUnit, rLR, (int)dvmAllocArrayByClass); -#else loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocArrayByClass), rLR); -#endif - loadConstant(cUnit, r2, ALLOC_DONT_TRACK); newLIR1(cUnit, kThumbBlxR, rLR); // (arrayClass, length, allocFlags) // Reserve ret0 (r0) - we'll use it in place. oatLockTemp(cUnit, r0); @@ -130,7 +112,7 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) opRegRegImm(cUnit, kOpAdd, rSrc, rSP, rlFirst.spOffset); // Set up the target pointer opRegRegImm(cUnit, kOpAdd, rDst, r0, - OFFSETOF_MEMBER(ArrayObject, contents)); + Array::DataOffset().Int32Value()); // Set up the loop counter (known to be > 0) loadConstant(cUnit, rIdx, dInsn->vA); // Generate the copy loop. Going backwards for convenience @@ -148,7 +130,8 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) for (unsigned int i = 0; i < dInsn->vA; i++) { RegLocation rlArg = loadValue(cUnit, oatGetSrc(cUnit, mir, i), kCoreReg); - storeBaseDisp(cUnit, r0, OFFSETOF_MEMBER(ArrayObject, contents) + + storeBaseDisp(cUnit, r0, + Array::DataOffset().Int32Value() + i * 4, rlArg.lowReg, kWord); // If the loadValue caused a temp to be allocated, free it if (oatIsTemp(cUnit, rlArg.lowReg)) { @@ -160,6 +143,8 @@ static void genFilledNewArray(CompilationUnit* cUnit, MIR* mir, bool isRange) static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { + UNIMPLEMENTED(FATAL) << "Must update for new world"; +#if 0 int valOffset = OFFSETOF_MEMBER(StaticField, value); int tReg = oatAllocTemp(cUnit); int objHead; @@ -181,9 +166,9 @@ static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) (opcode == OP_SPUT_VOLATILE_JUMBO) || (opcode == OP_SPUT_OBJECT_VOLATILE) || (opcode == OP_SPUT_OBJECT_VOLATILE_JUMBO); - assert(isVolatile == dvmIsVolatileField((Field *) fieldPtr)); + assert(isVolatile == artIsVolatileField((Field *) fieldPtr)); #else - isVolatile = dvmIsVolatileField((Field *) fieldPtr); + isVolatile = artIsVolatileField((Field *) fieldPtr); #endif isSputObject = (opcode == OP_SPUT_OBJECT) || @@ -206,10 +191,13 @@ static void genSput(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) markGCCard(cUnit, rlSrc.lowReg, objHead); oatFreeTemp(cUnit, objHead); } +#endif } static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { + UNIMPLEMENTED(FATAL) << "Must update for new world"; +#if 0 int tReg = oatAllocTemp(cUnit); int valOffset = OFFSETOF_MEMBER(StaticField, value); const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? @@ -227,6 +215,7 @@ static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) loadConstant(cUnit, tReg, (int) fieldPtr + valOffset); storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg); +#endif } @@ -234,6 +223,8 @@ static void genSputWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) static void genSgetWide(CompilationUnit* cUnit, MIR* mir, RegLocation rlResult, RegLocation rlDest) { + UNIMPLEMENTED(FATAL) << "Must update for new world"; +#if 0 int valOffset = OFFSETOF_MEMBER(StaticField, value); const Method *method = (mir->OptimizationFlags & MIR_CALLEE) ? mir->meta.calleeMethod : cUnit->method; @@ -253,11 +244,14 @@ static void genSgetWide(CompilationUnit* cUnit, MIR* mir, loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg); storeValueWide(cUnit, rlDest, rlResult); +#endif } static void genSget(CompilationUnit* cUnit, MIR* mir, RegLocation rlResult, RegLocation rlDest) { + UNIMPLEMENTED(FATAL) << "Must update for new world"; +#if 0 int valOffset = OFFSETOF_MEMBER(StaticField, value); int tReg = oatAllocTemp(cUnit); bool isVolatile; @@ -282,9 +276,9 @@ static void genSget(CompilationUnit* cUnit, MIR* mir, Opcode opcode = mir->dalvikInsn.opcode; isVolatile = (opcode == OP_SGET_VOLATILE) || (opcode == OP_SGET_OBJECT_VOLATILE); - assert(isVolatile == dvmIsVolatileField((Field *) fieldPtr)); + assert(isVolatile == artIsVolatileField((Field *) fieldPtr)); #else - isVolatile = dvmIsVolatileField((Field *) fieldPtr); + isVolatile = artIsVolatileField((Field *) fieldPtr); #endif rlDest = oatGetDest(cUnit, mir, 0); @@ -297,6 +291,7 @@ static void genSget(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, tReg, 0, rlResult.lowReg); storeValue(cUnit, rlDest, rlResult); +#endif } typedef int (*NextCallInsn)(CompilationUnit*, MIR*, DecodedInstruction*, int); @@ -308,11 +303,14 @@ typedef int (*NextCallInsn)(CompilationUnit*, MIR*, DecodedInstruction*, int); static int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn, int state) { + UNIMPLEMENTED(FATAL) << "Update with new cache model"; +#if 0 switch(state) { case 0: // Get the current Method* [sets r0] loadBaseDisp(cUnit, mir, rSP, 0, r0, kWord, INVALID_SREG); break; case 1: // Get the pResMethods pointer [uses r0, sets r0] + UNIMPLEMENTED(FATAL) << "Update with new cache"; loadBaseDisp(cUnit, mir, r0, OFFSETOF_MEMBER(Method, pResMethods), r0, kWord, INVALID_SREG); break; @@ -328,6 +326,7 @@ static int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir, default: return -1; } +#endif return state + 1; } @@ -341,6 +340,8 @@ static int nextSDCallInsn(CompilationUnit* cUnit, MIR* mir, static int nextVCallInsn(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn, int state) { + UNIMPLEMENTED(FATAL) << "Update with new cache model"; +#if 0 RegLocation rlArg; switch(state) { case 0: // Get the current Method* [set r0] @@ -368,19 +369,21 @@ static int nextVCallInsn(CompilationUnit* cUnit, MIR* mir, r12, kUnsignedHalf, INVALID_SREG); // get this->clazz->vtable [use rLR, set rLR] loadBaseDisp(cUnit, mir, rLR, - OFFSETOF_MEMBER(ClassObject, vtable), rLR, kWord, + OFFSETOF_MEMBER(Class, vtable), rLR, kWord, INVALID_SREG); break; case 4: // get target Method* [use rLR, use r12, set r0] loadBaseIndexed(cUnit, rLR, r12, r0, 2, kWord); break; case 5: // Get the target compiled code address [use r0, set rLR] + UNIMPLEMENTED(FATAL) << "Update with new cache"; loadBaseDisp(cUnit, mir, r0, OFFSETOF_MEMBER(Method, compiledInsns), rLR, kWord, INVALID_SREG); break; default: return -1; } +#endif return state + 1; } @@ -412,6 +415,8 @@ static int loadArgRegs(CompilationUnit* cUnit, MIR* mir, static int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn, int state) { + UNIMPLEMENTED(FATAL) << "Update with new cache model"; +#if 0 RegLocation rlArg; switch(state) { case 0: @@ -427,14 +432,14 @@ static int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir, loadBaseDisp(cUnit, mir, r2, OFFSETOF_MEMBER(Method, clazz), r3, kWord, INVALID_SREG); // Load this->class [usr r12, set arg0] - loadBaseDisp(cUnit, mir, r12, OFFSETOF_MEMBER(ClassObject, clazz), + loadBaseDisp(cUnit, mir, r12, OFFSETOF_MEMBER(Class, clazz), r3, kWord, INVALID_SREG); // Load address of helper function loadBaseDisp(cUnit, mir, rSELF, OFFSETOF_MEMBER(Thread, pArtFindInterfaceMethodInCache), rLR, kWord, INVALID_SREG); // Get dvmDex - loadBaseDisp(cUnit, mir, r3, OFFSETOF_MEMBER(ClassObject, pDvmDex), + loadBaseDisp(cUnit, mir, r3, OFFSETOF_MEMBER(Class, pDvmDex), r3, kWord, INVALID_SREG); // Load ref [set arg1] loadConstant(cUnit, r1, dInsn->vB); @@ -447,6 +452,7 @@ static int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir, default: return -1; } +#endif return state + 1; } @@ -458,6 +464,8 @@ static int nextInterfaceCallInsn(CompilationUnit* cUnit, MIR* mir, static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir, DecodedInstruction* dInsn, int state) { + UNIMPLEMENTED(FATAL) << "Update with new cache model"; +#if 0 RegLocation rlArg; switch(state) { case 0: @@ -473,7 +481,7 @@ static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir, loadBaseDisp(cUnit, mir, r0, OFFSETOF_MEMBER(Method, pResMethods), rLR, kWord, INVALID_SREG); // Get clazz->super [use r12, set r12] - loadBaseDisp(cUnit, mir, r12, OFFSETOF_MEMBER(ClassObject, super), + loadBaseDisp(cUnit, mir, r12, OFFSETOF_MEMBER(Class, super), r12, kWord, INVALID_SREG); // Get base method [use rLR, set r0] loadBaseDisp(cUnit, mir, rLR, dInsn->vB * 4, r0, @@ -486,7 +494,7 @@ static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir, rLR, kUnsignedHalf, INVALID_SREG); // Get vtableCount [use r12, set r0] loadBaseDisp(cUnit, mir, r12, - OFFSETOF_MEMBER(ClassObject, vtableCount), + OFFSETOF_MEMBER(Class, vtableCount), r0, kWord, INVALID_SREG); // Compare method index w/ vtable count [use r12, use rLR] genRegRegCheck(cUnit, kArmCondGe, rLR, r0, mir->offset, NULL); @@ -498,6 +506,7 @@ static int nextSuperCallInsn(CompilationUnit* cUnit, MIR* mir, default: return -1; } +#endif return state + 1; } @@ -591,7 +600,8 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, * Dalvik vRegs and the ins. */ int highestVreg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow; - if (highestVreg >= cUnit->method->registersSize - cUnit->method->insSize) { + if (highestVreg >= cUnit->method->num_registers_ - + cUnit->method->num_ins_) { LOG(FATAL) << "Wide argument spanned locals & args"; } @@ -622,7 +632,7 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir, newLIR1(cUnit, kThumbBlxR, rLR); } else { // Use vldm/vstm pair using r3 as a temp - int regsLeft = MIN(numArgs - 3, 16); + int regsLeft = std::min(numArgs - 3, 16); callState = nextCallInsn(cUnit, mir, dInsn, callState); opRegRegImm(cUnit, kOpAdd, r3, rSP, startOffset); newLIR3(cUnit, kThumb2Vldms, r3, fr0 & FP_REG_MASK, regsLeft); @@ -791,7 +801,7 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, case OP_MOVE_EXCEPTION: int exOffset; int resetReg; - exOffset = OFFSETOF_MEMBER(Thread, exception); + exOffset = Thread::ExceptionOffset().Int32Value(); resetReg = oatAllocTemp(cUnit); rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); loadWordDisp(cUnit, rSELF, exOffset, rlResult.lowReg); @@ -923,7 +933,7 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, case OP_ARRAY_LENGTH: int lenOffset; - lenOffset = OFFSETOF_MEMBER(ArrayObject, length); + lenOffset = Array::LengthOffset().Int32Value(); genNullCheck(cUnit, rlSrc[0].sRegLow, rlSrc[0].lowReg, mir->offset, NULL); rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); @@ -1101,7 +1111,7 @@ static bool compileDalvikInstruction(CompilationUnit* cUnit, MIR* mir, genArrayPut(cUnit, mir, kWord, rlSrc[1], rlSrc[2], rlSrc[0], 2); break; case OP_APUT_OBJECT: - genArrayObjectPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2); + genArrayPut(cUnit, mir, rlSrc[1], rlSrc[2], rlSrc[0], 2); break; case OP_APUT_SHORT: case OP_APUT_CHAR: @@ -1432,11 +1442,11 @@ static void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir) * Note: at this pointCopy any ins that are passed in register to their home location */ static void flushIns(CompilationUnit* cUnit) { - if (cUnit->method->insSize == 0) + if (cUnit->method->num_ins_ == 0) return; - int inRegs = (cUnit->method->insSize > 2) ? 3 : cUnit->method->insSize; + int inRegs = (cUnit->method->num_ins_ > 2) ? 3 : cUnit->method->num_ins_; int startReg = r1; - int startLoc = cUnit->method->registersSize - cUnit->method->insSize; + int startLoc = cUnit->method->num_registers_ - cUnit->method->num_ins_; for (int i = 0; i < inRegs; i++) { RegLocation loc = cUnit->regLocation[startLoc + i]; if (loc.location == kLocPhysReg) { @@ -1459,7 +1469,7 @@ static void flushIns(CompilationUnit* cUnit) } // Now, do initial assignment of all promoted arguments passed in frame - for (int i = inRegs; i < cUnit->method->insSize;) { + for (int i = inRegs; i < cUnit->method->num_ins_;) { RegLocation loc = cUnit->regLocation[startLoc + i]; if (loc.fpLocation == kLocPhysReg) { loc.location = kLocPhysReg; @@ -1721,45 +1731,3 @@ void oatFlushRegWideImpl(CompilationUnit* cUnit, int rBase, { storeBaseDispWide(cUnit, rBase, displacement, rSrcLo, rSrcHi); } - -#ifdef TESTMODE -// Will be done at runtime by art. Keep for debugging -void oatInitHelpers(Thread* thread) -{ - thread->pMemcpy = memcpy; - thread->pI2f = __aeabi_i2f; - thread->pF2iz = __aeabi_f2iz; - thread->pD2f = __aeabi_d2f; - thread->pF2d = __aeabi_f2d; - thread->pI2d = __aeabi_i2d; - thread->pD2iz = __aeabi_d2iz; - thread->pL2f = __aeabi_l2f; - thread->pL2d = __aeabi_l2d; - thread->pArtF2l = artF2L; - thread->pArtD2l = artD2L; - thread->pFadd = __aeabi_fadd; - thread->pFsub = __aeabi_fsub; - thread->pFdiv = __aeabi_fdiv; - thread->pFmul = __aeabi_fmul; - thread->pFmodf = fmodf; - thread->pDadd = __aeabi_dadd; - thread->pDsub = __aeabi_dsub; - thread->pDdiv = __aeabi_ddiv; - thread->pDmul = __aeabi_dmul; - thread->pFmod = fmod; - thread->pIdivmod = __aeabi_idivmod; - thread->pIdiv = __aeabi_idiv; - thread->pLdivmod = __aeabi_ldivmod; - thread->pArtUnlockObject = dvmUnlockObject; - thread->pArtCanPutArrayElementNoThrow = dvmCanPutArrayElement; - thread->pArtInstanceofNonTrivialNoThrow = dvmInstanceofNonTrivial; - thread->pArtInstanceofNonTrivial = dvmInstanceofNonTrivial; - thread->pArtAllocArrayByClass = dvmAllocArrayByClass; - thread->pArtFindInterfaceMethodInCache = dvmFindInterfaceMethodInCache; - thread->pArtUnlockObjectNoThrow = dvmUnlockObject; - thread->pArtLockObjectNoThrow = dvmLockObject; - thread->pArtAllocObjectNoThrow = dvmAllocObject; - thread->pArtThrowException = NULL; //TBD - thread->pArtHandleFillArrayDataNoThrow = dvmInterpHandleFillArrayData; -} -#endif diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index c9d72f709c..1a126e4e89 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -356,7 +356,7 @@ static void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) int regCardBase = oatAllocTemp(cUnit); int regCardNo = oatAllocTemp(cUnit); ArmLIR* branchOver = genCmpImmBranch(cUnit, kArmCondEq, valReg, 0); - loadWordDisp(cUnit, rSELF, offsetof(Thread, cardTable), + loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(), regCardBase); opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT); storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0, @@ -371,8 +371,8 @@ static void markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg) static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size, RegLocation rlDest, RegLocation rlObj) { - Field* fieldPtr = - cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC]; + Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedField(mir->dalvikInsn.vC); if (fieldPtr == NULL) { /* * With current scheme, we should never be in a situation @@ -387,7 +387,7 @@ static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size, #else bool isVolatile = false; #endif - int fieldOffset = ((InstField *)fieldPtr)->byteOffset; + int fieldOffset = fieldPtr->GetOffset(); RegLocation rlResult; RegisterClass regClass = oatRegClassBySize(size); rlObj = loadValue(cUnit, rlObj, kCoreReg); @@ -406,8 +406,8 @@ static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size, static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size, RegLocation rlSrc, RegLocation rlObj, bool isObject) { - Field* fieldPtr = - cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC]; + Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedField(mir->dalvikInsn.vC); if (fieldPtr == NULL) { /* * With current scheme, we should never be in a situation @@ -422,7 +422,7 @@ static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size, #else bool isVolatile = false; #endif - int fieldOffset = ((InstField *)fieldPtr)->byteOffset; + int fieldOffset = fieldPtr->GetOffset(); RegisterClass regClass = oatRegClassBySize(size); rlObj = loadValue(cUnit, rlObj, kCoreReg); rlSrc = loadValue(cUnit, rlSrc, regClass); @@ -442,8 +442,8 @@ static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size, static void genIGetWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, RegLocation rlObj) { - Field* fieldPtr = - cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC]; + Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedField(mir->dalvikInsn.vC); if (fieldPtr == NULL) { /* * With current scheme, we should never be in a situation @@ -458,7 +458,7 @@ static void genIGetWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, #else bool isVolatile = false; #endif - int fieldOffset = ((InstField *)fieldPtr)->byteOffset; + int fieldOffset = fieldPtr->GetOffset(); RegLocation rlResult; rlObj = loadValue(cUnit, rlObj, kCoreReg); int regPtr = oatAllocTemp(cUnit); @@ -483,8 +483,8 @@ static void genIGetWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, RegLocation rlObj) { - Field* fieldPtr = - cUnit->method->clazz->pDvmDex->pResFields[mir->dalvikInsn.vC]; + Field* fieldPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedField(mir->dalvikInsn.vC); if (fieldPtr == NULL) { /* * With current scheme, we should never be in a situation @@ -499,7 +499,7 @@ static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, #else bool isVolatile = false; #endif - int fieldOffset = ((InstField *)fieldPtr)->byteOffset; + int fieldOffset = fieldPtr->GetOffset(); rlObj = loadValue(cUnit, rlObj, kCoreReg); int regPtr; @@ -520,13 +520,14 @@ static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc, static void genConstClass(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, RegLocation rlSrc) { - void* classPtr = (void*) - (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]); + Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedClass(mir->dalvikInsn.vB); if (classPtr == NULL) { LOG(FATAL) << "Unexpected null class pointer"; } + UNIMPLEMENTED(WARNING) << "Not position independent. Fix"; RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); loadConstantNoClobber(cUnit, rlResult.lowReg, (int) classPtr ); storeValue(cUnit, rlDest, rlResult); @@ -535,14 +536,15 @@ static void genConstClass(CompilationUnit* cUnit, MIR* mir, static void genConstString(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, RegLocation rlSrc) { - void* strPtr = (void*) - (cUnit->method->clazz->pDvmDex->pResStrings[mir->dalvikInsn.vB]); + String* strPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedString(mir->dalvikInsn.vB); if (strPtr == NULL) { /* Shouldn't happen */ LOG(FATAL) << "Unexpected null const string pointer"; } + UNIMPLEMENTED(WARNING) << "Not position indendent. Fix"; RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); loadConstantNoClobber(cUnit, rlResult.lowReg, (int) strPtr ); storeValue(cUnit, rlDest, rlResult); @@ -551,8 +553,8 @@ static void genConstString(CompilationUnit* cUnit, MIR* mir, static void genNewInstance(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest) { - ClassObject* classPtr = (ClassObject *) - (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]); + Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedClass(mir->dalvikInsn.vB); if (classPtr == NULL) { /* Shouldn't happen */ @@ -560,12 +562,13 @@ static void genNewInstance(CompilationUnit* cUnit, MIR* mir, } // Verifier should have already rejected abstract/interface - assert((classPtr->accessFlags & (ACC_INTERFACE|ACC_ABSTRACT)) == 0); + assert((classPtr->access_flags_ & + (art::kAccInterface|art::kAccAbstract)) == 0); oatFlushAllRegs(cUnit); /* Everything to home location */ loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtAllocObjectNoThrow), rLR); loadConstant(cUnit, r0, (int) classPtr); - loadConstant(cUnit, r1, ALLOC_DONT_TRACK); + UNIMPLEMENTED(WARNING) << "Need NewWorld dvmAllocObject"; opReg(cUnit, kOpBlx, rLR); oatClobberCallRegs(cUnit); RegLocation rlResult = oatGetReturn(cUnit); @@ -586,8 +589,8 @@ static void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, { // May generate a call - use explicit registers RegLocation rlResult; - ClassObject* classPtr = - (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vC]); + Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedClass(mir->dalvikInsn.vC); if (classPtr == NULL) { /* Shouldn't happen */ LOG(FATAL) << "Unexpected null class pointer"; @@ -598,7 +601,8 @@ static void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, /* When taken r0 has NULL which can be used for store directly */ ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0); /* r1 now contains object->clazz */ - loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1); + assert(OFFSETOF_MEMBER(Object, klass_) == 0); + loadWordDisp(cUnit, r0, OFFSETOF_MEMBER(Object, klass_), r1); /* r1 now contains object->clazz */ loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtInstanceofNonTrivial), rLR); @@ -620,8 +624,8 @@ static void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, static void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - ClassObject* classPtr = - (cUnit->method->clazz->pDvmDex->pResClasses[mir->dalvikInsn.vB]); + Class* classPtr = cUnit->method->GetDeclaringClass()->GetDexCache()-> + GetResolvedClass(mir->dalvikInsn.vB); if (classPtr == NULL) { /* Shouldn't happen with our current model */ LOG(FATAL) << "Unexpected null class pointer"; @@ -639,7 +643,7 @@ static void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) * with clazz. */ /* r0 now contains object->clazz */ - loadWordDisp(cUnit, rlSrc.lowReg, offsetof(Object, clazz), r0); + loadWordDisp(cUnit, rlSrc.lowReg, OFFSETOF_MEMBER(Object, klass_), r0); loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtInstanceofNonTrivialNoThrow), rLR); opRegReg(cUnit, kOpCmp, r0, r1); @@ -783,20 +787,23 @@ static void genMonitorEnter(CompilationUnit* cUnit, MIR* mir, ArmLIR* hopBranch; oatFlushAllRegs(cUnit); - assert(LW_SHAPE_THIN == 0); + assert(art::Monitor::kLwShapeThin == 0); loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj oatLockAllTemps(cUnit); // Prepare for explicit register usage genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); - loadWordDisp(cUnit, rSELF, offsetof(Thread, threadId), r3); // Get threadId + loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3); newLIR3(cUnit, kThumb2Ldrex, r2, r1, - offsetof(Object, lock) >> 2); // Get object->lock - opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner + OFFSETOF_MEMBER(Object, monitor_) >> 2); // Get object->lock + // Align owner + opRegImm(cUnit, kOpLsl, r3, art::Monitor::kLwLockOwnerShift); // Is lock unheld on lock or held by us (==threadId) on unlock? - newLIR4(cUnit, kThumb2Bfi, r3, r2, 0, LW_LOCK_OWNER_SHIFT - 1); - newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT, - LW_LOCK_OWNER_SHIFT - 1); + newLIR4(cUnit, kThumb2Bfi, r3, r2, 0, art::Monitor::kLwLockOwnerShift + - 1); + newLIR3(cUnit, kThumb2Bfc, r2, art::Monitor::kLwHashStateShift, + art::Monitor::kLwLockOwnerShift - 1); hopBranch = newLIR2(cUnit, kThumb2Cbnz, r2, 0); - newLIR4(cUnit, kThumb2Strex, r2, r3, r1, offsetof(Object, lock) >> 2); + newLIR4(cUnit, kThumb2Strex, r2, r3, r1, + OFFSETOF_MEMBER(Object, monitor_) >> 2); oatGenMemBarrier(cUnit, kSY); branch = newLIR2(cUnit, kThumb2Cbz, r2, 0); @@ -830,23 +837,24 @@ static void genMonitorExit(CompilationUnit* cUnit, MIR* mir, ArmLIR* hopTarget; ArmLIR* hopBranch; - assert(LW_SHAPE_THIN == 0); + assert(art::Monitor::kLwShapeThin == 0); oatFlushAllRegs(cUnit); loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj oatLockAllTemps(cUnit); // Prepare for explicit register usage genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL); - loadWordDisp(cUnit, r1, offsetof(Object, lock), r2); // Get object->lock - loadWordDisp(cUnit, rSELF, offsetof(Thread, threadId), r3); // Get threadId + loadWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, monitor_), r2); // Get lock + loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3); // Is lock unheld on lock or held by us (==threadId) on unlock? - opRegRegImm(cUnit, kOpAnd, r12, r2, - (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT)); - opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner - newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT, - LW_LOCK_OWNER_SHIFT - 1); + opRegRegImm(cUnit, kOpAnd, r12, r2, (art::Monitor::kLwHashStateMask << + art::Monitor::kLwHashStateShift)); + // Align owner + opRegImm(cUnit, kOpLsl, r3, art::Monitor::kLwLockOwnerShift); + newLIR3(cUnit, kThumb2Bfc, r2, art::Monitor::kLwHashStateShift, + art::Monitor::kLwLockOwnerShift - 1); opRegReg(cUnit, kOpSub, r2, r3); hopBranch = opCondBranch(cUnit, kArmCondNe); oatGenMemBarrier(cUnit, kSY); - storeWordDisp(cUnit, r1, offsetof(Object, lock), r12); + storeWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, monitor_), r12); branch = opNone(cUnit, kOpUncondBr); hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel); @@ -1116,13 +1124,13 @@ static inline ArmLIR* genTrap(CompilationUnit* cUnit, int dOffset, * Generate array store * */ -static void genArrayObjectPut(CompilationUnit* cUnit, MIR* mir, +static void genArrayPut(CompilationUnit* cUnit, MIR* mir, RegLocation rlArray, RegLocation rlIndex, RegLocation rlSrc, int scale) { RegisterClass regClass = oatRegClassBySize(kWord); - int lenOffset = OFFSETOF_MEMBER(ArrayObject, length); - int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents); + int lenOffset = Array::LengthOffset().Int32Value(); + int dataOffset = Array::DataOffset().Int32Value(); /* Make sure it's a legal object Put. Use direct regs at first */ loadValueDirectFixed(cUnit, rlArray, r1); @@ -1138,9 +1146,9 @@ static void genArrayObjectPut(CompilationUnit* cUnit, MIR* mir, loadWordDisp(cUnit, rSELF, OFFSETOF_MEMBER(Thread, pArtCanPutArrayElementNoThrow), rLR); /* Get the array's clazz */ - loadWordDisp(cUnit, r1, offsetof(Object, clazz), r1); + loadWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, klass_), r1); /* Get the object's clazz */ - loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0); + loadWordDisp(cUnit, r0, OFFSETOF_MEMBER(Object, klass_), r0); opReg(cUnit, kOpBlx, rLR); oatClobberCallRegs(cUnit); @@ -1186,8 +1194,8 @@ static void genArrayGet(CompilationUnit* cUnit, MIR* mir, OpSize size, RegLocation rlDest, int scale) { RegisterClass regClass = oatRegClassBySize(size); - int lenOffset = OFFSETOF_MEMBER(ArrayObject, length); - int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents); + int lenOffset = Array::LengthOffset().Int32Value(); + int dataOffset = Array::DataOffset().Int32Value(); RegLocation rlResult; rlArray = loadValue(cUnit, rlArray, kCoreReg); rlIndex = loadValue(cUnit, rlIndex, kCoreReg); @@ -1251,8 +1259,8 @@ static void genArrayPut(CompilationUnit* cUnit, MIR* mir, OpSize size, RegLocation rlSrc, int scale) { RegisterClass regClass = oatRegClassBySize(size); - int lenOffset = OFFSETOF_MEMBER(ArrayObject, length); - int dataOffset = OFFSETOF_MEMBER(ArrayObject, contents); + int lenOffset = Array::LengthOffset().Int32Value(); + int dataOffset = Array::DataOffset().Int32Value(); int regPtr; rlArray = loadValue(cUnit, rlArray, kCoreReg); diff --git a/src/compiler_test.cc b/src/compiler_test.cc new file mode 100644 index 0000000000..c0d0c90aaa --- /dev/null +++ b/src/compiler_test.cc @@ -0,0 +1,42 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +#include "class_linker.h" +#include "common_test.h" +#include "dex_file.h" +#include "heap.h" +#include "object.h" +#include "scoped_ptr.h" + +#include <stdint.h> +#include <stdio.h> +#include "gtest/gtest.h" + +namespace art { + +class CompilerTest : public CommonTest { +}; + +#if defined(__arm__) +TEST_F(CompilerTest, BasicCodegen) { + scoped_ptr<DexFile> dex_file(OpenDexFileBase64(kFibonacciDex, + "kFibonacciDex")); + PathClassLoader* class_loader = AllocPathClassLoader(dex_file.get()); + + Thread::Current()->SetClassLoaderOverride(class_loader); + + JNIEnv* env = Thread::Current()->GetJniEnv(); + + jclass c = env->FindClass("Fibonacci"); + ASSERT_TRUE(c != NULL); + + jmethodID m = env->GetStaticMethodID(c, "fibonacci", "(I)I"); + ASSERT_TRUE(m != NULL); + + jint result = env->CallStaticIntMethod(c, m, 10); + LOG(INFO) << "Fibonacci[10] is " << result; + + ASSERT_EQ(55, result); +} +#endif + +} // namespace art diff --git a/src/constants.h b/src/constants.h index 2dd13b7195..f71857edc9 100644 --- a/src/constants.h +++ b/src/constants.h @@ -3,6 +3,17 @@ #ifndef ART_SRC_CONSTANTS_H_ #define ART_SRC_CONSTANTS_H_ +namespace art { + +enum InstructionSet { + kNone, + kArm, + kThumb2, + kX86 +}; + +} // namespace art + #if defined(__i386__) #include "constants_x86.h" #elif defined(__arm__) diff --git a/src/image_test.cc b/src/image_test.cc index 8c00e895ad..7c1312b640 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -4,8 +4,8 @@ #include "file.h" #include "image.h" #include "image_writer.h" -#include "os.h" #include "space.h" +#include "utils.h" #include "gtest/gtest.h" @@ -13,23 +13,6 @@ namespace art { class ImageTest : public CommonTest {}; -std::string ReadFileToString(const char* file_name) { - scoped_ptr<File> file(OS::OpenFile(file_name, false)); - CHECK(file != NULL); - - std::string contents; - char buf[8 * KB]; - while (true) { - int64_t n = file->Read(buf, sizeof(buf)); - CHECK_NE(-1, n); - if (n == 0) { - break; - } - contents.append(buf, n); - } - return contents; -} - TEST_F(ImageTest, WriteRead) { // TODO: move the touching of classes and GC to the ImageWriter proper diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc index 077e7bb73f..42150311fa 100644 --- a/src/jni_compiler.cc +++ b/src/jni_compiler.cc @@ -292,7 +292,9 @@ void JniCompiler::Compile(Assembler* jni_asm, Method* native_method) { size_t cs = jni_asm->CodeSize(); MemoryRegion code(AllocateCode(cs), cs); jni_asm->FinalizeInstructions(code); - native_method->SetCode(code.pointer()); + // TODO: need to ask jni_asm what instruction set used + native_method->SetCode(reinterpret_cast<byte*>(code.pointer()), cs, + jni_asm->GetInstructionSet()); } // Copy a single parameter from the managed to the JNI calling convention diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc index cb48e7635c..f315d1f9ad 100644 --- a/src/jni_compiler_test.cc +++ b/src/jni_compiler_test.cc @@ -23,32 +23,29 @@ class JniCompilerTest : public CommonTest { CommonTest::SetUp(); dex_.reset(OpenDexFileBase64(kMyClassNativesDex, "kMyClassNativesDex")); class_loader_ = AllocPathClassLoader(dex_.get()); + Thread::Current()->SetClassLoaderOverride(class_loader_); } void SetupForTest(bool direct, const char* method_name, const char* method_sig, void* native_fnptr) { - const char* class_name = "LMyClass;"; - Class* klass = class_linker_->FindClass(class_name, class_loader_); - ASSERT_TRUE(klass != NULL); + env_ = Thread::Current()->GetJniEnv(); + + jklass_ = env_->FindClass("MyClass"); + ASSERT_TRUE(jklass_ != NULL); + Class* c = class_linker_->FindClass("LMyClass;", class_loader_); Method* method; if (direct) { - method = klass->FindDirectMethod(method_name, method_sig); + method = c->FindDirectMethod(method_name, method_sig); } else { - method = klass->FindVirtualMethod(method_name, method_sig); + method = c->FindVirtualMethod(method_name, method_sig); } ASSERT_TRUE(method != NULL); // Compile the native method jni_compiler.Compile(&jni_asm, method); + ASSERT_TRUE(method->HasCode()); - env_ = Thread::Current()->GetJniEnv(); - - // TODO: when we support class loaders - env->FindClass(class_name); - IndirectReferenceTable& locals = reinterpret_cast<JNIEnvExt*>(env_)->locals; - uint32_t cookie = IRT_FIRST_SEGMENT; // TODO - IndirectRef klass_ref = locals.Add(cookie, klass); - jklass_ = reinterpret_cast<jclass>(klass_ref); if (direct) { jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig); } else { diff --git a/src/jni_internal.cc b/src/jni_internal.cc index 6acfb71d98..bfbd83e87a 100644 --- a/src/jni_internal.cc +++ b/src/jni_internal.cc @@ -18,6 +18,8 @@ #include "stringpiece.h" #include "thread.h" +extern bool oatCompileMethod(art::Method*, art::InstructionSet); + namespace art { // This is private API, but with two different implementations: ARM and x86. @@ -400,15 +402,22 @@ JValue InvokeWithArgArray(ScopedJniThreadState& ts, jobject obj, // Pass everything as arguments const Method::InvokeStub* stub = method->GetInvokeStub(); CHECK(stub != NULL); + +#ifdef __arm__ + // Compile... + // TODO: not here! + oatCompileMethod(method, kThumb2); +#endif + JValue result; - // TODO: we should always have code associated with a method - if (method->GetCode()) { + if (method->HasCode()) { (*stub)(method, rcvr, self, args, &result); } else { LOG(WARNING) << "Not invoking method with no associated code: " << PrettyMethod(method, true); result.j = 0; } + // Pop transition self->PopNativeToManagedRecord(record); return result; @@ -544,7 +553,8 @@ class JNI { ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); std::string descriptor(NormalizeJniClassDescriptor(name)); // TODO: need to get the appropriate ClassLoader. - Class* c = class_linker->FindClass(descriptor, NULL); + ClassLoader* cl = (ClassLoader*) ts.Self()->GetClassLoaderOverride(); // TODO: fix type in Thread + Class* c = class_linker->FindClass(descriptor, cl); return AddLocalReference<jclass>(ts, c); } diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc index b9e8f19286..cb71fa29bc 100644 --- a/src/jni_internal_test.cc +++ b/src/jni_internal_test.cc @@ -426,16 +426,6 @@ TEST_F(JniInternalTest, DeleteWeakGlobalRef) { bool EnsureInvokeStub(Method* method); -byte* AllocateCode(void* code, size_t length) { - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - void* addr = mmap(NULL, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - CHECK(addr != MAP_FAILED); - memcpy(addr, code, length); - __builtin___clear_cache(addr, (byte*)addr + length); - // Set the low-order bit so a BLX will switch to Thumb mode. - return reinterpret_cast<byte*>(reinterpret_cast<uintptr_t>(addr) | 1); -} - Method::InvokeStub* AllocateStub(Method* method, byte* code, size_t length) { @@ -443,17 +433,10 @@ Method::InvokeStub* AllocateStub(Method* method, EnsureInvokeStub(method); Method::InvokeStub* stub = method->GetInvokeStub(); CHECK(stub != NULL); - method->SetCode(AllocateCode(code, length)); - CHECK(method->GetCode() != NULL); + method->SetCode(code, length, kThumb2); return stub; } -void FreeStub(Method* method, size_t length) { - void* addr = const_cast<void*>(method->GetCode()); - munmap(addr, length); - method->SetCode(NULL); -} - #if defined(__arm__) TEST_F(JniInternalTest, StaticMainMethod) { scoped_ptr<DexFile> dex(OpenDexFileBase64(kMainDex, "kMainDex")); @@ -479,8 +462,6 @@ TEST_F(JniInternalTest, StaticMainMethod) { Object* arg = NULL; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), NULL); - - FreeStub(method, sizeof(main_LV_code)); } TEST_F(JniInternalTest, StaticNopMethod) { @@ -506,8 +487,6 @@ TEST_F(JniInternalTest, StaticNopMethod) { ASSERT_TRUE(stub); (*stub)(method, NULL, NULL, NULL, NULL); - - FreeStub(method, sizeof(nop_V_code)); } TEST_F(JniInternalTest, StaticIdentityByteMethod) { @@ -554,8 +533,6 @@ TEST_F(JniInternalTest, StaticIdentityByteMethod) { result.b = 0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result); EXPECT_EQ(SCHAR_MIN, result.b); - - FreeStub(method, sizeof(identity_BB_code)); } TEST_F(JniInternalTest, StaticIdentityIntMethod) { @@ -602,8 +579,6 @@ TEST_F(JniInternalTest, StaticIdentityIntMethod) { result.i = 0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result); EXPECT_EQ(INT_MIN, result.i); - - FreeStub(method, sizeof(identity_II_code)); } TEST_F(JniInternalTest, StaticIdentityDoubleMethod) { @@ -651,8 +626,6 @@ TEST_F(JniInternalTest, StaticIdentityDoubleMethod) { result.d = 0.0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result); EXPECT_EQ(DBL_MIN, result.d); - - FreeStub(method, sizeof(identity_DD_code)); } TEST_F(JniInternalTest, StaticSumIntIntMethod) { @@ -711,8 +684,6 @@ TEST_F(JniInternalTest, StaticSumIntIntMethod) { result.i = INT_MIN; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(-2, result.i); - - FreeStub(method, sizeof(sum_III_code)); } TEST_F(JniInternalTest, StaticSumIntIntIntMethod) { @@ -778,8 +749,6 @@ TEST_F(JniInternalTest, StaticSumIntIntIntMethod) { result.i = INT_MIN; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(2147483645, result.i); - - FreeStub(method, sizeof(sum_IIII_code)); } TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) { @@ -851,8 +820,6 @@ TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) { result.i = INT_MIN; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(-4, result.i); - - FreeStub(method, sizeof(sum_IIIII_code)); } TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) { @@ -931,8 +898,6 @@ TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) { result.i = INT_MIN; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(2147483643, result.i); - - FreeStub(method, sizeof(sum_IIIIII_code)); } TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) { @@ -992,8 +957,6 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) { result.d = 0.0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(INFINITY, result.d); - - FreeStub(method, sizeof(sum_DDD_code)); } TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) { @@ -1046,8 +1009,6 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) { result.d = 0.0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(2.0, result.d); - - FreeStub(method, sizeof(sum_DDDD_code)); } TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) { @@ -1105,8 +1066,6 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) { result.d = 0.0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(-2.0, result.d); - - FreeStub(method, sizeof(sum_DDDDD_code)); } TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) { @@ -1169,8 +1128,6 @@ TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) { result.d = 0.0; (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result); EXPECT_EQ(3.0, result.d); - - FreeStub(method, sizeof(sum_DDDDDD_code)); } #endif // __arm__ diff --git a/src/monitor.h b/src/monitor.h index 9ab3dd9f55..b82c463ae6 100644 --- a/src/monitor.h +++ b/src/monitor.h @@ -10,6 +10,13 @@ namespace art { class Monitor { public: + + // Lock constants used by compiler + static const uint32_t kLwLockOwnerShift = 3; + static const uint32_t kLwHashStateShift = 1; + static const uint32_t kLwHashStateMask = 0x3; + static const uint32_t kLwShapeThin = 0; + void Enter() { } @@ -39,6 +46,7 @@ class Monitor { class MonitorLock { public: + MonitorLock(Monitor* monitor) : monitor_(monitor) { CHECK(monitor != NULL); monitor_->Enter(); diff --git a/src/object.h b/src/object.h index c8ec9cb882..5d781e4f1e 100644 --- a/src/object.h +++ b/src/object.h @@ -535,18 +535,43 @@ class Method : public AccessibleObject { // Size in bytes of the return value size_t ReturnSize() const; - const void* GetCode() const { - return code_; + bool HasCode() { + return code_ != NULL; + } + + void SetCode(const byte* compiled_code, size_t byte_count, InstructionSet set) { + // Copy the code into an executable region. + code_instruction_set_ = set; + code_area_.reset(MemMap::Map(byte_count, + PROT_READ | PROT_WRITE | PROT_EXEC)); + byte* code = code_area_->GetAddress(); + memcpy(code, compiled_code, byte_count); + __builtin___clear_cache(code, code + byte_count); + + uintptr_t address = reinterpret_cast<uintptr_t>(code); + if (code_instruction_set_ == kThumb2) { + // Set the low-order bit so a BLX will switch to Thumb mode + address |= 0x1; + } + code_ = reinterpret_cast<void*>(address); + } + + void SetFrameSize(uint32_t frame_size) { + frame_size_ = frame_size; } - void SetCode(const void* code) { - code_ = code; + void SetCoreSpillMask(uint32_t core_spill_mask) { + core_spill_mask_ = core_spill_mask; } static size_t GetCodeOffset() { return OFFSETOF_MEMBER(Method, code_); } + void SetFpSpillMask(uint32_t fp_spill_mask) { + fp_spill_mask_ = fp_spill_mask; + } + void RegisterNative(const void* native_method) { native_method_ = native_method; } @@ -588,6 +613,13 @@ class Method : public AccessibleObject { uint16_t num_outs_; uint16_t num_ins_; + // Total size in bytes of the frame + uint32_t frame_size_; + + // Architecture-dependent register spill masks + uint32_t core_spill_mask_; + uint32_t fp_spill_mask_; + // The method descriptor. This represents the parameters a method // takes and value it returns. This string is a list of the type // descriptors for the parameters enclosed in parenthesis followed @@ -617,7 +649,13 @@ class Method : public AccessibleObject { private: // Compiled code associated with this method - const void* code_; + scoped_ptr<MemMap> code_area_; + void* code_; + // Instruction set of the coompiled code + InstructionSet code_instruction_set_; + + // Size in bytes of compiled code associated with this method + const uint32_t code_size_; // Any native method registered with this method const void* native_method_; @@ -660,6 +698,14 @@ class Array : public Object { length_ = length; } + static MemberOffset LengthOffset() { + return MemberOffset(OFFSETOF_MEMBER(Array, length_)); + } + + static MemberOffset DataOffset() { + return MemberOffset(OFFSETOF_MEMBER(Array, first_element_)); + } + protected: bool IsValidIndex(int32_t index) const { if (index < 0 || index >= length_) { @@ -676,6 +722,8 @@ class Array : public Object { int32_t length_; // Padding to ensure the first member defined by a subclass begins on a 8-byte boundary int32_t padding_; + // Marker for the data (used by generated code) + uint32_t first_element_[0]; DISALLOW_IMPLICIT_CONSTRUCTORS(Array); }; diff --git a/src/thread.h b/src/thread.h index ac332e0a9f..d511f04d8e 100644 --- a/src/thread.h +++ b/src/thread.h @@ -124,8 +124,53 @@ class Thread { kTerminated, }; + static const size_t kDefaultStackSize = 64 * KB; +// TODO - needs to be redone properly, just hacked into place for now + // Runtime support function pointers + void* (*pMemcpy)(void*, const void*, size_t); + float (*pI2f)(int); + int (*pF2iz)(float); + float (*pD2f)(double); + double (*pF2d)(float); + double (*pI2d)(int); + int (*pD2iz)(double); + float (*pL2f)(long); + double (*pL2d)(long); + long long (*pArtF2l)(float); + long long (*pArtD2l)(double); + float (*pFadd)(float, float); + float (*pFsub)(float, float); + float (*pFdiv)(float, float); + float (*pFmul)(float, float); + float (*pFmodf)(float, float); + double (*pDadd)(double, double); + double (*pDsub)(double, double); + double (*pDdiv)(double, double); + double (*pDmul)(double, double); + double (*pFmod)(double, double); + int (*pIdivmod)(int, int); + int (*pIdiv)(int, int); + long long (*pLdivmod)(long long, long long); + bool (*pArtUnlockObject)(struct Thread*, struct Object*); + bool (*pArtCanPutArrayElementNoThrow)(const struct ClassObject*, + const struct ClassObject*); + int (*pArtInstanceofNonTrivialNoThrow) + (const struct ClassObject*, const struct ClassObject*); + int (*pArtInstanceofNonTrivial) (const struct ClassObject*, + const struct ClassObject*); + struct ArrayObject* (*pArtAllocArrayByClass)(struct ClassObject*, + size_t, int); + struct Method* (*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t, + const struct Method*, struct DvmDex*); + bool (*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*); + void (*pArtLockObjectNoThrow)(struct Thread*, struct Object*); + struct Object* (*pArtAllocObjectNoThrow)(struct ClassObject*, int); + void (*pArtThrowException)(struct Thread*, struct Object*); + bool (*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*); + + // Creates a new thread. static Thread* Create(const Runtime* runtime); @@ -171,6 +216,16 @@ class Thread { return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_)); } + // Offset of id within Thread, used by generated code + static ThreadOffset IdOffset() { + return ThreadOffset(OFFSETOF_MEMBER(Thread, id_)); + } + + // Offset of card_table within Thread, used by generated code + static ThreadOffset CardTableOffset() { + return ThreadOffset(OFFSETOF_MEMBER(Thread, card_table_)); + } + void SetName(const char* name); void Suspend(); @@ -262,6 +317,14 @@ class Thread { top_of_managed_stack_ = record.last_top_of_managed_stack; } + Object* GetClassLoaderOverride() { + return class_loader_override_; + } + + void SetClassLoaderOverride(Object* class_loader_override) { + class_loader_override_ = class_loader_override; + } + private: Thread() : id_(1234), @@ -270,7 +333,8 @@ class Thread { top_shb_(NULL), jni_env_(NULL), exception_(NULL), - suspend_count_(0) { + suspend_count_(0), + class_loader_override_(NULL) { } ~Thread() { @@ -282,6 +346,9 @@ class Thread { // Managed thread id. uint32_t id_; + // FIXME: placeholder for the gc cardTable + uint32_t card_table_; + // Top of the managed stack, written out prior to the state transition from // kRunnable to kNative. Uses include to give the starting point for scanning // a managed stack when a thread is in native code. @@ -319,6 +386,8 @@ class Thread { // at the next poll. int suspend_count_; + Object* class_loader_override_; + // The memory mapping of the stack for non-attached threads. scoped_ptr<MemMap> stack_; diff --git a/src/utils.cc b/src/utils.cc index 67d5780865..f8a55cefe1 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -1,11 +1,30 @@ // Copyright 2011 Google Inc. All Rights Reserved. // Author: enh@google.com (Elliott Hughes) +#include "file.h" #include "object.h" +#include "os.h" #include "utils.h" namespace art { +std::string ReadFileToString(const char* file_name) { + scoped_ptr<File> file(OS::OpenFile(file_name, false)); + CHECK(file != NULL); + + std::string contents; + char buf[8 * KB]; + while (true) { + int64_t n = file->Read(buf, sizeof(buf)); + CHECK_NE(-1, n); + if (n == 0) { + break; + } + contents.append(buf, n); + } + return contents; +} + std::string PrettyDescriptor(const StringPiece& descriptor) { // Count the number of '['s to get the dimensionality. const char* c = descriptor.data(); diff --git a/src/utils.h b/src/utils.h index 541fbfa7d9..5c2a44ae5e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -151,6 +151,8 @@ std::string PrettyMethod(const Method* m, bool with_signature); // Given String.class, the output would be "java.lang.Class<java.lang.String>". std::string PrettyType(const Object* obj); +std::string ReadFileToString(const char* file_name); + } // namespace art #endif // ART_SRC_UTILS_H_ |