8003195: AbstractAssembler should not store code pointers but use the CodeSection directly

Fri, 30 Nov 2012 11:44:05 -0800

author
twisti
date
Fri, 30 Nov 2012 11:44:05 -0800
changeset 4317
6ab62ad83507
parent 4316
1acccb7c0b01
child 4318
cd3d6a6b95d9

8003195: AbstractAssembler should not store code pointers but use the CodeSection directly
Reviewed-by: twisti, kvn
Contributed-by: Bharadwaj Yadavalli <bharadwaj.yadavalli@oracle.com>

src/cpu/x86/vm/assembler_x86.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/assembler_x86.hpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/assembler_x86.inline.hpp file | annotate | diff | comparison | revisions
src/share/vm/asm/assembler.cpp file | annotate | diff | comparison | revisions
src/share/vm/asm/assembler.hpp file | annotate | diff | comparison | revisions
src/share/vm/asm/assembler.inline.hpp file | annotate | diff | comparison | revisions
src/share/vm/asm/codeBuffer.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/cpu/x86/vm/assembler_x86.cpp	Tue Nov 27 17:41:38 2012 -0800
     1.2 +++ b/src/cpu/x86/vm/assembler_x86.cpp	Fri Nov 30 11:44:05 2012 -0800
     1.3 @@ -1154,7 +1154,7 @@
     1.4    assert(entry != NULL, "call most probably wrong");
     1.5    InstructionMark im(this);
     1.6    emit_byte(0xE8);
     1.7 -  intptr_t disp = entry - (_code_pos + sizeof(int32_t));
     1.8 +  intptr_t disp = entry - (pc() + sizeof(int32_t));
     1.9    assert(is_simm32(disp), "must be 32bit offset (call2)");
    1.10    // Technically, should use call32_operand, but this format is
    1.11    // implied by the fact that we're emitting a call instruction.
    1.12 @@ -1417,7 +1417,7 @@
    1.13  
    1.14      const int short_size = 2;
    1.15      const int long_size = 6;
    1.16 -    intptr_t offs = (intptr_t)dst - (intptr_t)_code_pos;
    1.17 +    intptr_t offs = (intptr_t)dst - (intptr_t)pc();
    1.18      if (maybe_short && is8bit(offs - short_size)) {
    1.19        // 0111 tttn #8-bit disp
    1.20        emit_byte(0x70 | cc);
    1.21 @@ -1447,14 +1447,14 @@
    1.22      const int short_size = 2;
    1.23      address entry = target(L);
    1.24  #ifdef ASSERT
    1.25 -    intptr_t dist = (intptr_t)entry - ((intptr_t)_code_pos + short_size);
    1.26 +    intptr_t dist = (intptr_t)entry - ((intptr_t)pc() + short_size);
    1.27      intptr_t delta = short_branch_delta();
    1.28      if (delta != 0) {
    1.29        dist += (dist < 0 ? (-delta) :delta);
    1.30      }
    1.31      assert(is8bit(dist), "Dispacement too large for a short jmp");
    1.32  #endif
    1.33 -    intptr_t offs = (intptr_t)entry - (intptr_t)_code_pos;
    1.34 +    intptr_t offs = (intptr_t)entry - (intptr_t)pc();
    1.35      // 0111 tttn #8-bit disp
    1.36      emit_byte(0x70 | cc);
    1.37      emit_byte((offs - short_size) & 0xFF);
    1.38 @@ -1480,7 +1480,7 @@
    1.39      InstructionMark im(this);
    1.40      const int short_size = 2;
    1.41      const int long_size = 5;
    1.42 -    intptr_t offs = entry - _code_pos;
    1.43 +    intptr_t offs = entry - pc();
    1.44      if (maybe_short && is8bit(offs - short_size)) {
    1.45        emit_byte(0xEB);
    1.46        emit_byte((offs - short_size) & 0xFF);
    1.47 @@ -1510,7 +1510,7 @@
    1.48    InstructionMark im(this);
    1.49    emit_byte(0xE9);
    1.50    assert(dest != NULL, "must have a target");
    1.51 -  intptr_t disp = dest - (_code_pos + sizeof(int32_t));
    1.52 +  intptr_t disp = dest - (pc() + sizeof(int32_t));
    1.53    assert(is_simm32(disp), "must be 32bit offset (jmp)");
    1.54    emit_data(disp, rspec.reloc(), call32_operand);
    1.55  }
    1.56 @@ -1521,14 +1521,14 @@
    1.57      address entry = target(L);
    1.58      assert(entry != NULL, "jmp most probably wrong");
    1.59  #ifdef ASSERT
    1.60 -    intptr_t dist = (intptr_t)entry - ((intptr_t)_code_pos + short_size);
    1.61 +    intptr_t dist = (intptr_t)entry - ((intptr_t)pc() + short_size);
    1.62      intptr_t delta = short_branch_delta();
    1.63      if (delta != 0) {
    1.64        dist += (dist < 0 ? (-delta) :delta);
    1.65      }
    1.66      assert(is8bit(dist), "Dispacement too large for a short jmp");
    1.67  #endif
    1.68 -    intptr_t offs = entry - _code_pos;
    1.69 +    intptr_t offs = entry - pc();
    1.70      emit_byte(0xEB);
    1.71      emit_byte((offs - short_size) & 0xFF);
    1.72    } else {
    1.73 @@ -4361,7 +4361,7 @@
    1.74    disp = (int64_t)adr._target - ((int64_t)CodeCache::high_bound() + sizeof(int));
    1.75    if (!is_simm32(disp)) return false;
    1.76  
    1.77 -  disp = (int64_t)adr._target - ((int64_t)_code_pos + sizeof(int));
    1.78 +  disp = (int64_t)adr._target - ((int64_t)pc() + sizeof(int));
    1.79  
    1.80    // Because rip relative is a disp + address_of_next_instruction and we
    1.81    // don't know the value of address_of_next_instruction we apply a fudge factor
    1.82 @@ -4392,7 +4392,7 @@
    1.83                              relocInfo::relocType rtype,
    1.84                              int format) {
    1.85    if (rtype == relocInfo::none) {
    1.86 -    emit_long64(data);
    1.87 +    emit_int64(data);
    1.88    } else {
    1.89      emit_data64(data, Relocation::spec_simple(rtype), format);
    1.90    }
    1.91 @@ -4410,7 +4410,7 @@
    1.92  #ifdef ASSERT
    1.93    check_relocation(rspec, format);
    1.94  #endif
    1.95 -  emit_long64(data);
    1.96 +  emit_int64(data);
    1.97  }
    1.98  
    1.99  int Assembler::prefix_and_encode(int reg_enc, bool byteinst) {
   1.100 @@ -4943,7 +4943,7 @@
   1.101    InstructionMark im(this);
   1.102    int encode = prefixq_and_encode(dst->encoding());
   1.103    emit_byte(0xB8 | encode);
   1.104 -  emit_long64(imm64);
   1.105 +  emit_int64(imm64);
   1.106  }
   1.107  
   1.108  void Assembler::mov_literal64(Register dst, intptr_t imm64, RelocationHolder const& rspec) {
   1.109 @@ -7891,7 +7891,7 @@
   1.110      relocate(dst.reloc());
   1.111      const int short_size = 2;
   1.112      const int long_size = 6;
   1.113 -    int offs = (intptr_t)dst.target() - ((intptr_t)_code_pos);
   1.114 +    int offs = (intptr_t)dst.target() - ((intptr_t)pc());
   1.115      if (dst.reloc() == relocInfo::none && is8bit(offs - short_size)) {
   1.116        // 0111 tttn #8-bit disp
   1.117        emit_byte(0x70 | cc);
     2.1 --- a/src/cpu/x86/vm/assembler_x86.hpp	Tue Nov 27 17:41:38 2012 -0800
     2.2 +++ b/src/cpu/x86/vm/assembler_x86.hpp	Fri Nov 30 11:44:05 2012 -0800
     2.3 @@ -706,8 +706,6 @@
     2.4    void check_relocation(RelocationHolder const& rspec, int format);
     2.5    #endif
     2.6  
     2.7 -  inline void emit_long64(jlong x);
     2.8 -
     2.9    void emit_data(jint data, relocInfo::relocType    rtype, int format);
    2.10    void emit_data(jint data, RelocationHolder const& rspec, int format);
    2.11    void emit_data64(jlong data, relocInfo::relocType rtype, int format = 0);
     3.1 --- a/src/cpu/x86/vm/assembler_x86.inline.hpp	Tue Nov 27 17:41:38 2012 -0800
     3.2 +++ b/src/cpu/x86/vm/assembler_x86.inline.hpp	Fri Nov 30 11:44:05 2012 -0800
     3.3 @@ -87,12 +87,6 @@
     3.4  
     3.5  inline void Assembler::prefix(Address adr, XMMRegister reg) {}
     3.6  inline void Assembler::prefixq(Address adr, XMMRegister reg) {}
     3.7 -#else
     3.8 -inline void Assembler::emit_long64(jlong x) {
     3.9 -  *(jlong*) _code_pos = x;
    3.10 -  _code_pos += sizeof(jlong);
    3.11 -  code_section()->set_end(_code_pos);
    3.12 -}
    3.13  #endif // _LP64
    3.14  
    3.15  #endif // CPU_X86_VM_ASSEMBLER_X86_INLINE_HPP
     4.1 --- a/src/share/vm/asm/assembler.cpp	Tue Nov 27 17:41:38 2012 -0800
     4.2 +++ b/src/share/vm/asm/assembler.cpp	Fri Nov 30 11:44:05 2012 -0800
     4.3 @@ -56,16 +56,13 @@
     4.4    if (code == NULL)  return;
     4.5    CodeSection* cs = code->insts();
     4.6    cs->clear_mark();   // new assembler kills old mark
     4.7 -  _code_section = cs;
     4.8 -  _code_begin  = cs->start();
     4.9 -  _code_limit  = cs->limit();
    4.10 -  _code_pos    = cs->end();
    4.11 -  _oop_recorder= code->oop_recorder();
    4.12 -  DEBUG_ONLY( _short_branch_delta = 0; )
    4.13 -  if (_code_begin == NULL)  {
    4.14 +  if (cs->start() == NULL)  {
    4.15      vm_exit_out_of_memory(0, err_msg("CodeCache: no room for %s",
    4.16                                       code->name()));
    4.17    }
    4.18 +  _code_section = cs;
    4.19 +  _oop_recorder= code->oop_recorder();
    4.20 +  DEBUG_ONLY( _short_branch_delta = 0; )
    4.21  }
    4.22  
    4.23  void AbstractAssembler::set_code_section(CodeSection* cs) {
    4.24 @@ -73,9 +70,6 @@
    4.25    assert(cs->is_allocated(), "need to pre-allocate this section");
    4.26    cs->clear_mark();  // new assembly into this section kills old mark
    4.27    _code_section = cs;
    4.28 -  _code_begin  = cs->start();
    4.29 -  _code_limit  = cs->limit();
    4.30 -  _code_pos    = cs->end();
    4.31  }
    4.32  
    4.33  // Inform CodeBuffer that incoming code and relocation will be for stubs
    4.34 @@ -83,7 +77,6 @@
    4.35    CodeBuffer*  cb = code();
    4.36    CodeSection* cs = cb->stubs();
    4.37    assert(_code_section == cb->insts(), "not in insts?");
    4.38 -  sync();
    4.39    if (cs->maybe_expand_to_ensure_remaining(required_space)
    4.40        && cb->blob() == NULL) {
    4.41      return NULL;
    4.42 @@ -96,7 +89,6 @@
    4.43  // Should not be called if start_a_stub() returned NULL
    4.44  void AbstractAssembler::end_a_stub() {
    4.45    assert(_code_section == code()->stubs(), "not in stubs?");
    4.46 -  sync();
    4.47    set_code_section(code()->insts());
    4.48  }
    4.49  
    4.50 @@ -105,7 +97,6 @@
    4.51    CodeBuffer*  cb = code();
    4.52    CodeSection* cs = cb->consts();
    4.53    assert(_code_section == cb->insts() || _code_section == cb->stubs(), "not in insts/stubs?");
    4.54 -  sync();
    4.55    address end = cs->end();
    4.56    int pad = -(intptr_t)end & (required_align-1);
    4.57    if (cs->maybe_expand_to_ensure_remaining(pad + required_space)) {
    4.58 @@ -124,12 +115,10 @@
    4.59  // in section cs (insts or stubs).
    4.60  void AbstractAssembler::end_a_const(CodeSection* cs) {
    4.61    assert(_code_section == code()->consts(), "not in consts?");
    4.62 -  sync();
    4.63    set_code_section(cs);
    4.64  }
    4.65  
    4.66  void AbstractAssembler::flush() {
    4.67 -  sync();
    4.68    ICache::invalidate_range(addr_at(0), offset());
    4.69  }
    4.70  
     5.1 --- a/src/share/vm/asm/assembler.hpp	Tue Nov 27 17:41:38 2012 -0800
     5.2 +++ b/src/share/vm/asm/assembler.hpp	Fri Nov 30 11:44:05 2012 -0800
     5.3 @@ -201,13 +201,10 @@
     5.4  
     5.5   protected:
     5.6    CodeSection* _code_section;          // section within the code buffer
     5.7 -  address      _code_begin;            // first byte of code buffer
     5.8 -  address      _code_limit;            // first byte after code buffer
     5.9 -  address      _code_pos;              // current code generation position
    5.10    OopRecorder* _oop_recorder;          // support for relocInfo::oop_type
    5.11  
    5.12    // Code emission & accessing
    5.13 -  address addr_at(int pos) const       { return _code_begin + pos; }
    5.14 +  inline address addr_at(int pos) const;
    5.15  
    5.16    // This routine is called with a label is used for an address.
    5.17    // Labels and displacements truck in offsets, but target must return a PC.
    5.18 @@ -217,10 +214,18 @@
    5.19    bool isByte(int x) const             { return 0 <= x && x < 0x100; }
    5.20    bool isShiftCount(int x) const       { return 0 <= x && x < 32; }
    5.21  
    5.22 -  void emit_byte(int x);  // emit a single byte
    5.23 -  void emit_word(int x);  // emit a 16-bit word (not a wordSize word!)
    5.24 -  void emit_long(jint x); // emit a 32-bit word (not a longSize word!)
    5.25 -  void emit_address(address x); // emit an address (not a longSize word!)
    5.26 +  void emit_byte(int x)  { emit_int8 (x); }  // deprecated
    5.27 +  void emit_word(int x)  { emit_int16(x); }  // deprecated
    5.28 +  void emit_long(jint x) { emit_int32(x); }  // deprecated
    5.29 +
    5.30 +  inline void emit_int8(  int8_t  x);
    5.31 +  inline void emit_int16( int16_t x);
    5.32 +  inline void emit_int32( int32_t x);
    5.33 +  inline void emit_int64( int64_t x);
    5.34 +
    5.35 +  inline void emit_float( jfloat  x);
    5.36 +  inline void emit_double(jdouble x);
    5.37 +  inline void emit_address(address x);
    5.38  
    5.39    // Instruction boundaries (required when emitting relocatable values).
    5.40    class InstructionMark: public StackObj {
    5.41 @@ -278,9 +283,6 @@
    5.42    // Creation
    5.43    AbstractAssembler(CodeBuffer* code);
    5.44  
    5.45 -  // save end pointer back to code buf.
    5.46 -  void sync();
    5.47 -
    5.48    // ensure buf contains all code (call this before using/copying the code)
    5.49    void flush();
    5.50  
    5.51 @@ -308,12 +310,13 @@
    5.52    static bool is_simm32(intptr_t x) { return is_simm(x, 32); }
    5.53  
    5.54    // Accessors
    5.55 -  CodeBuffer*   code() const;          // _code_section->outer()
    5.56    CodeSection*  code_section() const   { return _code_section; }
    5.57 -  int           sect() const;          // return _code_section->index()
    5.58 -  address       pc() const             { return _code_pos; }
    5.59 -  int           offset() const         { return _code_pos - _code_begin; }
    5.60 -  int           locator() const;       // CodeBuffer::locator(offset(), sect())
    5.61 +  inline CodeBuffer*   code() const;
    5.62 +  inline int           sect() const;
    5.63 +  inline address       pc() const;
    5.64 +  inline int           offset() const;
    5.65 +  inline int           locator() const;       // CodeBuffer::locator(offset(), sect())
    5.66 +
    5.67    OopRecorder*  oop_recorder() const   { return _oop_recorder; }
    5.68    void      set_oop_recorder(OopRecorder* r) { _oop_recorder = r; }
    5.69  
    5.70 @@ -358,8 +361,7 @@
    5.71      CodeSection* c1 = _code_section;
    5.72      address ptr = start_a_const(sizeof(c), sizeof(c));
    5.73      if (ptr != NULL) {
    5.74 -      *(jlong*)ptr = c;
    5.75 -      _code_pos = ptr + sizeof(c);
    5.76 +      emit_int64(c);
    5.77        end_a_const(c1);
    5.78      }
    5.79      return ptr;
    5.80 @@ -368,8 +370,7 @@
    5.81      CodeSection* c1 = _code_section;
    5.82      address ptr = start_a_const(sizeof(c), sizeof(c));
    5.83      if (ptr != NULL) {
    5.84 -      *(jdouble*)ptr = c;
    5.85 -      _code_pos = ptr + sizeof(c);
    5.86 +      emit_double(c);
    5.87        end_a_const(c1);
    5.88      }
    5.89      return ptr;
    5.90 @@ -378,8 +379,7 @@
    5.91      CodeSection* c1 = _code_section;
    5.92      address ptr = start_a_const(sizeof(c), sizeof(c));
    5.93      if (ptr != NULL) {
    5.94 -      *(jfloat*)ptr = c;
    5.95 -      _code_pos = ptr + sizeof(c);
    5.96 +      emit_float(c);
    5.97        end_a_const(c1);
    5.98      }
    5.99      return ptr;
   5.100 @@ -388,8 +388,7 @@
   5.101      CodeSection* c1 = _code_section;
   5.102      address ptr = start_a_const(sizeof(c), sizeof(c));
   5.103      if (ptr != NULL) {
   5.104 -      *(address*)ptr = c;
   5.105 -      _code_pos = ptr + sizeof(c);
   5.106 +      emit_address(c);
   5.107        end_a_const(c1);
   5.108      }
   5.109      return ptr;
   5.110 @@ -399,8 +398,7 @@
   5.111      address ptr = start_a_const(sizeof(c), sizeof(c));
   5.112      if (ptr != NULL) {
   5.113        relocate(rspec);
   5.114 -      *(address*)ptr = c;
   5.115 -      _code_pos = ptr + sizeof(c);
   5.116 +      emit_address(c);
   5.117        end_a_const(c1);
   5.118      }
   5.119      return ptr;
     6.1 --- a/src/share/vm/asm/assembler.inline.hpp	Tue Nov 27 17:41:38 2012 -0800
     6.2 +++ b/src/share/vm/asm/assembler.inline.hpp	Fri Nov 30 11:44:05 2012 -0800
     6.3 @@ -30,49 +30,27 @@
     6.4  #include "compiler/disassembler.hpp"
     6.5  #include "runtime/threadLocalStorage.hpp"
     6.6  
     6.7 -inline void AbstractAssembler::sync() {
     6.8 -  CodeSection* cs = code_section();
     6.9 -  guarantee(cs->start() == _code_begin, "must not shift code buffer");
    6.10 -  cs->set_end(_code_pos);
    6.11 +inline address AbstractAssembler::addr_at(int pos) const {
    6.12 +  return code_section()->start() + pos;
    6.13  }
    6.14  
    6.15 -inline void AbstractAssembler::emit_byte(int x) {
    6.16 -  assert(isByte(x), "not a byte");
    6.17 -  *(unsigned char*)_code_pos = (unsigned char)x;
    6.18 -  _code_pos += sizeof(unsigned char);
    6.19 -  sync();
    6.20 -}
    6.21 +void AbstractAssembler::emit_int8(int8_t x)     { code_section()->emit_int8 (x); }
    6.22 +void AbstractAssembler::emit_int16(int16_t x)   { code_section()->emit_int16(x); }
    6.23 +void AbstractAssembler::emit_int32(int32_t x)   { code_section()->emit_int32(x); }
    6.24 +void AbstractAssembler::emit_int64(int64_t x)   { code_section()->emit_int64(x); }
    6.25  
    6.26 -
    6.27 -inline void AbstractAssembler::emit_word(int x) {
    6.28 -  *(short*)_code_pos = (short)x;
    6.29 -  _code_pos += sizeof(short);
    6.30 -  sync();
    6.31 -}
    6.32 -
    6.33 -
    6.34 -inline void AbstractAssembler::emit_long(jint x) {
    6.35 -  *(jint*)_code_pos = x;
    6.36 -  _code_pos += sizeof(jint);
    6.37 -  sync();
    6.38 -}
    6.39 -
    6.40 -inline void AbstractAssembler::emit_address(address x) {
    6.41 -  *(address*)_code_pos = x;
    6.42 -  _code_pos += sizeof(address);
    6.43 -  sync();
    6.44 -}
    6.45 +void AbstractAssembler::emit_float(jfloat  x)   { code_section()->emit_float(x); }
    6.46 +void AbstractAssembler::emit_double(jdouble x)  { code_section()->emit_double(x); }
    6.47 +void AbstractAssembler::emit_address(address x) { code_section()->emit_address(x); }
    6.48  
    6.49  inline address AbstractAssembler::inst_mark() const {
    6.50    return code_section()->mark();
    6.51  }
    6.52  
    6.53 -
    6.54  inline void AbstractAssembler::set_inst_mark() {
    6.55    code_section()->set_mark();
    6.56  }
    6.57  
    6.58 -
    6.59  inline void AbstractAssembler::clear_inst_mark() {
    6.60    code_section()->clear_mark();
    6.61  }
    6.62 @@ -80,9 +58,9 @@
    6.63  
    6.64  inline void AbstractAssembler::relocate(RelocationHolder const& rspec, int format) {
    6.65    assert(!pd_check_instruction_mark()
    6.66 -         || inst_mark() == NULL || inst_mark() == _code_pos,
    6.67 +         || inst_mark() == NULL || inst_mark() == code_section()->end(),
    6.68           "call relocate() between instructions");
    6.69 -  code_section()->relocate(_code_pos, rspec, format);
    6.70 +  code_section()->relocate(code_section()->end(), rspec, format);
    6.71  }
    6.72  
    6.73  
    6.74 @@ -94,6 +72,14 @@
    6.75    return code_section()->index();
    6.76  }
    6.77  
    6.78 +inline address AbstractAssembler::pc() const {
    6.79 +  return code_section()->end();
    6.80 +}
    6.81 +
    6.82 +inline int AbstractAssembler::offset() const {
    6.83 +  return code_section()->size();
    6.84 +}
    6.85 +
    6.86  inline int AbstractAssembler::locator() const {
    6.87    return CodeBuffer::locator(offset(), sect());
    6.88  }
     7.1 --- a/src/share/vm/asm/codeBuffer.hpp	Tue Nov 27 17:41:38 2012 -0800
     7.2 +++ b/src/share/vm/asm/codeBuffer.hpp	Fri Nov 30 11:44:05 2012 -0800
     7.3 @@ -30,8 +30,6 @@
     7.4  #include "code/relocInfo.hpp"
     7.5  
     7.6  class  CodeComments;
     7.7 -class  AbstractAssembler;
     7.8 -class  MacroAssembler;
     7.9  class  PhaseCFG;
    7.10  class  Compile;
    7.11  class  BufferBlob;
    7.12 @@ -194,10 +192,14 @@
    7.13    }
    7.14  
    7.15    // Code emission
    7.16 -  void emit_int8 (int8_t  x) { *((int8_t*)  end()) = x; set_end(end() + 1); }
    7.17 -  void emit_int16(int16_t x) { *((int16_t*) end()) = x; set_end(end() + 2); }
    7.18 -  void emit_int32(int32_t x) { *((int32_t*) end()) = x; set_end(end() + 4); }
    7.19 -  void emit_int64(int64_t x) { *((int64_t*) end()) = x; set_end(end() + 8); }
    7.20 +  void emit_int8 ( int8_t  x)  { *((int8_t*)  end()) = x; set_end(end() + sizeof(int8_t)); }
    7.21 +  void emit_int16( int16_t x)  { *((int16_t*) end()) = x; set_end(end() + sizeof(int16_t)); }
    7.22 +  void emit_int32( int32_t x)  { *((int32_t*) end()) = x; set_end(end() + sizeof(int32_t)); }
    7.23 +  void emit_int64( int64_t x)  { *((int64_t*) end()) = x; set_end(end() + sizeof(int64_t)); }
    7.24 +
    7.25 +  void emit_float( jfloat  x)  { *((jfloat*)  end()) = x; set_end(end() + sizeof(jfloat)); }
    7.26 +  void emit_double(jdouble x)  { *((jdouble*) end()) = x; set_end(end() + sizeof(jdouble)); }
    7.27 +  void emit_address(address x) { *((address*) end()) = x; set_end(end() + sizeof(address)); }
    7.28  
    7.29    // Share a scratch buffer for relocinfo.  (Hacky; saves a resource allocation.)
    7.30    void initialize_shared_locs(relocInfo* buf, int length);

mercurial