def: dst/tagged-rep
literal: obj ;
-! These two are inserted by representation selection
+! These three are inserted by representation selection
INSN: ##load-tagged
def: dst/tagged-rep
literal: val ;
def: dst/double-rep
literal: val ;
+INSN: ##load-vector
+def: dst
+literal: val rep ;
+
! Stack operations
INSN: ##peek
def: dst/tagged-rep
! Copyright (C) 2010 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors combinators combinators.short-circuit kernel
-layouts locals make math namespaces sequences cpu.architecture
-compiler.cfg.registers
+USING: accessors byte-arrays combinators
+combinators.short-circuit kernel layouts locals make math
+namespaces sequences cpu.architecture compiler.cfg.registers
compiler.cfg.instructions
compiler.cfg.representations.rewrite
compiler.cfg.representations.selection ;
! if the architecture supports it
: convert-to-load-double? ( insn -- ? )
{
- [ drop load-double? ]
+ [ drop object-immediates? ]
[ dst>> rep-of double-rep? ]
[ obj>> float? ]
} 1&& ;
+: convert-to-load-vector? ( insn -- ? )
+ {
+ [ drop object-immediates? ]
+ [ dst>> rep-of vector-rep? ]
+ [ obj>> byte-array? ]
+ } 1&& ;
+
! When a literal zeroes/ones vector is unboxed, we replace the ##load-reference
! with a ##zero-vector or ##fill-vector instruction since this is more efficient.
: convert-to-zero-vector? ( insn -- ? )
[ obj>> B{ 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 } = ]
} 1&& ;
-: (convert-to-load-double) ( insn -- dst val )
- [ dst>> ] [ obj>> ] bi ; inline
-
-: (convert-to-zero/fill-vector) ( insn -- dst rep )
- dst>> dup rep-of ; inline
-
M: ##load-reference optimize-insn
{
{
[ dup convert-to-load-double? ]
- [ (convert-to-load-double) ##load-double here ]
+ [ [ dst>> ] [ obj>> ] bi ##load-double here ]
}
{
[ dup convert-to-zero-vector? ]
- [ (convert-to-zero/fill-vector) ##zero-vector here ]
+ [ dst>> dup rep-of ##zero-vector here ]
}
{
[ dup convert-to-fill-vector? ]
- [ (convert-to-zero/fill-vector) ##fill-vector here ]
+ [ dst>> dup rep-of ##fill-vector here ]
+ }
+ {
+ [ dup convert-to-load-vector? ]
+ [ [ dst>> ] [ obj>> ] [ dst>> rep-of ] tri ##load-vector here ]
}
[ call-next-method ]
} cond ;
CODEGEN: ##load-tagged %load-immediate
CODEGEN: ##load-reference %load-reference
CODEGEN: ##load-double %load-double
+CODEGEN: ##load-vector %load-vector
CODEGEN: ##peek %peek
CODEGEN: ##replace %replace
CODEGEN: ##inc-d %inc-d
: rel-float ( literal class -- )
[ add-literal ] dip rt-float rel-fixup ;
+: rel-byte-array ( literal class -- )
+ [ add-literal ] dip rt-byte-array rel-fixup ;
+
: rel-this ( class -- )
rt-this rel-fixup ;
CONSTANT: rt-decks-offset 11
CONSTANT: rt-exception-handler 12
CONSTANT: rt-float 13
+CONSTANT: rt-byte-array 14
: rc-absolute? ( n -- ? )
${
HOOK: %load-immediate cpu ( reg val -- )
HOOK: %load-reference cpu ( reg obj -- )
HOOK: %load-double cpu ( reg val -- )
+HOOK: %load-vector cpu ( reg val rep -- )
HOOK: %peek cpu ( vreg loc -- )
HOOK: %replace cpu ( vreg loc -- )
M: stack-params param-reg 2drop ;
-! Does this architecture support %load-double?
-HOOK: load-double? cpu ( -- ? )
+! Does this architecture support %load-double, %load-vector and
+! objects in %compare-imm?
+HOOK: object-immediates? cpu ( -- ? )
-M: object load-double? f ;
+M: object object-immediates? f ;
! Can this value be an immediate operand for %add-imm, %sub-imm,
! or %mul-imm?
M: x86.32 immediate-comparand? ( n -- ? )
[ call-next-method ] [ word? ] bi or ;
-M: x86.32 load-double? ( -- ? ) t ;
+M: x86.32 object-immediates? ( -- ? ) t ;
M: x86.32 %load-double ( dst val -- )
[ 0 [] MOVSD ] dip rc-absolute rel-float ;
+M:: x86.32 %load-vector ( dst val rep -- )
+ dst 0 [] rep copy-memory* val rc-absolute rel-byte-array ;
+
M: x86.32 %mov-vm-ptr ( reg -- )
0 MOV 0 rc-absolute-cell rel-vm ;
break;
#endif
default:
- critical_error("Bad rel type",op.rel_type());
+ critical_error("Bad rel type in store_external_address()",op.rel_type());
break;
}
}
case RT_FLOAT:
op.store_float(next_literal());
break;
+ case RT_BYTE_ARRAY:
+ op.store_byte_array(next_literal());
+ break;
case RT_ENTRY_POINT:
op.store_value(parent->compute_entry_point_address(next_literal()));
break;
case RT_FLOAT:
op.store_float(slot_forwarder.visit_pointer(op.load_float(old_offset)));
break;
+ case RT_BYTE_ARRAY:
+ op.store_byte_array(slot_forwarder.visit_pointer(op.load_byte_array(old_offset)));
+ break;
case RT_ENTRY_POINT:
case RT_ENTRY_POINT_PIC:
case RT_ENTRY_POINT_PIC_TAIL:
case RT_FLOAT:
op.store_float(data_visitor.visit_pointer(op.load_float(old_offset)));
break;
+ case RT_BYTE_ARRAY:
+ op.store_byte_array(data_visitor.visit_pointer(op.load_byte_array(old_offset)));
+ break;
case RT_ENTRY_POINT:
case RT_ENTRY_POINT_PIC:
case RT_ENTRY_POINT_PIC_TAIL:
return (cell)load_value(pointer) - boxed_float_offset;
}
+cell instruction_operand::load_byte_array()
+{
+ return (cell)load_value() - byte_array_offset;
+}
+
+cell instruction_operand::load_byte_array(cell pointer)
+{
+ return (cell)load_value(pointer) - byte_array_offset;
+}
+
code_block *instruction_operand::load_code_block(cell relative_to)
{
return ((code_block *)load_value(relative_to) - 1);
store_value((fixnum)value + boxed_float_offset);
}
+void instruction_operand::store_byte_array(cell value)
+{
+ store_value((fixnum)value + byte_array_offset);
+}
+
void instruction_operand::store_code_block(code_block *compiled)
{
store_value((cell)compiled->entry_point());
RT_EXCEPTION_HANDLER,
/* pointer to a float's payload */
RT_FLOAT,
+ /* pointer to a byte array's payload */
+ RT_BYTE_ARRAY,
};
case RT_DECKS_OFFSET:
case RT_EXCEPTION_HANDLER:
case RT_FLOAT:
+ case RT_BYTE_ARRAY:
return 0;
default:
- critical_error("Bad rel type",rel_type());
+ critical_error("Bad rel type in number_of_parameters()",rel_type());
return -1; /* Can't happen */
}
}
fixnum load_value();
cell load_float(cell relative_to);
cell load_float();
+ cell load_byte_array(cell relative_to);
+ cell load_byte_array();
code_block *load_code_block(cell relative_to);
code_block *load_code_block();
void store_value_masked(fixnum value, cell mask, cell shift);
void store_value(fixnum value);
void store_float(cell value);
+ void store_byte_array(cell value);
void store_code_block(code_block *compiled);
};
cell *data() const { return (cell *)(this + 1); }
};
+const cell byte_array_offset = 16 - BYTE_ARRAY_TYPE;
+
struct byte_array : public object {
static const cell type_number = BYTE_ARRAY_TYPE;
static const cell element_size = 1;
case RT_FLOAT:
op.store_float(visitor->visit_pointer(op.load_float()));
break;
+ case RT_BYTE_ARRAY:
+ op.store_byte_array(visitor->visit_pointer(op.load_byte_array()));
+ break;
default:
break;
}