pike.git/
src/
code/
amd64.c
Branch:
Tag:
Non-build tags
All tags
No tags
2014-08-14
2014-08-14 13:36:53 by Per Hedbor <ph@opera.com>
da045c58493a736f524db4a8e53ea2c39fde5d7f (
87
lines) (+
87
/-
0
)
[
Show
|
Annotate
]
Branch:
8.0
Added F_ASSIGN_PRIVATE_TYPED_GLOBAL
[_AND_POP]
.
This completes the suite of private global opcodes.
3058:
ins_f_byte(F_MARK); ins_f_byte_with_2_args(F_EXTERNAL, b, c); return;
+
+
case F_ASSIGN_PRIVATE_TYPED_GLOBAL_AND_POP:
+
case F_ASSIGN_PRIVATE_TYPED_GLOBAL:
+
{
+
LABELS();
+
amd64_load_sp_reg();
+
+
ins_debug_instr_prologue(a-F_OFFSET, b, 0);
+
+
amd64_get_storage( P_REG_RBX, b );
+
+
/* do not assign anything if this object is destructed. */
+
+
/* we really only need to redo this check after we have called
+
some other function. It is sort of hard to know when that
+
happens while generating the code, however. Simply assigning
+
the global could in theory actually destruct this object (old
+
value includes something with a destroy that calls destruct on
+
this object...)
+
+
Note that nothing crash if we do the assign. We "just" leak the
+
variable when the storage is eventually free:d.
+
+
The generated code does look sort of silly, however.
+
*/
+
mov_mem_reg( fp_reg, OFFSETOF(pike_frame,current_object), ARG1_REG );
+
mov_mem_reg( ARG1_REG, OFFSETOF(object,prog), P_REG_RAX );
+
test_reg(P_REG_RAX);
+
jnz(&label_A);
+
+
/* will not return. */
+
amd64_call_c_function(object_low_set_index);
+
+
LABEL_A;
+
/* 1: check type of argument */
+
mov_mem8_reg( sp_reg, -sizeof(struct svalue )+OFFSETOF(svalue,tu.t.type), P_REG_RAX);
+
cmp_reg32_imm( P_REG_RAX, c );
+
je( &label_B );
+
+
/* not the same type. Fall back to use C-function (for code size mainly).. */
+
mov_reg_reg( P_REG_RBX, ARG1_REG );
+
mov_imm_reg( c, ARG2_REG );
+
add_reg_imm_reg( sp_reg, -sizeof(struct svalue), ARG3_REG );
+
amd64_call_c_function(assign_to_short_svalue);
+
/* pop stack if needed. */
+
if( a == F_ASSIGN_PRIVATE_GLOBAL_AND_POP )
+
{
+
amd64_add_sp(-1);
+
/* this will either have assigned 0 or thrown an error.
+
* if we assigned 0, it was because the argument evaluated as false.
+
* However, that means that we might possibly have to free it here..
+
*
+
* We do not even know that is has at least two references.
+
*/
+
amd64_free_svalue( sp_reg, 0 );
+
}
+
+
jmp( &label_E ); /* pop or not. */
+
+
LABEL_B;
+
/* at this point: o->storage + off in RBX. */
+
if( c >= MIN_REF_TYPE )
+
{
+
mov_mem_reg( P_REG_RBX, 0, P_REG_RAX );
+
test_reg(P_REG_RAX); /* old value == NULL? */
+
jz(&label_C);
+
+
/* deref. */
+
add_mem32_imm( P_REG_RAX, OFFSETOF(pike_string,refs), -1);
+
jnz(&label_C);
+
+
mov_reg_reg( P_REG_RBX, ARG1_REG );
+
mov_imm_reg( c, ARG2_REG );
+
amd64_call_c_function(really_free_short_svalue_ptr);
+
}
+
LABEL_C; /* old value is gone. Assign new value */
+
mov_mem_reg( sp_reg, -8, P_REG_RAX );
+
mov_reg_mem( P_REG_RAX, P_REG_RBX, 0 );
+
+
if( a == F_ASSIGN_PRIVATE_GLOBAL_AND_POP )
+
amd64_add_sp( -1 );
+
else if( c >= MIN_REF_TYPE )
+
add_mem_imm( P_REG_RAX, OFFSETOF(pike_string,refs), 1 );
+
LABEL_E;
+
}
+
return;
case F_PRIVATE_TYPED_GLOBAL: /* b -> off, c -> type */ ins_debug_instr_prologue(a-F_OFFSET, b, c);