Tue, 11 May 2010 14:35:43 -0700
6931180: Migration to recent versions of MS Platform SDK
6951582: Build problems on win64
Summary: Changes to enable building JDK7 with Microsoft Visual Studio 2010
Reviewed-by: ohair, art, ccheung, dcubed
duke@435 | 1 | /* |
jrose@1100 | 2 | * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. |
duke@435 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@435 | 4 | * |
duke@435 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@435 | 6 | * under the terms of the GNU General Public License version 2 only, as |
duke@435 | 7 | * published by the Free Software Foundation. |
duke@435 | 8 | * |
duke@435 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@435 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@435 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@435 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@435 | 13 | * accompanied this code). |
duke@435 | 14 | * |
duke@435 | 15 | * You should have received a copy of the GNU General Public License version |
duke@435 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@435 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@435 | 18 | * |
duke@435 | 19 | * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
duke@435 | 20 | * CA 95054 USA or visit www.sun.com if you need additional information or |
duke@435 | 21 | * have any questions. |
duke@435 | 22 | * |
duke@435 | 23 | */ |
duke@435 | 24 | |
twisti@1040 | 25 | // This file contains platform-independent assembler declarations. |
duke@435 | 26 | |
duke@435 | 27 | class CodeBuffer; |
duke@435 | 28 | class MacroAssembler; |
duke@435 | 29 | class AbstractAssembler; |
duke@435 | 30 | class Label; |
duke@435 | 31 | |
duke@435 | 32 | /** |
duke@435 | 33 | * Labels represent destinations for control transfer instructions. Such |
duke@435 | 34 | * instructions can accept a Label as their target argument. A Label is |
duke@435 | 35 | * bound to the current location in the code stream by calling the |
duke@435 | 36 | * MacroAssembler's 'bind' method, which in turn calls the Label's 'bind' |
duke@435 | 37 | * method. A Label may be referenced by an instruction before it's bound |
duke@435 | 38 | * (i.e., 'forward referenced'). 'bind' stores the current code offset |
duke@435 | 39 | * in the Label object. |
duke@435 | 40 | * |
duke@435 | 41 | * If an instruction references a bound Label, the offset field(s) within |
duke@435 | 42 | * the instruction are immediately filled in based on the Label's code |
duke@435 | 43 | * offset. If an instruction references an unbound label, that |
duke@435 | 44 | * instruction is put on a list of instructions that must be patched |
duke@435 | 45 | * (i.e., 'resolved') when the Label is bound. |
duke@435 | 46 | * |
duke@435 | 47 | * 'bind' will call the platform-specific 'patch_instruction' method to |
duke@435 | 48 | * fill in the offset field(s) for each unresolved instruction (if there |
duke@435 | 49 | * are any). 'patch_instruction' lives in one of the |
duke@435 | 50 | * cpu/<arch>/vm/assembler_<arch>* files. |
duke@435 | 51 | * |
duke@435 | 52 | * Instead of using a linked list of unresolved instructions, a Label has |
duke@435 | 53 | * an array of unresolved instruction code offsets. _patch_index |
duke@435 | 54 | * contains the total number of forward references. If the Label's array |
duke@435 | 55 | * overflows (i.e., _patch_index grows larger than the array size), a |
duke@435 | 56 | * GrowableArray is allocated to hold the remaining offsets. (The cache |
duke@435 | 57 | * size is 4 for now, which handles over 99.5% of the cases) |
duke@435 | 58 | * |
duke@435 | 59 | * Labels may only be used within a single CodeSection. If you need |
duke@435 | 60 | * to create references between code sections, use explicit relocations. |
duke@435 | 61 | */ |
duke@435 | 62 | class Label VALUE_OBJ_CLASS_SPEC { |
duke@435 | 63 | private: |
duke@435 | 64 | enum { PatchCacheSize = 4 }; |
duke@435 | 65 | |
duke@435 | 66 | // _loc encodes both the binding state (via its sign) |
duke@435 | 67 | // and the binding locator (via its value) of a label. |
duke@435 | 68 | // |
duke@435 | 69 | // _loc >= 0 bound label, loc() encodes the target (jump) position |
duke@435 | 70 | // _loc == -1 unbound label |
duke@435 | 71 | int _loc; |
duke@435 | 72 | |
duke@435 | 73 | // References to instructions that jump to this unresolved label. |
duke@435 | 74 | // These instructions need to be patched when the label is bound |
duke@435 | 75 | // using the platform-specific patchInstruction() method. |
duke@435 | 76 | // |
duke@435 | 77 | // To avoid having to allocate from the C-heap each time, we provide |
duke@435 | 78 | // a local cache and use the overflow only if we exceed the local cache |
duke@435 | 79 | int _patches[PatchCacheSize]; |
duke@435 | 80 | int _patch_index; |
duke@435 | 81 | GrowableArray<int>* _patch_overflow; |
duke@435 | 82 | |
duke@435 | 83 | Label(const Label&) { ShouldNotReachHere(); } |
duke@435 | 84 | |
duke@435 | 85 | public: |
duke@435 | 86 | |
duke@435 | 87 | /** |
duke@435 | 88 | * After binding, be sure 'patch_instructions' is called later to link |
duke@435 | 89 | */ |
duke@435 | 90 | void bind_loc(int loc) { |
duke@435 | 91 | assert(loc >= 0, "illegal locator"); |
duke@435 | 92 | assert(_loc == -1, "already bound"); |
duke@435 | 93 | _loc = loc; |
duke@435 | 94 | } |
duke@435 | 95 | void bind_loc(int pos, int sect); // = bind_loc(locator(pos, sect)) |
duke@435 | 96 | |
duke@435 | 97 | #ifndef PRODUCT |
duke@435 | 98 | // Iterates over all unresolved instructions for printing |
duke@435 | 99 | void print_instructions(MacroAssembler* masm) const; |
duke@435 | 100 | #endif // PRODUCT |
duke@435 | 101 | |
duke@435 | 102 | /** |
duke@435 | 103 | * Returns the position of the the Label in the code buffer |
duke@435 | 104 | * The position is a 'locator', which encodes both offset and section. |
duke@435 | 105 | */ |
duke@435 | 106 | int loc() const { |
duke@435 | 107 | assert(_loc >= 0, "unbound label"); |
duke@435 | 108 | return _loc; |
duke@435 | 109 | } |
duke@435 | 110 | int loc_pos() const; // == locator_pos(loc()) |
duke@435 | 111 | int loc_sect() const; // == locator_sect(loc()) |
duke@435 | 112 | |
duke@435 | 113 | bool is_bound() const { return _loc >= 0; } |
duke@435 | 114 | bool is_unbound() const { return _loc == -1 && _patch_index > 0; } |
duke@435 | 115 | bool is_unused() const { return _loc == -1 && _patch_index == 0; } |
duke@435 | 116 | |
duke@435 | 117 | /** |
duke@435 | 118 | * Adds a reference to an unresolved displacement instruction to |
duke@435 | 119 | * this unbound label |
duke@435 | 120 | * |
duke@435 | 121 | * @param cb the code buffer being patched |
duke@435 | 122 | * @param branch_loc the locator of the branch instruction in the code buffer |
duke@435 | 123 | */ |
duke@435 | 124 | void add_patch_at(CodeBuffer* cb, int branch_loc); |
duke@435 | 125 | |
duke@435 | 126 | /** |
duke@435 | 127 | * Iterate over the list of patches, resolving the instructions |
duke@435 | 128 | * Call patch_instruction on each 'branch_loc' value |
duke@435 | 129 | */ |
duke@435 | 130 | void patch_instructions(MacroAssembler* masm); |
duke@435 | 131 | |
duke@435 | 132 | void init() { |
duke@435 | 133 | _loc = -1; |
duke@435 | 134 | _patch_index = 0; |
duke@435 | 135 | _patch_overflow = NULL; |
duke@435 | 136 | } |
duke@435 | 137 | |
duke@435 | 138 | Label() { |
duke@435 | 139 | init(); |
duke@435 | 140 | } |
duke@435 | 141 | }; |
duke@435 | 142 | |
jrose@1057 | 143 | // A union type for code which has to assemble both constant and |
jrose@1057 | 144 | // non-constant operands, when the distinction cannot be made |
jrose@1057 | 145 | // statically. |
jrose@1100 | 146 | class RegisterOrConstant VALUE_OBJ_CLASS_SPEC { |
jrose@1057 | 147 | private: |
jrose@1057 | 148 | Register _r; |
jrose@1057 | 149 | intptr_t _c; |
jrose@1057 | 150 | |
jrose@1057 | 151 | public: |
jrose@1100 | 152 | RegisterOrConstant(): _r(noreg), _c(0) {} |
jrose@1100 | 153 | RegisterOrConstant(Register r): _r(r), _c(0) {} |
jrose@1100 | 154 | RegisterOrConstant(intptr_t c): _r(noreg), _c(c) {} |
jrose@1057 | 155 | |
jrose@1057 | 156 | Register as_register() const { assert(is_register(),""); return _r; } |
jrose@1057 | 157 | intptr_t as_constant() const { assert(is_constant(),""); return _c; } |
jrose@1057 | 158 | |
jrose@1057 | 159 | Register register_or_noreg() const { return _r; } |
jrose@1057 | 160 | intptr_t constant_or_zero() const { return _c; } |
jrose@1057 | 161 | |
jrose@1057 | 162 | bool is_register() const { return _r != noreg; } |
jrose@1057 | 163 | bool is_constant() const { return _r == noreg; } |
jrose@1057 | 164 | }; |
duke@435 | 165 | |
duke@435 | 166 | // The Abstract Assembler: Pure assembler doing NO optimizations on the |
duke@435 | 167 | // instruction level; i.e., what you write is what you get. |
duke@435 | 168 | // The Assembler is generating code into a CodeBuffer. |
duke@435 | 169 | class AbstractAssembler : public ResourceObj { |
duke@435 | 170 | friend class Label; |
duke@435 | 171 | |
duke@435 | 172 | protected: |
duke@435 | 173 | CodeSection* _code_section; // section within the code buffer |
duke@435 | 174 | address _code_begin; // first byte of code buffer |
duke@435 | 175 | address _code_limit; // first byte after code buffer |
duke@435 | 176 | address _code_pos; // current code generation position |
duke@435 | 177 | OopRecorder* _oop_recorder; // support for relocInfo::oop_type |
duke@435 | 178 | |
duke@435 | 179 | // Code emission & accessing |
duke@435 | 180 | address addr_at(int pos) const { return _code_begin + pos; } |
duke@435 | 181 | |
duke@435 | 182 | // This routine is called with a label is used for an address. |
duke@435 | 183 | // Labels and displacements truck in offsets, but target must return a PC. |
duke@435 | 184 | address target(Label& L); // return _code_section->target(L) |
duke@435 | 185 | |
duke@435 | 186 | bool is8bit(int x) const { return -0x80 <= x && x < 0x80; } |
duke@435 | 187 | bool isByte(int x) const { return 0 <= x && x < 0x100; } |
duke@435 | 188 | bool isShiftCount(int x) const { return 0 <= x && x < 32; } |
duke@435 | 189 | |
duke@435 | 190 | void emit_byte(int x); // emit a single byte |
duke@435 | 191 | void emit_word(int x); // emit a 16-bit word (not a wordSize word!) |
duke@435 | 192 | void emit_long(jint x); // emit a 32-bit word (not a longSize word!) |
duke@435 | 193 | void emit_address(address x); // emit an address (not a longSize word!) |
duke@435 | 194 | |
duke@435 | 195 | // Instruction boundaries (required when emitting relocatable values). |
duke@435 | 196 | class InstructionMark: public StackObj { |
duke@435 | 197 | private: |
duke@435 | 198 | AbstractAssembler* _assm; |
duke@435 | 199 | |
duke@435 | 200 | public: |
duke@435 | 201 | InstructionMark(AbstractAssembler* assm) : _assm(assm) { |
duke@435 | 202 | assert(assm->inst_mark() == NULL, "overlapping instructions"); |
duke@435 | 203 | _assm->set_inst_mark(); |
duke@435 | 204 | } |
duke@435 | 205 | ~InstructionMark() { |
duke@435 | 206 | _assm->clear_inst_mark(); |
duke@435 | 207 | } |
duke@435 | 208 | }; |
duke@435 | 209 | friend class InstructionMark; |
duke@435 | 210 | #ifdef ASSERT |
duke@435 | 211 | // Make it return true on platforms which need to verify |
duke@435 | 212 | // instruction boundaries for some operations. |
duke@435 | 213 | inline static bool pd_check_instruction_mark(); |
duke@435 | 214 | #endif |
duke@435 | 215 | |
duke@435 | 216 | // Label functions |
duke@435 | 217 | void print(Label& L); |
duke@435 | 218 | |
duke@435 | 219 | public: |
duke@435 | 220 | |
duke@435 | 221 | // Creation |
duke@435 | 222 | AbstractAssembler(CodeBuffer* code); |
duke@435 | 223 | |
duke@435 | 224 | // save end pointer back to code buf. |
duke@435 | 225 | void sync(); |
duke@435 | 226 | |
duke@435 | 227 | // ensure buf contains all code (call this before using/copying the code) |
duke@435 | 228 | void flush(); |
duke@435 | 229 | |
duke@435 | 230 | // Accessors |
duke@435 | 231 | CodeBuffer* code() const; // _code_section->outer() |
duke@435 | 232 | CodeSection* code_section() const { return _code_section; } |
duke@435 | 233 | int sect() const; // return _code_section->index() |
duke@435 | 234 | address pc() const { return _code_pos; } |
duke@435 | 235 | int offset() const { return _code_pos - _code_begin; } |
duke@435 | 236 | int locator() const; // CodeBuffer::locator(offset(), sect()) |
duke@435 | 237 | OopRecorder* oop_recorder() const { return _oop_recorder; } |
duke@435 | 238 | void set_oop_recorder(OopRecorder* r) { _oop_recorder = r; } |
duke@435 | 239 | |
duke@435 | 240 | address inst_mark() const; |
duke@435 | 241 | void set_inst_mark(); |
duke@435 | 242 | void clear_inst_mark(); |
duke@435 | 243 | |
duke@435 | 244 | // Constants in code |
duke@435 | 245 | void a_byte(int x); |
duke@435 | 246 | void a_long(jint x); |
duke@435 | 247 | void relocate(RelocationHolder const& rspec, int format = 0); |
duke@435 | 248 | void relocate( relocInfo::relocType rtype, int format = 0) { |
duke@435 | 249 | if (rtype != relocInfo::none) |
duke@435 | 250 | relocate(Relocation::spec_simple(rtype), format); |
duke@435 | 251 | } |
duke@435 | 252 | |
duke@435 | 253 | static int code_fill_byte(); // used to pad out odd-sized code buffers |
duke@435 | 254 | |
duke@435 | 255 | // Associate a comment with the current offset. It will be printed |
duke@435 | 256 | // along with the disassembly when printing nmethods. Currently |
duke@435 | 257 | // only supported in the instruction section of the code buffer. |
duke@435 | 258 | void block_comment(const char* comment); |
duke@435 | 259 | |
duke@435 | 260 | // Label functions |
duke@435 | 261 | void bind(Label& L); // binds an unbound label L to the current code position |
duke@435 | 262 | |
duke@435 | 263 | // Move to a different section in the same code buffer. |
duke@435 | 264 | void set_code_section(CodeSection* cs); |
duke@435 | 265 | |
duke@435 | 266 | // Inform assembler when generating stub code and relocation info |
duke@435 | 267 | address start_a_stub(int required_space); |
duke@435 | 268 | void end_a_stub(); |
duke@435 | 269 | // Ditto for constants. |
duke@435 | 270 | address start_a_const(int required_space, int required_align = sizeof(double)); |
duke@435 | 271 | void end_a_const(); |
duke@435 | 272 | |
duke@435 | 273 | // fp constants support |
duke@435 | 274 | address double_constant(jdouble c) { |
duke@435 | 275 | address ptr = start_a_const(sizeof(c), sizeof(c)); |
duke@435 | 276 | if (ptr != NULL) { |
duke@435 | 277 | *(jdouble*)ptr = c; |
duke@435 | 278 | _code_pos = ptr + sizeof(c); |
duke@435 | 279 | end_a_const(); |
duke@435 | 280 | } |
duke@435 | 281 | return ptr; |
duke@435 | 282 | } |
duke@435 | 283 | address float_constant(jfloat c) { |
duke@435 | 284 | address ptr = start_a_const(sizeof(c), sizeof(c)); |
duke@435 | 285 | if (ptr != NULL) { |
duke@435 | 286 | *(jfloat*)ptr = c; |
duke@435 | 287 | _code_pos = ptr + sizeof(c); |
duke@435 | 288 | end_a_const(); |
duke@435 | 289 | } |
duke@435 | 290 | return ptr; |
duke@435 | 291 | } |
duke@435 | 292 | address address_constant(address c, RelocationHolder const& rspec) { |
duke@435 | 293 | address ptr = start_a_const(sizeof(c), sizeof(c)); |
duke@435 | 294 | if (ptr != NULL) { |
duke@435 | 295 | relocate(rspec); |
duke@435 | 296 | *(address*)ptr = c; |
duke@435 | 297 | _code_pos = ptr + sizeof(c); |
duke@435 | 298 | end_a_const(); |
duke@435 | 299 | } |
duke@435 | 300 | return ptr; |
duke@435 | 301 | } |
duke@435 | 302 | inline address address_constant(Label& L); |
duke@435 | 303 | inline address address_table_constant(GrowableArray<Label*> label); |
duke@435 | 304 | |
jrose@1057 | 305 | // Bootstrapping aid to cope with delayed determination of constants. |
jrose@1057 | 306 | // Returns a static address which will eventually contain the constant. |
jrose@1057 | 307 | // The value zero (NULL) stands instead of a constant which is still uncomputed. |
jrose@1057 | 308 | // Thus, the eventual value of the constant must not be zero. |
jrose@1057 | 309 | // This is fine, since this is designed for embedding object field |
jrose@1057 | 310 | // offsets in code which must be generated before the object class is loaded. |
jrose@1057 | 311 | // Field offsets are never zero, since an object's header (mark word) |
jrose@1057 | 312 | // is located at offset zero. |
jrose@1100 | 313 | RegisterOrConstant delayed_value(int(*value_fn)(), Register tmp, int offset = 0) { |
jrose@1100 | 314 | return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); |
jrose@1057 | 315 | } |
jrose@1100 | 316 | RegisterOrConstant delayed_value(address(*value_fn)(), Register tmp, int offset = 0) { |
jrose@1100 | 317 | return delayed_value_impl(delayed_value_addr(value_fn), tmp, offset); |
jrose@1057 | 318 | } |
jrose@1100 | 319 | virtual RegisterOrConstant delayed_value_impl(intptr_t* delayed_value_addr, Register tmp, int offset) = 0; |
jrose@1057 | 320 | // Last overloading is platform-dependent; look in assembler_<arch>.cpp. |
jrose@1057 | 321 | static intptr_t* delayed_value_addr(int(*constant_fn)()); |
jrose@1057 | 322 | static intptr_t* delayed_value_addr(address(*constant_fn)()); |
jrose@1057 | 323 | static void update_delayed_values(); |
jrose@1057 | 324 | |
duke@435 | 325 | // Bang stack to trigger StackOverflowError at a safe location |
duke@435 | 326 | // implementation delegates to machine-specific bang_stack_with_offset |
duke@435 | 327 | void generate_stack_overflow_check( int frame_size_in_bytes ); |
duke@435 | 328 | virtual void bang_stack_with_offset(int offset) = 0; |
duke@435 | 329 | |
duke@435 | 330 | |
duke@435 | 331 | /** |
duke@435 | 332 | * A platform-dependent method to patch a jump instruction that refers |
duke@435 | 333 | * to this label. |
duke@435 | 334 | * |
duke@435 | 335 | * @param branch the location of the instruction to patch |
duke@435 | 336 | * @param masm the assembler which generated the branch |
duke@435 | 337 | */ |
duke@435 | 338 | void pd_patch_instruction(address branch, address target); |
duke@435 | 339 | |
duke@435 | 340 | #ifndef PRODUCT |
duke@435 | 341 | /** |
duke@435 | 342 | * Platform-dependent method of printing an instruction that needs to be |
duke@435 | 343 | * patched. |
duke@435 | 344 | * |
duke@435 | 345 | * @param branch the instruction to be patched in the buffer. |
duke@435 | 346 | */ |
duke@435 | 347 | static void pd_print_patched_instruction(address branch); |
duke@435 | 348 | #endif // PRODUCT |
duke@435 | 349 | }; |
duke@435 | 350 | |
duke@435 | 351 | #include "incls/_assembler_pd.hpp.incl" |