Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4424890
glue.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
29 KB
Referenced Files
None
Subscribers
None
glue.c
View Options
#ifdef ANT_JIT
#include
<math.h>
#include
"silver/glue.h"
#include
"utf8.h"
#include
"internal.h"
#include
"errors.h"
#include
"ops/globals.h"
#include
"ops/property.h"
#include
"ops/iteration.h"
#include
"ops/upvalues.h"
#include
"ops/comparison.h"
#include
"ops/calls.h"
bool
jit_helper_stack_overflow
(
ant_t
*
js
)
{
volatile
char
marker
;
uintptr_t
curr
=
(
uintptr_t
)
&
marker
;
if
(
js
->
cstk
.
limit
==
0
||
js
->
cstk
.
base
==
NULL
)
return
false
;
uintptr_t
base
=
(
uintptr_t
)
js
->
cstk
.
base
;
size_t
used
=
(
base
>
curr
)
?
(
base
-
curr
)
:
(
curr
-
base
);
return
used
>
js
->
cstk
.
limit
;
}
ant_value_t
jit_helper_stack_overflow_error
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
return
js_mkerr_typed
(
js
,
JS_ERR_RANGE
|
JS_ERR_NO_STACK
,
"Maximum JIT call stack size exceeded"
);
}
ant_value_t
jit_helper_add
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
tov
(
tod
(
l
)
+
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_sub
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
tov
(
tod
(
l
)
-
tod
(
r
));
if
((
vtype
(
l
)
==
T_NUM
||
vtype
(
l
)
==
T_STR
)
&&
(
vtype
(
r
)
==
T_NUM
||
vtype
(
r
)
==
T_STR
))
{
double
ld
=
(
vtype
(
l
)
==
T_NUM
)
?
tod
(
l
)
:
js_to_number
(
js
,
l
);
double
rd
=
(
vtype
(
r
)
==
T_NUM
)
?
tod
(
r
)
:
js_to_number
(
js
,
r
);
return
tov
(
ld
-
rd
);
}
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_mul
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
tov
(
tod
(
l
)
*
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_div
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
tov
(
tod
(
l
)
/
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_mod
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
tov
(
fmod
(
tod
(
l
),
tod
(
r
)));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_str_append_local
(
sv_vm_t
*
vm
,
ant_t
*
js
,
sv_func_t
*
func
,
ant_value_t
*
args
,
int
argc
,
ant_value_t
*
locals
,
uint16_t
slot_idx
,
ant_value_t
rhs
)
{
if
(
!
func
)
return
SV_JIT_BAILOUT
;
sv_frame_t
frame
=
{
.
func
=
func
,
.
bp
=
args
,
.
lp
=
locals
,
.
argc
=
argc
,
.
arguments_obj
=
js_mkundef
(),
};
return
sv_string_builder_append_slot
(
vm
,
js
,
&
frame
,
func
,
slot_idx
,
rhs
);
}
ant_value_t
jit_helper_str_append_local_snapshot
(
sv_vm_t
*
vm
,
ant_t
*
js
,
sv_func_t
*
func
,
ant_value_t
*
args
,
int
argc
,
ant_value_t
*
locals
,
uint16_t
slot_idx
,
ant_value_t
lhs
,
ant_value_t
rhs
)
{
if
(
!
func
)
return
SV_JIT_BAILOUT
;
sv_frame_t
frame
=
{
.
func
=
func
,
.
bp
=
args
,
.
lp
=
locals
,
.
argc
=
argc
,
.
arguments_obj
=
js_mkundef
(),
};
return
sv_string_builder_append_snapshot_slot
(
vm
,
js
,
&
frame
,
func
,
slot_idx
,
lhs
,
rhs
);
}
ant_value_t
jit_helper_str_flush_local
(
sv_vm_t
*
vm
,
ant_t
*
js
,
sv_func_t
*
func
,
ant_value_t
*
args
,
int
argc
,
ant_value_t
*
locals
,
uint16_t
slot_idx
)
{
if
(
!
func
)
return
SV_JIT_BAILOUT
;
sv_frame_t
frame
=
{
.
func
=
func
,
.
bp
=
args
,
.
lp
=
locals
,
.
argc
=
argc
,
.
arguments_obj
=
js_mkundef
(),
};
ant_value_t
flush
=
sv_string_builder_flush_slot
(
vm
,
js
,
&
frame
,
slot_idx
);
if
(
is_err
(
flush
))
return
flush
;
return
js_mkundef
();
}
ant_value_t
jit_helper_lt
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
js_bool
(
tod
(
l
)
<
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_le
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
js_bool
(
tod
(
l
)
<=
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_call
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
func
,
ant_value_t
this_val
,
ant_value_t
*
args
,
int
argc
)
{
return
sv_vm_call
(
vm
,
js
,
func
,
this_val
,
args
,
argc
,
NULL
,
false
);
}
ant_value_t
jit_helper_call_method
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
func
,
ant_value_t
this_val
,
ant_value_t
*
args
,
int
argc
,
ant_value_t
super_val
,
ant_value_t
new_target
,
ant_value_t
*
out_this
)
{
bool
is_super_call
=
(
vtype
(
super_val
)
!=
T_UNDEF
&&
func
==
super_val
);
ant_value_t
call_this
=
this_val
;
if
(
is_super_call
)
js
->
new_target
=
new_target
;
ant_value_t
super_this
=
call_this
;
ant_value_t
result
=
sv_vm_call
(
vm
,
js
,
func
,
call_this
,
args
,
argc
,
is_super_call
?
&
super_this
:
NULL
,
is_super_call
);
if
(
out_this
)
{
if
(
is_super_call
&&
!
is_err
(
result
))
*
out_this
=
is_object_type
(
result
)
?
result
:
super_this
;
else
*
out_this
=
call_this
;
}
return
result
;
}
ant_value_t
jit_helper_apply
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
func
,
ant_value_t
this_val
,
ant_value_t
*
args
,
int
argc
)
{
sv_call_args_t
call
;
sv_call_args_reset
(
&
call
,
args
,
argc
);
ant_value_t
norm
=
sv_apply_normalize_args
(
js
,
&
call
);
if
(
is_err
(
norm
))
return
norm
;
ant_value_t
result
=
sv_vm_call
(
vm
,
js
,
func
,
this_val
,
call
.
args
,
call
.
argc
,
NULL
,
false
);
sv_call_args_release
(
&
call
);
return
result
;
}
ant_value_t
jit_helper_rest
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
*
args
,
int
argc
,
int
start
)
{
ant_value_t
arr
=
js_mkarr
(
js
);
for
(
int
i
=
start
;
i
<
argc
;
i
++
)
js_arr_push
(
js
,
arr
,
args
[
i
]);
return
arr
;
}
ant_value_t
jit_helper_get_global
(
ant_t
*
js
,
const
char
*
str
,
sv_func_t
*
func
,
int32_t
bc_off
)
{
uint8_t
*
ip
=
NULL
;
if
(
func
&&
bc_off
>=
0
&&
bc_off
<
func
->
code_len
)
ip
=
func
->
code
+
bc_off
;
return
sv_global_get_interned_ic
(
js
,
str
,
func
,
ip
);
}
ant_value_t
jit_helper_special_obj
(
sv_vm_t
*
vm
,
ant_t
*
js
,
uint32_t
which
)
{
if
(
which
==
1
)
return
sv_vm_get_new_target
(
vm
,
js
);
if
(
which
==
2
)
return
sv_vm_get_super_val
(
vm
);
if
(
which
==
3
)
return
js_get_module_import_binding
(
js
);
return
js_mkundef
();
}
void
jit_helper_define_method_comp
(
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
key
,
ant_value_t
fn
,
uint8_t
flags
)
{
ant_value_t
desc_obj
=
js_as_obj
(
obj
);
bool
is_getter
=
(
flags
&
1
)
!=
0
;
bool
is_setter
=
(
flags
&
2
)
!=
0
;
if
(
vtype
(
key
)
==
T_SYMBOL
)
{
if
(
is_getter
)
{
js_set_sym_getter_desc
(
js
,
desc_obj
,
key
,
fn
,
JS_DESC_E
|
JS_DESC_C
);
return
;
}
if
(
is_setter
)
{
js_set_sym_setter_desc
(
js
,
desc_obj
,
key
,
fn
,
JS_DESC_E
|
JS_DESC_C
);
return
;
}
js_set_sym
(
js
,
obj
,
key
,
fn
);
return
;
}
ant_value_t
key_str
=
sv_key_to_propstr
(
js
,
key
);
if
((
is_getter
||
is_setter
)
&&
vtype
(
key_str
)
==
T_STR
)
{
ant_offset_t
klen
=
0
;
ant_offset_t
koff
=
vstr
(
js
,
key_str
,
&
klen
);
const
char
*
kptr
=
(
const
char
*
)(
uintptr_t
)(
koff
);
if
(
is_getter
)
js_set_getter_desc
(
js
,
desc_obj
,
kptr
,
klen
,
fn
,
JS_DESC_E
|
JS_DESC_C
);
else
js_set_setter_desc
(
js
,
desc_obj
,
kptr
,
klen
,
fn
,
JS_DESC_E
|
JS_DESC_C
);
return
;
}
if
(
vtype
(
key_str
)
==
T_STR
)
{
ant_offset_t
klen
=
0
;
ant_offset_t
koff
=
vstr
(
js
,
key_str
,
&
klen
);
const
char
*
kptr
=
(
const
char
*
)(
uintptr_t
)(
koff
);
js_define_own_prop
(
js
,
obj
,
kptr
,
(
size_t
)
klen
,
fn
);
}
else
mkprop
(
js
,
obj
,
key_str
,
fn
,
0
);
}
static
ant_value_t
jit_iter_advance_from_buf
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
*
iter_buf
,
int
hint
,
ant_value_t
*
out_value
,
bool
*
out_done
)
{
GC_ROOT_SAVE
(
root_mark
,
js
);
int
tag
=
hint
?
hint
:
(
int
)
js_getnum
(
iter_buf
[
2
]);
switch
(
tag
)
{
case
SV_ITER_ARRAY
:
{
ant_value_t
arr
=
iter_buf
[
0
];
GC_ROOT_PIN
(
js
,
arr
);
int
idx
=
(
int
)
js_getnum
(
iter_buf
[
1
]);
ant_offset_t
len
=
js_arr_len
(
js
,
arr
);
if
(
idx
>=
(
int
)
len
)
{
*
out_value
=
js_mkundef
();
*
out_done
=
true
;
}
else
{
*
out_value
=
js_arr_get
(
js
,
arr
,
(
ant_offset_t
)
idx
);
*
out_done
=
false
;
iter_buf
[
1
]
=
tov
(
idx
+
1
);
}
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
case
SV_ITER_MAP
:
{
map_iterator_state_t
*
st
=
(
map_iterator_state_t
*
)(
uintptr_t
)
js_getnum
(
iter_buf
[
0
]);
if
(
!
st
->
current
)
{
*
out_value
=
js_mkundef
();
*
out_done
=
true
;
}
else
{
map_entry_t
*
entry
=
st
->
current
;
ant_value_t
value
;
switch
(
st
->
type
)
{
case
ITER_TYPE_MAP_VALUES
:
value
=
entry
->
value
;
break
;
case
ITER_TYPE_MAP_KEYS
:
value
=
entry
->
key_val
;
break
;
case
ITER_TYPE_MAP_ENTRIES
:
{
ant_value_t
pair
=
js_mkarr
(
js
);
js_arr_push
(
js
,
pair
,
entry
->
key_val
);
js_arr_push
(
js
,
pair
,
entry
->
value
);
value
=
pair
;
break
;
}
default
:
value
=
js_mkundef
();
}
st
->
current
=
entry
->
hh
.
next
;
*
out_value
=
value
;
*
out_done
=
false
;
}
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
case
SV_ITER_SET
:
{
set_iterator_state_t
*
st
=
(
set_iterator_state_t
*
)(
uintptr_t
)
js_getnum
(
iter_buf
[
0
]);
if
(
!
st
->
current
)
{
*
out_value
=
js_mkundef
();
*
out_done
=
true
;
}
else
{
set_entry_t
*
entry
=
st
->
current
;
ant_value_t
value
;
if
(
st
->
type
==
ITER_TYPE_SET_ENTRIES
)
{
ant_value_t
pair
=
js_mkarr
(
js
);
js_arr_push
(
js
,
pair
,
entry
->
value
);
js_arr_push
(
js
,
pair
,
entry
->
value
);
value
=
pair
;
}
else
{
value
=
entry
->
value
;
}
st
->
current
=
entry
->
hh
.
next
;
*
out_value
=
value
;
*
out_done
=
false
;
}
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
case
SV_ITER_STRING
:
{
ant_value_t
str
=
iter_buf
[
0
];
GC_ROOT_PIN
(
js
,
str
);
int
idx
=
(
int
)
js_getnum
(
iter_buf
[
1
]);
ant_offset_t
slen
=
str_len_fast
(
js
,
str
);
if
(
idx
>=
(
int
)
slen
)
{
*
out_value
=
js_mkundef
();
*
out_done
=
true
;
}
else
{
ant_offset_t
off
=
vstr
(
js
,
str
,
NULL
);
utf8proc_int32_t
cp
;
ant_offset_t
cb_len
=
(
ant_offset_t
)
utf8_next
(
(
const
utf8proc_uint8_t
*
)(
uintptr_t
)(
off
+
idx
),
(
utf8proc_ssize_t
)(
slen
-
idx
),
&
cp
);
*
out_value
=
js_mkstr
(
js
,
(
const
void
*
)(
uintptr_t
)(
off
+
idx
),
cb_len
);
*
out_done
=
false
;
iter_buf
[
1
]
=
tov
(
idx
+
(
int
)
cb_len
);
}
GC_ROOT_PIN
(
js
,
*
out_value
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
default
:
{
ant_value_t
iterator
=
iter_buf
[
0
];
ant_value_t
next_method
=
iter_buf
[
1
];
GC_ROOT_PIN
(
js
,
iterator
);
GC_ROOT_PIN
(
js
,
next_method
);
if
(
!
is_callable
(
next_method
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
js_mkerr
(
js
,
"iterator.next is not a function"
);
}
ant_value_t
result
=
sv_vm_call
(
vm
,
js
,
next_method
,
iterator
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
result
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
result
;
}
GC_ROOT_PIN
(
js
,
result
);
if
(
!
is_object_type
(
result
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Iterator result is not an object"
);
}
ant_value_t
done
=
js_mkundef
();
GC_ROOT_PIN
(
js
,
done
);
sv_iter_result_unpack
(
js
,
result
,
&
done
,
out_value
);
GC_ROOT_PIN
(
js
,
*
out_value
);
if
(
is_err
(
done
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
done
;
}
if
(
is_err
(
*
out_value
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
*
out_value
;
}
*
out_done
=
js_truthy
(
js
,
done
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}}
}
void
jit_helper_destructure_close
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
*
iter_buf
)
{
GC_ROOT_SAVE
(
root_mark
,
js
);
int
tag
=
(
int
)
js_getnum
(
iter_buf
[
2
]);
if
(
tag
==
SV_ITER_GENERIC
)
{
ant_value_t
iterator
=
iter_buf
[
0
];
GC_ROOT_PIN
(
js
,
iterator
);
ant_value_t
return_fn
=
js_getprop_fallback
(
js
,
iterator
,
"return"
);
GC_ROOT_PIN
(
js
,
return_fn
);
if
(
is_callable
(
return_fn
))
sv_vm_call
(
vm
,
js
,
return_fn
,
iterator
,
NULL
,
0
,
NULL
,
false
);
}
GC_ROOT_RESTORE
(
js
,
root_mark
);
}
ant_value_t
jit_helper_for_of
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
iterable
,
ant_value_t
*
iter_buf
)
{
GC_ROOT_SAVE
(
root_mark
,
js
);
GC_ROOT_PIN
(
js
,
iterable
);
if
(
vtype
(
iterable
)
==
T_ARR
)
{
iter_buf
[
0
]
=
iterable
;
iter_buf
[
1
]
=
tov
(
0
);
iter_buf
[
2
]
=
tov
(
SV_ITER_ARRAY
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
if
(
vtype
(
iterable
)
==
T_STR
)
{
if
(
str_is_heap_rope
(
iterable
)
||
str_is_heap_builder
(
iterable
))
{
iterable
=
str_materialize
(
js
,
iterable
);
if
(
is_err
(
iterable
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
iterable
;
}
GC_ROOT_PIN
(
js
,
iterable
);
}
iter_buf
[
0
]
=
iterable
;
iter_buf
[
1
]
=
tov
(
0
);
iter_buf
[
2
]
=
tov
(
SV_ITER_STRING
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
ant_value_t
iter_fn
=
js_get_sym
(
js
,
iterable
,
get_iterator_sym
());
GC_ROOT_PIN
(
js
,
iter_fn
);
if
(
!
is_callable
(
iter_fn
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
js_mkerr
(
js
,
"not iterable"
);
}
ant_value_t
iterator
=
sv_vm_call
(
vm
,
js
,
iter_fn
,
iterable
,
NULL
,
0
,
NULL
,
false
);
if
(
is_err
(
iterator
))
{
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
iterator
;
}
GC_ROOT_PIN
(
js
,
iterator
);
map_iterator_state_t
*
map_st
;
iter_type_t
map_type
;
if
(
sv_is_map_iter
(
js
,
iterator
,
&
map_st
,
&
map_type
))
{
iter_buf
[
0
]
=
ANT_PTR
(
map_st
);
iter_buf
[
1
]
=
tov
((
double
)
map_type
);
iter_buf
[
2
]
=
tov
(
SV_ITER_MAP
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
set_iterator_state_t
*
set_st
;
iter_type_t
set_type
;
if
(
sv_is_set_iter
(
js
,
iterator
,
&
set_st
,
&
set_type
))
{
iter_buf
[
0
]
=
ANT_PTR
(
set_st
);
iter_buf
[
1
]
=
tov
((
double
)
set_type
);
iter_buf
[
2
]
=
tov
(
SV_ITER_SET
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
ant_value_t
next_method
=
js_getprop_fallback
(
js
,
iterator
,
"next"
);
GC_ROOT_PIN
(
js
,
next_method
);
iter_buf
[
0
]
=
iterator
;
iter_buf
[
1
]
=
next_method
;
iter_buf
[
2
]
=
tov
(
SV_ITER_GENERIC
);
GC_ROOT_RESTORE
(
js
,
root_mark
);
return
tov
(
0
);
}
ant_value_t
jit_helper_destructure_next
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
*
iter_buf
)
{
ant_value_t
value
=
js_mkundef
();
bool
done
=
false
;
ant_value_t
status
=
jit_iter_advance_from_buf
(
vm
,
js
,
iter_buf
,
0
,
&
value
,
&
done
);
if
(
is_err
(
status
))
return
status
;
iter_buf
[
3
]
=
done
?
js_mkundef
()
:
value
;
return
status
;
}
ant_value_t
jit_helper_seq
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
return
mkval
(
T_BOOL
,
strict_eq_values
(
js
,
l
,
r
));
}
ant_value_t
jit_helper_in
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
return
do_in
(
js
,
l
,
r
);
}
ant_value_t
jit_helper_eq
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
return
sv_abstract_eq
(
js
,
l
,
r
);
}
ant_value_t
jit_helper_throw
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
val
)
{
return
js_throw
(
js
,
val
);
}
ant_value_t
jit_helper_ne
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
ant_value_t
eq
=
sv_abstract_eq
(
js
,
l
,
r
);
return
mkval
(
T_BOOL
,
!
vdata
(
eq
));
}
ant_value_t
jit_helper_sne
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
return
mkval
(
T_BOOL
,
!
strict_eq_values
(
js
,
l
,
r
));
}
ant_value_t
jit_helper_not
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
v
)
{
return
mkval
(
T_BOOL
,
!
js_truthy
(
js
,
v
));
}
ant_value_t
jit_helper_instanceof
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
,
sv_func_t
*
func
,
int32_t
bc_off
)
{
(
void
)
vm
;
uint8_t
*
ip
=
NULL
;
if
(
func
&&
bc_off
>=
0
&&
bc_off
<
func
->
code_len
)
ip
=
func
->
code
+
bc_off
;
return
sv_instanceof_ic_eval
(
js
,
l
,
r
,
func
,
ip
);
}
ant_value_t
jit_helper_call_is_proto
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
call_this
,
ant_value_t
call_func
,
ant_value_t
arg
,
sv_func_t
*
func
,
int32_t
bc_off
)
{
uint8_t
*
ip
=
NULL
;
if
(
func
&&
bc_off
>=
0
&&
bc_off
<
func
->
code_len
)
ip
=
func
->
code
+
bc_off
;
if
(
vtype
(
call_func
)
==
T_CFUNC
&&
js_cfunc_same_entrypoint
(
call_func
,
builtin_object_isPrototypeOf
))
{
return
sv_isproto_ic_eval
(
js
,
call_this
,
arg
,
func
,
ip
);
}
ant_value_t
args
[
1
]
=
{
arg
};
return
sv_vm_call
(
vm
,
js
,
call_func
,
call_this
,
args
,
1
,
NULL
,
false
);
}
ant_value_t
jit_helper_call_array_includes
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
call_func
,
ant_value_t
call_this
,
ant_value_t
*
args
,
int
argc
)
{
if
(
js_is_array_includes_builtin
(
call_func
))
return
js_array_includes_call
(
js
,
call_this
,
args
,
argc
);
return
sv_vm_call
(
vm
,
js
,
call_func
,
call_this
,
args
,
argc
,
NULL
,
false
);
}
// TODO: dont bail out
ant_value_t
jit_helper_typeof
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
v
)
{
return
SV_JIT_BAILOUT
;
}
int64_t
jit_helper_is_truthy
(
ant_t
*
js
,
ant_value_t
v
)
{
return
(
int64_t
)
js_truthy
(
js
,
v
);
}
static
inline
void
jit_set_error_site_from_func
(
ant_t
*
js
,
sv_func_t
*
func
,
int32_t
bc_off
)
{
if
(
!
func
)
return
;
js_set_error_site_from_bc
(
js
,
func
,
(
int
)
bc_off
,
func
->
filename
);
}
ant_value_t
jit_helper_get_field
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
const
char
*
str
,
uint32_t
len
,
sv_func_t
*
func
,
int32_t
bc_off
)
{
(
void
)
vm
;
uint8_t
*
ip
=
NULL
;
if
(
func
&&
bc_off
>=
0
&&
bc_off
<
func
->
code_len
)
ip
=
func
->
code
+
bc_off
;
sv_atom_t
atom
=
{
.
str
=
str
,
.
len
=
len
};
ant_value_t
out
=
sv_prop_get_field_ic
(
js
,
obj
,
&
atom
,
func
,
ip
);
if
((
vtype
(
obj
)
==
T_NULL
||
vtype
(
obj
)
==
T_UNDEF
)
&&
is_err
(
out
))
jit_set_error_site_from_func
(
js
,
func
,
bc_off
);
return
out
;
}
ant_value_t
jit_helper_to_propkey
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
v
)
{
if
(
vtype
(
v
)
==
T_STR
||
vtype
(
v
)
==
T_SYMBOL
)
return
v
;
return
coerce_to_str
(
js
,
v
);
}
static
inline
sv_upvalue_t
*
jit_make_undef_upvalue
(
void
)
{
sv_upvalue_t
*
uv
=
js_upvalue_alloc
();
uv
->
closed
=
js_mkundef
();
uv
->
location
=
&
uv
->
closed
;
return
uv
;
}
ant_value_t
jit_helper_closure
(
sv_vm_t
*
vm
,
ant_t
*
js
,
sv_closure_t
*
parent_closure
,
ant_value_t
this_val
,
ant_value_t
*
slots
,
int
slot_base
,
int
slot_count
,
uint32_t
const_idx
)
{
sv_func_t
*
parent_func
=
parent_closure
->
func
;
sv_func_t
*
child
=
(
sv_func_t
*
)(
uintptr_t
)
vdata
(
parent_func
->
constants
[
const_idx
]);
sv_closure_t
*
closure
=
js_closure_alloc
(
js
);
if
(
!
closure
)
return
mkval
(
T_ERR
,
0
);
closure
->
func
=
child
;
closure
->
bound_this
=
child
->
is_arrow
?
this_val
:
js_mkundef
();
closure
->
bound_args
=
js_mkundef
();
closure
->
super_val
=
js_mkundef
();
closure
->
call_flags
=
child
->
is_arrow
?
SV_CALL_IS_ARROW
:
0
;
if
(
child
->
upvalue_count
>
0
)
closure
->
upvalues
=
calloc
((
size_t
)
child
->
upvalue_count
,
sizeof
(
sv_upvalue_t
*
));
for
(
int
i
=
0
;
i
<
child
->
upvalue_count
;
i
++
)
{
sv_upval_desc_t
*
desc
=
&
child
->
upval_descs
[
i
];
if
(
!
desc
->
is_local
)
{
closure
->
upvalues
[
i
]
=
parent_closure
->
upvalues
[
desc
->
index
];
continue
;
}
int
idx
=
(
int
)
desc
->
index
-
slot_base
;
if
(
!
slots
||
idx
<
0
||
idx
>=
slot_count
)
{
closure
->
upvalues
[
i
]
=
jit_make_undef_upvalue
();
continue
;
}
closure
->
upvalues
[
i
]
=
sv_capture_upvalue
(
vm
,
&
slots
[
idx
]);
}
ant_value_t
func_obj
=
mkobj
(
js
,
0
);
closure
->
func_obj
=
func_obj
;
ant_value_t
module_ctx
=
sv_get_current_closure_module_ctx
(
js
,
mkval
(
T_FUNC
,
(
uintptr_t
)
parent_closure
));
js_mark_constructor
(
func_obj
,
!
child
->
is_arrow
&&
!
child
->
is_method
&&
!
child
->
is_generator
&&
!
child
->
is_async
);
js_setprop
(
js
,
func_obj
,
js
->
length_str
,
tov
((
double
)
child
->
param_count
));
js_set_descriptor
(
js
,
func_obj
,
"length"
,
6
,
JS_DESC_C
);
if
(
is_object_type
(
module_ctx
))
js_set_slot_wb
(
js
,
func_obj
,
SLOT_MODULE_CTX
,
module_ctx
);
ant_value_t
func_val
=
mkval
(
T_FUNC
,
(
uintptr_t
)
closure
);
if
(
!
child
->
is_arrow
&&
!
child
->
is_method
&&
(
!
child
->
is_async
||
child
->
is_generator
))
{
ant_value_t
parent_proto
=
child
->
is_async
?
js
->
sym
.
async_generator_proto
:
(
child
->
is_generator
?
js
->
sym
.
generator_proto
:
js
->
sym
.
object_proto
);
sv_setup_function_prototype_with_parent
(
js
,
func_obj
,
func_val
,
parent_proto
);
}
if
(
child
->
is_async
&&
child
->
is_generator
)
{
js_set_slot
(
func_obj
,
SLOT_ASYNC
,
js_true
);
ant_value_t
async_generator_proto
=
js_get_slot
(
js
->
global
,
SLOT_ASYNC_GENERATOR_PROTO
);
if
(
vtype
(
async_generator_proto
)
==
T_FUNC
)
js_set_proto_init
(
func_obj
,
async_generator_proto
);
}
else
if
(
child
->
is_async
)
{
js_set_slot
(
func_obj
,
SLOT_ASYNC
,
js_true
);
ant_value_t
async_proto
=
js_get_slot
(
js
->
global
,
SLOT_ASYNC_PROTO
);
if
(
vtype
(
async_proto
)
==
T_FUNC
)
js_set_proto_init
(
func_obj
,
async_proto
);
}
else
if
(
child
->
is_generator
)
{
ant_value_t
generator_proto
=
js_get_slot
(
js
->
global
,
SLOT_GENERATOR_PROTO
);
if
(
vtype
(
generator_proto
)
==
T_FUNC
)
js_set_proto_init
(
func_obj
,
generator_proto
);
}
else
{
ant_value_t
func_proto
=
js_get_slot
(
js
->
global
,
SLOT_FUNC_PROTO
);
if
(
vtype
(
func_proto
)
==
T_FUNC
)
js_set_proto_init
(
func_obj
,
func_proto
);
}
return
func_val
;
}
void
jit_helper_close_upval
(
sv_vm_t
*
vm
,
uint16_t
slot_idx
,
ant_value_t
*
slots
,
int
slot_count
)
{
if
(
!
slots
||
slot_count
<=
0
)
return
;
if
((
int
)
slot_idx
>=
slot_count
)
return
;
ant_value_t
*
lo
=
slots
+
slot_idx
;
ant_value_t
*
hi
=
slots
+
slot_count
;
sv_upvalue_t
**
pp
=
&
vm
->
open_upvalues
;
while
(
*
pp
)
{
sv_upvalue_t
*
uv
=
*
pp
;
if
(
uv
->
location
<
lo
)
break
;
if
(
uv
->
location
>=
lo
&&
uv
->
location
<
hi
)
{
uv
->
closed
=
*
uv
->
location
;
uv
->
location
=
&
uv
->
closed
;
*
pp
=
uv
->
next
;
}
else
pp
=
&
uv
->
next
;
}
}
ant_value_t
jit_helper_bailout_resume
(
sv_vm_t
*
vm
,
sv_closure_t
*
closure
,
ant_value_t
this_val
,
ant_value_t
*
args
,
int
argc
,
ant_value_t
*
vstack
,
int64_t
vstack_sp
,
ant_value_t
*
locals
,
int64_t
n_locals
,
int64_t
bc_offset
)
{
if
(
!
closure
||
!
closure
->
func
)
return
mkval
(
T_ERR
,
0
);
sv_func_t
*
fn
=
closure
->
func
;
sv_jit_on_bailout
(
fn
);
vm
->
jit_resume
.
active
=
true
;
vm
->
jit_resume
.
ip_offset
=
(
int
)
bc_offset
;
vm
->
jit_resume
.
locals
=
locals
;
vm
->
jit_resume
.
n_locals
=
n_locals
;
vm
->
jit_resume
.
vstack
=
vstack
;
vm
->
jit_resume
.
vstack_sp
=
vstack_sp
;
return
sv_execute_closure_entry
(
vm
,
closure
,
closure
->
func_obj
,
js_mkundef
(),
this_val
,
args
,
argc
,
NULL
);
}
void
jit_helper_define_field
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
val
,
const
char
*
str
,
uint32_t
len
)
{
if
(
!
sv_try_define_field_fast
(
js
,
obj
,
str
,
val
))
js_define_own_prop
(
js
,
obj
,
str
,
len
,
val
);
}
void
jit_helper_set_name
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
fn
,
const
char
*
str
,
uint32_t
len
)
{
ant_value_t
name
=
js_mkstr
(
js
,
str
,
len
);
setprop_cstr
(
js
,
fn
,
"name"
,
4
,
name
);
}
ant_value_t
jit_helper_get_length
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
)
{
if
(
vtype
(
obj
)
==
T_ARR
)
return
tov
((
double
)(
uint32_t
)
js_arr_len
(
js
,
obj
));
if
(
vtype
(
obj
)
==
T_STR
)
{
ant_flat_string_t
*
flat
=
ant_str_flat_ptr
(
obj
);
if
(
flat
)
{
const
char
*
str_data
=
flat
->
bytes
;
ant_offset_t
byte_len
=
flat
->
len
;
return
tov
((
double
)(
uint32_t
)(
str_is_ascii
(
str_data
)
?
byte_len
:
utf16_strlen
(
str_data
,
byte_len
)
));
}
ant_offset_t
byte_len
=
0
;
ant_offset_t
off
=
vstr
(
js
,
obj
,
&
byte_len
);
const
char
*
str_data
=
(
const
char
*
)(
uintptr_t
)(
off
);
return
tov
((
double
)(
uint32_t
)
utf16_strlen
(
str_data
,
byte_len
));
}
return
js_getprop_fallback
(
js
,
obj
,
"length"
);
}
ant_value_t
jit_helper_put_field
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
val
,
const
char
*
str
,
uint32_t
len
)
{
ant_value_t
key
=
js_mkstr
(
js
,
str
,
len
);
return
js_setprop
(
js
,
obj
,
key
,
val
);
}
ant_value_t
jit_helper_get_elem
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
key
,
sv_func_t
*
func
,
int32_t
bc_off
)
{
uint8_t
ot
=
vtype
(
obj
);
if
(
ot
==
T_NULL
||
ot
==
T_UNDEF
)
{
jit_set_error_site_from_func
(
js
,
func
,
bc_off
);
return
sv_mk_nullish_read_error_by_key
(
js
,
obj
,
key
);
}
if
(
vtype
(
obj
)
==
T_ARR
&&
vtype
(
key
)
==
T_NUM
)
{
double
d
=
tod
(
key
);
if
(
d
>=
0
&&
d
==
(
uint32_t
)
d
)
return
js_arr_get
(
js
,
obj
,
(
uint32_t
)
d
);
}
ant_value_t
str_elem
=
js_mkundef
();
if
(
sv_try_string_index_get
(
js
,
obj
,
key
,
&
str_elem
))
return
str_elem
;
return
sv_getprop_by_key
(
js
,
obj
,
key
);
}
ant_value_t
jit_helper_put_elem
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
key
,
ant_value_t
val
)
{
if
(
vtype
(
key
)
==
T_SYMBOL
)
return
js_setprop
(
js
,
obj
,
key
,
val
);
ant_value_t
key_jv
=
sv_key_to_propstr
(
js
,
key
);
return
js_setprop
(
js
,
obj
,
key_jv
,
val
);
}
ant_value_t
jit_helper_put_global
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
val
,
const
char
*
str
,
uint32_t
len
,
int
is_strict
)
{
if
(
is_strict
&&
lkp
(
js
,
js
->
global
,
str
,
len
)
==
0
)
return
js_mkerr_typed
(
js
,
JS_ERR_REFERENCE
,
"'%.*s' is not defined"
,
(
int
)
len
,
str
);
ant_value_t
key
=
js_mkstr
(
js
,
str
,
len
);
return
js_setprop
(
js
,
js
->
global
,
key
,
val
);
}
ant_value_t
jit_helper_object
(
sv_vm_t
*
vm
,
ant_t
*
js
)
{
ant_value_t
obj
=
mkobj
(
js
,
0
);
ant_value_t
proto
=
js
->
sym
.
object_proto
;
if
(
vtype
(
proto
)
==
T_OBJ
)
js_set_proto_init
(
obj
,
proto
);
return
obj
;
}
ant_value_t
jit_helper_array
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
*
elements
,
int
count
)
{
ant_value_t
arr
=
js_mkarr
(
js
);
for
(
int
i
=
0
;
i
<
count
;
i
++
)
js_arr_push
(
js
,
arr
,
elements
[
i
]);
return
arr
;
}
ant_value_t
jit_helper_catch_value
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
err
)
{
if
(
vtype
(
err
)
==
T_ERR
&&
js
->
thrown_exists
&&
vtype
(
js
->
thrown_value
)
!=
T_UNDEF
)
{
ant_value_t
caught
=
js
->
thrown_value
;
js
->
thrown_value
=
js_mkundef
();
js
->
thrown_exists
=
false
;
return
caught
;
}
return
err
;
}
ant_value_t
jit_helper_throw_error
(
sv_vm_t
*
vm
,
ant_t
*
js
,
const
char
*
str
,
uint32_t
len
,
int
err_type
)
{
return
js_mkerr_typed
(
js
,
(
js_err_type_t
)
err_type
,
"%.*s"
,
(
int
)
len
,
str
);
}
ant_value_t
jit_helper_get_elem2
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
key
)
{
if
(
vtype
(
obj
)
==
T_ARR
&&
vtype
(
key
)
==
T_NUM
)
{
double
d
=
tod
(
key
);
if
(
d
>=
0
&&
d
==
(
uint32_t
)
d
)
return
js_arr_get
(
js
,
obj
,
(
uint32_t
)
d
);
}
ant_value_t
str_elem
=
js_mkundef
();
if
(
sv_try_string_index_get
(
js
,
obj
,
key
,
&
str_elem
))
return
str_elem
;
return
sv_getprop_by_key
(
js
,
obj
,
key
);
}
ant_value_t
jit_helper_set_proto
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
proto
)
{
uint8_t
pt
=
vtype
(
proto
);
if
(
pt
==
T_OBJ
||
pt
==
T_NULL
||
pt
==
T_FUNC
||
pt
==
T_ARR
)
js_set_proto_wb
(
js
,
obj
,
proto
);
return
js_mkundef
();
}
ant_value_t
jit_helper_band
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
!=
T_NUM
||
vtype
(
r
)
!=
T_NUM
)
return
SV_JIT_BAILOUT
;
int32_t
ai
=
js_to_int32
(
tod
(
l
));
int32_t
bi
=
js_to_int32
(
tod
(
r
));
return
tov
((
double
)(
ai
&
bi
));
}
ant_value_t
jit_helper_bor
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
!
((
vtype
(
l
)
==
T_NUM
||
vtype
(
l
)
==
T_STR
)
&&
(
vtype
(
r
)
==
T_NUM
||
vtype
(
r
)
==
T_STR
)))
return
SV_JIT_BAILOUT
;
int32_t
ai
=
js_to_int32
((
vtype
(
l
)
==
T_NUM
)
?
tod
(
l
)
:
js_to_number
(
js
,
l
));
int32_t
bi
=
js_to_int32
((
vtype
(
r
)
==
T_NUM
)
?
tod
(
r
)
:
js_to_number
(
js
,
r
));
return
tov
((
double
)(
ai
|
bi
));
}
ant_value_t
jit_helper_bxor
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
!=
T_NUM
||
vtype
(
r
)
!=
T_NUM
)
return
SV_JIT_BAILOUT
;
int32_t
ai
=
js_to_int32
(
tod
(
l
));
int32_t
bi
=
js_to_int32
(
tod
(
r
));
return
tov
((
double
)(
ai
^
bi
));
}
ant_value_t
jit_helper_bnot
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
v
)
{
if
(
vtype
(
v
)
!=
T_NUM
)
return
SV_JIT_BAILOUT
;
return
tov
((
double
)(
~
js_to_int32
(
tod
(
v
))));
}
ant_value_t
jit_helper_shl
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
!=
T_NUM
||
vtype
(
r
)
!=
T_NUM
)
return
SV_JIT_BAILOUT
;
int32_t
ai
=
js_to_int32
(
tod
(
l
));
uint32_t
bi
=
js_to_uint32
(
tod
(
r
));
return
tov
((
double
)(
ai
<<
(
bi
&
0x1f
)));
}
ant_value_t
jit_helper_shr
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
!=
T_NUM
||
vtype
(
r
)
!=
T_NUM
)
return
SV_JIT_BAILOUT
;
int32_t
ai
=
js_to_int32
(
tod
(
l
));
uint32_t
bi
=
js_to_uint32
(
tod
(
r
));
return
tov
((
double
)(
ai
>>
(
bi
&
0x1f
)));
}
ant_value_t
jit_helper_ushr
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
!=
T_NUM
||
vtype
(
r
)
!=
T_NUM
)
return
SV_JIT_BAILOUT
;
uint32_t
ai
=
js_to_uint32
(
tod
(
l
));
uint32_t
bi
=
js_to_uint32
(
tod
(
r
));
return
tov
((
double
)(
ai
>>
(
bi
&
0x1f
)));
}
ant_value_t
jit_helper_gt
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
js_bool
(
tod
(
l
)
>
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_ge
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
l
,
ant_value_t
r
)
{
if
(
vtype
(
l
)
==
T_NUM
&&
vtype
(
r
)
==
T_NUM
)
return
js_bool
(
tod
(
l
)
>=
tod
(
r
));
return
SV_JIT_BAILOUT
;
}
ant_value_t
jit_helper_delete
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
obj
,
ant_value_t
key
)
{
ant_value_t
key_str
=
js_mkundef
();
if
(
vtype
(
key
)
==
T_SYMBOL
)
return
js_delete_sym_prop
(
js
,
obj
,
key
);
else
key_str
=
coerce_to_str
(
js
,
key
);
if
(
!
is_err
(
key_str
)
&&
vtype
(
key_str
)
==
T_STR
)
{
ant_offset_t
klen
=
0
;
ant_offset_t
koff
=
vstr
(
js
,
key_str
,
&
klen
);
const
char
*
kptr
=
(
const
char
*
)(
uintptr_t
)(
koff
);
return
js_delete_prop
(
js
,
obj
,
kptr
,
klen
);
}
return
mkval
(
T_BOOL
,
0
);
}
ant_value_t
jit_helper_new
(
sv_vm_t
*
vm
,
ant_t
*
js
,
ant_value_t
func
,
ant_value_t
new_target
,
ant_value_t
*
args
,
int
argc
)
{
ant_value_t
record_func
=
func
;
js
->
new_target
=
new_target
;
if
(
vtype
(
func
)
==
T_OBJ
&&
is_proxy
(
func
))
return
js_proxy_construct
(
js
,
func
,
args
,
argc
,
new_target
);
if
(
!
js_is_constructor
(
func
))
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"not a constructor"
);
ant_value_t
proto
=
js_mkundef
();
if
(
vtype
(
func
)
==
T_FUNC
)
{
ant_value_t
proto_source
=
func
;
ant_value_t
func_obj
=
js_func_obj
(
func
);
ant_value_t
target_func
=
js_get_slot
(
func_obj
,
SLOT_TARGET_FUNC
);
if
(
vtype
(
target_func
)
==
T_FUNC
)
{
proto_source
=
target_func
;
record_func
=
target_func
;
}
proto
=
js_getprop_fallback
(
js
,
proto_source
,
"prototype"
);
}
ant_value_t
obj
=
js_mkobj_with_inobj_limit
(
js
,
sv_tfb_ctor_inobj_limit
(
record_func
));
if
(
is_object_type
(
proto
))
js_set_proto_init
(
obj
,
proto
);
ant_value_t
ctor_this
=
obj
;
ant_value_t
result
=
sv_vm_call
(
vm
,
js
,
func
,
obj
,
args
,
argc
,
&
ctor_this
,
true
);
if
(
is_err
(
result
))
return
result
;
ant_value_t
final_obj
=
is_object_type
(
result
)
?
result
:
(
is_object_type
(
ctor_this
)
?
ctor_this
:
obj
);
sv_tfb_record_ctor_prop_count
(
record_func
,
final_obj
);
return
final_obj
;
}
#endif
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, May 2, 2:12 AM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
542723
Default Alt Text
glue.c (29 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment