[runtime] Add new instance types for constructor functions
This will allow us optimize the protector cell checks in the fast path from checking against the function object in every context to just doing a range check against the instance type. This patch adds new instance types for constructor functions that require such protector cell checks. Bug: v8:11256 Change-Id: Iea722f9c6326dfa470149dd02e689a23942097f4 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2595442 Reviewed-by: Mythri Alle <mythria@chromium.org> Reviewed-by: Ulan Degenbaev <ulan@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org> Cr-Commit-Position: refs/heads/master@{#72146}
This commit is contained in:
parent
47135e0368
commit
624030e975
@ -694,8 +694,8 @@ Handle<JSFunction> ApiNatives::CreateApiFunction(
|
||||
immutable_proto = GetInstanceTemplate->immutable_proto();
|
||||
}
|
||||
|
||||
// JS_FUNCTION_TYPE requires information about the prototype slot.
|
||||
DCHECK_NE(JS_FUNCTION_TYPE, type);
|
||||
// JSFunction requires information about the prototype slot.
|
||||
DCHECK(!InstanceTypeChecker::IsJSFunction(type));
|
||||
int instance_size = JSObject::GetHeaderSize(type) +
|
||||
kEmbedderDataSlotSize * embedder_field_count;
|
||||
|
||||
|
@ -2160,9 +2160,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
Label non_callable, non_smi;
|
||||
__ JumpIfSmi(r1, &non_callable);
|
||||
__ bind(&non_smi);
|
||||
__ CompareObjectType(r1, r4, r5, JS_FUNCTION_TYPE);
|
||||
__ LoadMap(r4, r1);
|
||||
__ CompareInstanceTypeRange(r4, r5, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(mode),
|
||||
RelocInfo::CODE_TARGET, eq);
|
||||
RelocInfo::CODE_TARGET, ls);
|
||||
__ cmp(r5, Operand(JS_BOUND_FUNCTION_TYPE));
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), CallBoundFunction),
|
||||
RelocInfo::CODE_TARGET, eq);
|
||||
@ -2268,9 +2270,10 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
|
||||
__ b(eq, &non_constructor);
|
||||
|
||||
// Dispatch based on instance type.
|
||||
__ CompareInstanceType(r4, r5, JS_FUNCTION_TYPE);
|
||||
__ CompareInstanceTypeRange(r4, r5, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
|
||||
RelocInfo::CODE_TARGET, eq);
|
||||
RelocInfo::CODE_TARGET, ls);
|
||||
|
||||
// Only dispatch to bound functions after checking whether they are
|
||||
// constructors.
|
||||
|
@ -2523,9 +2523,11 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
Label non_callable, non_smi;
|
||||
__ JumpIfSmi(x1, &non_callable);
|
||||
__ Bind(&non_smi);
|
||||
__ CompareObjectType(x1, x4, x5, JS_FUNCTION_TYPE);
|
||||
__ LoadMap(x4, x1);
|
||||
__ CompareInstanceTypeRange(x4, x5, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(mode),
|
||||
RelocInfo::CODE_TARGET, eq);
|
||||
RelocInfo::CODE_TARGET, ls);
|
||||
__ Cmp(x5, JS_BOUND_FUNCTION_TYPE);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), CallBoundFunction),
|
||||
RelocInfo::CODE_TARGET, eq);
|
||||
@ -2639,9 +2641,10 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
|
||||
&non_constructor);
|
||||
|
||||
// Dispatch based on instance type.
|
||||
__ CompareInstanceType(x4, x5, JS_FUNCTION_TYPE);
|
||||
__ CompareInstanceTypeRange(x4, x5, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
|
||||
RelocInfo::CODE_TARGET, eq);
|
||||
RelocInfo::CODE_TARGET, ls);
|
||||
|
||||
// Only dispatch to bound functions after checking whether they are
|
||||
// constructors.
|
||||
|
@ -517,8 +517,7 @@ TNode<JSReceiver> CallOrConstructBuiltinsAssembler::GetCompatibleReceiver(
|
||||
//
|
||||
var_template = CAST(constructor);
|
||||
TNode<Uint16T> template_type = LoadInstanceType(var_template.value());
|
||||
GotoIf(InstanceTypeEqual(template_type, JS_FUNCTION_TYPE),
|
||||
&template_from_closure);
|
||||
GotoIf(IsJSFunctionInstanceType(template_type), &template_from_closure);
|
||||
Branch(InstanceTypeEqual(template_type, MAP_TYPE), &template_map_loop,
|
||||
&template_loop);
|
||||
}
|
||||
|
@ -737,16 +737,15 @@ TF_BUILTIN(ObjectToString, ObjectBuiltinsAssembler) {
|
||||
var_holder = receiver_heap_object;
|
||||
TNode<Uint16T> receiver_instance_type = LoadMapInstanceType(receiver_map);
|
||||
GotoIf(IsPrimitiveInstanceType(receiver_instance_type), &if_primitive);
|
||||
GotoIf(IsFunctionInstanceType(receiver_instance_type), &if_function);
|
||||
const struct {
|
||||
InstanceType value;
|
||||
Label* label;
|
||||
} kJumpTable[] = {{JS_OBJECT_TYPE, &if_object},
|
||||
{JS_ARRAY_TYPE, &if_array},
|
||||
{JS_FUNCTION_TYPE, &if_function},
|
||||
{JS_REG_EXP_TYPE, &if_regexp},
|
||||
{JS_ARGUMENTS_OBJECT_TYPE, &if_arguments},
|
||||
{JS_DATE_TYPE, &if_date},
|
||||
{JS_BOUND_FUNCTION_TYPE, &if_function},
|
||||
{JS_API_OBJECT_TYPE, &if_object},
|
||||
{JS_SPECIAL_API_OBJECT_TYPE, &if_object},
|
||||
{JS_PROXY_TYPE, &if_proxy},
|
||||
|
@ -1377,7 +1377,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
|
||||
__ Pop(kJavaScriptCallTargetRegister);
|
||||
__ PushReturnAddressFrom(eax);
|
||||
|
||||
__ AssertFunction(kJavaScriptCallTargetRegister);
|
||||
__ AssertFunction(kJavaScriptCallTargetRegister, eax);
|
||||
__ AssertUndefinedOrAllocationSite(kJavaScriptCallExtraArg1Register, eax);
|
||||
|
||||
__ movd(eax, xmm0); // Reload number of arguments.
|
||||
@ -2113,7 +2113,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
|
||||
// -- edi : the function to call (checked to be a JSFunction)
|
||||
// -----------------------------------
|
||||
StackArgumentsAccessor args(eax);
|
||||
__ AssertFunction(edi);
|
||||
__ AssertFunction(edi, edx);
|
||||
|
||||
// See ES6 section 9.2.1 [[Call]] ( thisArgument, argumentsList)
|
||||
// Check that the function is not a "classConstructor".
|
||||
@ -2328,12 +2328,15 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
non_jsboundfunction;
|
||||
__ JumpIfSmi(edi, &non_callable);
|
||||
__ bind(&non_smi);
|
||||
__ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx);
|
||||
__ j(not_equal, &non_jsfunction);
|
||||
__ LoadMap(ecx, edi);
|
||||
__ CmpInstanceTypeRange(ecx, ecx, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
__ j(above, &non_jsfunction);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(mode),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
__ bind(&non_jsfunction);
|
||||
__ LoadMap(ecx, edi);
|
||||
__ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
|
||||
__ j(not_equal, &non_jsboundfunction);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), CallBoundFunction),
|
||||
@ -2378,7 +2381,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
|
||||
// -- edi : the constructor to call (checked to be a JSFunction)
|
||||
// -----------------------------------
|
||||
__ AssertConstructor(edi);
|
||||
__ AssertFunction(edi);
|
||||
__ AssertFunction(edi, ecx);
|
||||
|
||||
Label call_generic_stub;
|
||||
|
||||
@ -2450,14 +2453,16 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
|
||||
__ j(zero, &non_constructor);
|
||||
|
||||
// Dispatch based on instance type.
|
||||
__ CmpInstanceType(ecx, JS_FUNCTION_TYPE);
|
||||
__ j(not_equal, &non_jsfunction);
|
||||
__ CmpInstanceTypeRange(ecx, ecx, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
__ j(above, &non_jsfunction);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
// Only dispatch to bound functions after checking whether they are
|
||||
// constructors.
|
||||
__ bind(&non_jsfunction);
|
||||
__ mov(ecx, FieldOperand(edi, HeapObject::kMapOffset));
|
||||
__ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE);
|
||||
__ j(not_equal, &non_jsboundfunction);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructBoundFunction),
|
||||
|
@ -2259,9 +2259,10 @@ void Builtins::Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode) {
|
||||
|
||||
Label non_callable;
|
||||
__ JumpIfSmi(rdi, &non_callable);
|
||||
__ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
|
||||
__ LoadMap(rcx, rdi);
|
||||
__ CmpInstanceTypeRange(rcx, FIRST_JS_FUNCTION_TYPE, LAST_JS_FUNCTION_TYPE);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(mode),
|
||||
RelocInfo::CODE_TARGET, equal);
|
||||
RelocInfo::CODE_TARGET, below_equal);
|
||||
|
||||
__ CmpInstanceType(rcx, JS_BOUND_FUNCTION_TYPE);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), CallBoundFunction),
|
||||
@ -2373,9 +2374,9 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
|
||||
__ j(zero, &non_constructor);
|
||||
|
||||
// Dispatch based on instance type.
|
||||
__ CmpInstanceType(rcx, JS_FUNCTION_TYPE);
|
||||
__ CmpInstanceTypeRange(rcx, FIRST_JS_FUNCTION_TYPE, LAST_JS_FUNCTION_TYPE);
|
||||
__ Jump(BUILTIN_CODE(masm->isolate(), ConstructFunction),
|
||||
RelocInfo::CODE_TARGET, equal);
|
||||
RelocInfo::CODE_TARGET, below_equal);
|
||||
|
||||
// Only dispatch to bound functions after checking whether they are
|
||||
// constructors.
|
||||
|
@ -1841,6 +1841,17 @@ void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
|
||||
cmp(type_reg, Operand(type));
|
||||
}
|
||||
|
||||
void MacroAssembler::CompareInstanceTypeRange(Register map, Register type_reg,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit) {
|
||||
DCHECK_LT(lower_limit, higher_limit);
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register scratch = temps.Acquire();
|
||||
ldrh(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
||||
sub(scratch, type_reg, Operand(lower_limit));
|
||||
cmp(scratch, Operand(higher_limit - lower_limit));
|
||||
}
|
||||
|
||||
void MacroAssembler::CompareRoot(Register obj, RootIndex index) {
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register scratch = temps.Acquire();
|
||||
@ -2141,9 +2152,11 @@ void MacroAssembler::AssertFunction(Register object) {
|
||||
tst(object, Operand(kSmiTagMask));
|
||||
Check(ne, AbortReason::kOperandIsASmiAndNotAFunction);
|
||||
push(object);
|
||||
CompareObjectType(object, object, object, JS_FUNCTION_TYPE);
|
||||
LoadMap(object, object);
|
||||
CompareInstanceTypeRange(object, object, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
pop(object);
|
||||
Check(eq, AbortReason::kOperandIsNotAFunction);
|
||||
Check(ls, AbortReason::kOperandIsNotAFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,6 +718,14 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
// sets the flags and leaves the object type in the type_reg register.
|
||||
void CompareInstanceType(Register map, Register type_reg, InstanceType type);
|
||||
|
||||
// Compare instance type ranges for a map (lower_limit and higher_limit
|
||||
// inclusive).
|
||||
//
|
||||
// Always use unsigned comparisons: ls for a positive result.
|
||||
void CompareInstanceTypeRange(Register map, Register type_reg,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit);
|
||||
|
||||
// Compare the object in a register to a value from the root list.
|
||||
// Acquires a scratch register.
|
||||
void CompareRoot(Register obj, RootIndex index);
|
||||
|
@ -1488,9 +1488,10 @@ void MacroAssembler::AssertFunction(Register object) {
|
||||
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register temp = temps.AcquireX();
|
||||
|
||||
CompareObjectType(object, temp, temp, JS_FUNCTION_TYPE);
|
||||
Check(eq, AbortReason::kOperandIsNotAFunction);
|
||||
LoadMap(temp, object);
|
||||
CompareInstanceTypeRange(temp, temp, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
Check(ls, AbortReason::kOperandIsNotAFunction);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2661,6 +2662,18 @@ void MacroAssembler::CompareInstanceType(Register map, Register type_reg,
|
||||
Cmp(type_reg, type);
|
||||
}
|
||||
|
||||
// Sets condition flags based on comparison, and returns type in type_reg.
|
||||
void MacroAssembler::CompareInstanceTypeRange(Register map, Register type_reg,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit) {
|
||||
DCHECK_LT(lower_limit, higher_limit);
|
||||
UseScratchRegisterScope temps(this);
|
||||
Register scratch = temps.AcquireX();
|
||||
Ldrh(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
|
||||
Sub(scratch, type_reg, Operand(lower_limit));
|
||||
Cmp(scratch, Operand(higher_limit - lower_limit));
|
||||
}
|
||||
|
||||
void MacroAssembler::LoadElementsKindFromMap(Register result, Register map) {
|
||||
// Load the map's "bit field 2".
|
||||
Ldrb(result, FieldMemOperand(map, Map::kBitField2Offset));
|
||||
|
@ -1913,6 +1913,14 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
// sets the flags and leaves the object type in the type_reg register.
|
||||
void CompareInstanceType(Register map, Register type_reg, InstanceType type);
|
||||
|
||||
// Compare instance type ranges for a map (lower_limit and higher_limit
|
||||
// inclusive).
|
||||
//
|
||||
// Always use unsigned comparisons: ls for a positive result.
|
||||
void CompareInstanceTypeRange(Register map, Register type_reg,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit);
|
||||
|
||||
// Load the elements kind field from a map, and return it in the result
|
||||
// register.
|
||||
void LoadElementsKindFromMap(Register result, Register map);
|
||||
|
@ -6369,9 +6369,15 @@ TNode<BoolT> CodeStubAssembler::IsJSGeneratorObject(TNode<HeapObject> object) {
|
||||
return HasInstanceType(object, JS_GENERATOR_OBJECT_TYPE);
|
||||
}
|
||||
|
||||
TNode<BoolT> CodeStubAssembler::IsFunctionInstanceType(
|
||||
TNode<Int32T> instance_type) {
|
||||
return IsInRange(instance_type, FIRST_JS_FUNCTION_OR_BOUND_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_OR_BOUND_FUNCTION_TYPE);
|
||||
}
|
||||
TNode<BoolT> CodeStubAssembler::IsJSFunctionInstanceType(
|
||||
SloppyTNode<Int32T> instance_type) {
|
||||
return InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE);
|
||||
return IsInRange(instance_type, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
}
|
||||
|
||||
TNode<BoolT> CodeStubAssembler::IsJSFunction(TNode<HeapObject> object) {
|
||||
@ -9429,7 +9435,7 @@ TNode<Oddball> CodeStubAssembler::OrdinaryHasInstance(
|
||||
|
||||
// Goto runtime if {callable} is not a JSFunction.
|
||||
TNode<Uint16T> callable_instance_type = LoadMapInstanceType(callable_map);
|
||||
GotoIfNot(InstanceTypeEqual(callable_instance_type, JS_FUNCTION_TYPE),
|
||||
GotoIfNot(IsJSFunctionInstanceType(callable_instance_type),
|
||||
&return_runtime);
|
||||
|
||||
GotoIfPrototypeRequiresRuntimeLookup(CAST(callable), callable_map,
|
||||
|
@ -2365,6 +2365,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
TNode<BoolT> IsJSArray(TNode<HeapObject> object);
|
||||
TNode<BoolT> IsJSArrayIterator(TNode<HeapObject> object);
|
||||
TNode<BoolT> IsJSAsyncGeneratorObject(TNode<HeapObject> object);
|
||||
TNode<BoolT> IsFunctionInstanceType(TNode<Int32T> instance_type);
|
||||
TNode<BoolT> IsJSFunctionInstanceType(SloppyTNode<Int32T> instance_type);
|
||||
TNode<BoolT> IsJSFunctionMap(TNode<Map> map);
|
||||
TNode<BoolT> IsJSFunction(TNode<HeapObject> object);
|
||||
|
@ -871,6 +871,15 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
|
||||
cmpw(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
|
||||
}
|
||||
|
||||
void MacroAssembler::CmpInstanceTypeRange(Register map, Register scratch,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit) {
|
||||
DCHECK_LT(lower_limit, higher_limit);
|
||||
movzx_w(scratch, FieldOperand(map, Map::kInstanceTypeOffset));
|
||||
lea(scratch, Operand(scratch, 0u - lower_limit));
|
||||
cmp(scratch, Immediate(higher_limit - lower_limit));
|
||||
}
|
||||
|
||||
void MacroAssembler::AssertSmi(Register object) {
|
||||
if (emit_debug_code()) {
|
||||
test(object, Immediate(kSmiTagMask));
|
||||
@ -891,14 +900,16 @@ void MacroAssembler::AssertConstructor(Register object) {
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::AssertFunction(Register object) {
|
||||
void MacroAssembler::AssertFunction(Register object, Register scratch) {
|
||||
if (emit_debug_code()) {
|
||||
test(object, Immediate(kSmiTagMask));
|
||||
Check(not_equal, AbortReason::kOperandIsASmiAndNotAFunction);
|
||||
Push(object);
|
||||
CmpObjectType(object, JS_FUNCTION_TYPE, object);
|
||||
LoadMap(object, object);
|
||||
CmpInstanceTypeRange(object, scratch, FIRST_JS_FUNCTION_TYPE,
|
||||
LAST_JS_FUNCTION_TYPE);
|
||||
Pop(object);
|
||||
Check(equal, AbortReason::kOperandIsNotAFunction);
|
||||
Check(below_equal, AbortReason::kOperandIsNotAFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -810,6 +810,15 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
// Compare instance type for map.
|
||||
void CmpInstanceType(Register map, InstanceType type);
|
||||
|
||||
// Compare instance type ranges for a map (lower_limit and higher_limit
|
||||
// inclusive).
|
||||
//
|
||||
// Always use unsigned comparisons: below_equal for a positive
|
||||
// result.
|
||||
void CmpInstanceTypeRange(Register map, Register scratch,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit);
|
||||
|
||||
// Smi tagging support.
|
||||
void SmiTag(Register reg) {
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
@ -847,7 +856,7 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
void AssertNotSmi(Register object);
|
||||
|
||||
// Abort execution if argument is not a JSFunction, enabled via --debug-code.
|
||||
void AssertFunction(Register object);
|
||||
void AssertFunction(Register object, Register scratch);
|
||||
|
||||
// Abort execution if argument is not a Constructor, enabled via --debug-code.
|
||||
void AssertConstructor(Register object);
|
||||
|
@ -2465,6 +2465,15 @@ void MacroAssembler::CmpInstanceType(Register map, InstanceType type) {
|
||||
cmpw(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type));
|
||||
}
|
||||
|
||||
void MacroAssembler::CmpInstanceTypeRange(Register map,
|
||||
InstanceType lower_limit,
|
||||
InstanceType higher_limit) {
|
||||
DCHECK_LT(lower_limit, higher_limit);
|
||||
movzxwl(kScratchRegister, FieldOperand(map, Map::kInstanceTypeOffset));
|
||||
leal(kScratchRegister, Operand(kScratchRegister, 0u - lower_limit));
|
||||
cmpl(kScratchRegister, Immediate(higher_limit - lower_limit));
|
||||
}
|
||||
|
||||
void MacroAssembler::AssertNotSmi(Register object) {
|
||||
if (emit_debug_code()) {
|
||||
Condition is_smi = CheckSmi(object);
|
||||
@ -2513,9 +2522,10 @@ void MacroAssembler::AssertFunction(Register object) {
|
||||
testb(object, Immediate(kSmiTagMask));
|
||||
Check(not_equal, AbortReason::kOperandIsASmiAndNotAFunction);
|
||||
Push(object);
|
||||
CmpObjectType(object, JS_FUNCTION_TYPE, object);
|
||||
LoadMap(object, object);
|
||||
CmpInstanceTypeRange(object, FIRST_JS_FUNCTION_TYPE, LAST_JS_FUNCTION_TYPE);
|
||||
Pop(object);
|
||||
Check(equal, AbortReason::kOperandIsNotAFunction);
|
||||
Check(below_equal, AbortReason::kOperandIsNotAFunction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -986,6 +986,10 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
|
||||
// Always use unsigned comparisons: above and below, not less and greater.
|
||||
void CmpInstanceType(Register map, InstanceType type);
|
||||
|
||||
// Compare instance type ranges for a map (low and high inclusive)
|
||||
// Always use unsigned comparisons: below_equal for a positive result.
|
||||
void CmpInstanceTypeRange(Register map, InstanceType low, InstanceType high);
|
||||
|
||||
template <typename Field>
|
||||
void DecodeField(Register reg) {
|
||||
static const int shift = Field::kShift;
|
||||
|
@ -1773,8 +1773,10 @@ Node* EffectControlLinearizer::LowerCheckClosure(Node* node,
|
||||
Node* value_map = __ LoadField(AccessBuilder::ForMap(), value);
|
||||
Node* value_instance_type =
|
||||
__ LoadField(AccessBuilder::ForMapInstanceType(), value_map);
|
||||
Node* check_instance_type =
|
||||
__ Word32Equal(value_instance_type, __ Int32Constant(JS_FUNCTION_TYPE));
|
||||
Node* check_instance_type = __ Uint32LessThanOrEqual(
|
||||
__ Int32Sub(value_instance_type,
|
||||
__ Int32Constant(FIRST_JS_FUNCTION_TYPE)),
|
||||
__ Int32Constant(LAST_JS_FUNCTION_TYPE - FIRST_JS_FUNCTION_TYPE));
|
||||
__ DeoptimizeIfNot(DeoptimizeReason::kWrongCallTarget, FeedbackSource(),
|
||||
check_instance_type, frame_state);
|
||||
|
||||
|
@ -271,6 +271,13 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
|
||||
DCHECK(!map.is_undetectable());
|
||||
return kBoundFunction;
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
DCHECK(!map.is_undetectable());
|
||||
return kFunction;
|
||||
case JS_PROXY_TYPE:
|
||||
|
@ -265,6 +265,16 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
|
||||
case STORE_HANDLER_TYPE:
|
||||
StoreHandler::cast(*this).StoreHandlerVerify(isolate);
|
||||
break;
|
||||
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
JSFunction::cast(*this).JSFunctionVerify(isolate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,7 +492,8 @@ void Map::MapVerify(Isolate* isolate) {
|
||||
layout_descriptor(kAcquireLoad).IsConsistentWithMap(*this));
|
||||
// Only JSFunction maps have has_prototype_slot() bit set and constructible
|
||||
// JSFunction objects must have prototype slot.
|
||||
CHECK_IMPLIES(has_prototype_slot(), instance_type() == JS_FUNCTION_TYPE);
|
||||
CHECK_IMPLIES(has_prototype_slot(),
|
||||
InstanceTypeChecker::IsJSFunction(instance_type()));
|
||||
if (!may_have_interesting_symbols()) {
|
||||
CHECK(!has_named_interceptor());
|
||||
CHECK(!is_dictionary_map());
|
||||
|
@ -215,6 +215,15 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
|
||||
case FEEDBACK_METADATA_TYPE:
|
||||
FeedbackMetadata::cast(*this).FeedbackMetadataPrint(os);
|
||||
break;
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
JSFunction::cast(*this).JSFunctionPrint(os);
|
||||
break;
|
||||
case INTERNALIZED_STRING_TYPE:
|
||||
case EXTERNAL_INTERNALIZED_STRING_TYPE:
|
||||
case ONE_BYTE_INTERNALIZED_STRING_TYPE:
|
||||
|
@ -2125,7 +2125,7 @@ Handle<JSObject> Factory::NewJSObjectFromMap(
|
||||
Handle<AllocationSite> allocation_site) {
|
||||
// JSFunctions should be allocated using AllocateFunction to be
|
||||
// properly initialized.
|
||||
DCHECK(map->instance_type() != JS_FUNCTION_TYPE);
|
||||
DCHECK(!InstanceTypeChecker::IsJSFunction((map->instance_type())));
|
||||
|
||||
// Both types of global objects should be allocated using
|
||||
// AllocateGlobalObject to be properly initialized.
|
||||
@ -3510,7 +3510,7 @@ Handle<JSFunction> Factory::JSFunctionBuilder::BuildRaw(Handle<Code> code) {
|
||||
Handle<Map> map = maybe_map_.ToHandleChecked();
|
||||
Handle<FeedbackCell> feedback_cell = maybe_feedback_cell_.ToHandleChecked();
|
||||
|
||||
DCHECK_EQ(JS_FUNCTION_TYPE, map->instance_type());
|
||||
DCHECK(InstanceTypeChecker::IsJSFunction(map->instance_type()));
|
||||
|
||||
// Allocation.
|
||||
Handle<JSFunction> function(
|
||||
|
@ -2890,8 +2890,7 @@ void AccessorAssembler::LoadIC_NoFeedback(const LoadICParameters* p,
|
||||
// Special case for Function.prototype load, because it's very common
|
||||
// for ICs that are only executed once (MyFunc.prototype.foo = ...).
|
||||
Label not_function_prototype(this, Label::kDeferred);
|
||||
GotoIfNot(InstanceTypeEqual(instance_type, JS_FUNCTION_TYPE),
|
||||
¬_function_prototype);
|
||||
GotoIfNot(IsJSFunctionInstanceType(instance_type), ¬_function_prototype);
|
||||
GotoIfNot(IsPrototypeString(p->name()), ¬_function_prototype);
|
||||
|
||||
GotoIfPrototypeRequiresRuntimeLookup(CAST(lookup_start_object),
|
||||
|
@ -239,7 +239,8 @@ class Genesis {
|
||||
bool InstallExtrasBindings();
|
||||
|
||||
Handle<JSFunction> InstallTypedArray(const char* name,
|
||||
ElementsKind elements_kind);
|
||||
ElementsKind elements_kind,
|
||||
InstanceType type);
|
||||
void InitializeNormalizedMapCaches();
|
||||
|
||||
enum ExtensionTraversalState { UNVISITED, VISITED, INSTALLED };
|
||||
@ -518,6 +519,24 @@ V8_NOINLINE Handle<JSFunction> InstallFunction(
|
||||
instance_size, inobject_properties, prototype, call);
|
||||
}
|
||||
|
||||
// This installs an instance type (|constructor_type|) on the constructor map
|
||||
// which will be used for protector cell checks -- this is separate from |type|
|
||||
// which is used to set the instance type of the object created by this
|
||||
// constructor. If protector cell checks are not required, continue to use the
|
||||
// default JS_FUNCTION_TYPE by directly calling InstallFunction.
|
||||
V8_NOINLINE Handle<JSFunction> InstallConstructor(
|
||||
Isolate* isolate, Handle<JSObject> target, const char* name,
|
||||
InstanceType type, int instance_size, int inobject_properties,
|
||||
Handle<HeapObject> prototype, Builtins::Name call,
|
||||
InstanceType constructor_type) {
|
||||
Handle<JSFunction> function = InstallFunction(
|
||||
isolate, target, isolate->factory()->InternalizeUtf8String(name), type,
|
||||
instance_size, inobject_properties, prototype, call);
|
||||
DCHECK(InstanceTypeChecker::IsJSFunction(constructor_type));
|
||||
function->map().set_instance_type(constructor_type);
|
||||
return function;
|
||||
}
|
||||
|
||||
V8_NOINLINE Handle<JSFunction> SimpleCreateFunction(Isolate* isolate,
|
||||
Handle<String> name,
|
||||
Builtins::Name call,
|
||||
@ -1702,9 +1721,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
|
||||
Handle<JSFunction> array_prototype_to_string_fun;
|
||||
{ // --- A r r a y ---
|
||||
Handle<JSFunction> array_function = InstallFunction(
|
||||
Handle<JSFunction> array_function = InstallConstructor(
|
||||
isolate_, global, "Array", JS_ARRAY_TYPE, JSArray::kHeaderSize, 0,
|
||||
isolate_->initial_object_prototype(), Builtins::kArrayConstructor);
|
||||
isolate_->initial_object_prototype(), Builtins::kArrayConstructor,
|
||||
JS_ARRAY_CONSTRUCTOR_TYPE);
|
||||
array_function->shared().DontAdaptArguments();
|
||||
|
||||
// This seems a bit hackish, but we need to make sure Array.length
|
||||
@ -2390,10 +2410,10 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
}
|
||||
|
||||
{ // -- P r o m i s e
|
||||
Handle<JSFunction> promise_fun = InstallFunction(
|
||||
Handle<JSFunction> promise_fun = InstallConstructor(
|
||||
isolate_, global, "Promise", JS_PROMISE_TYPE,
|
||||
JSPromise::kSizeWithEmbedderFields, 0, factory->the_hole_value(),
|
||||
Builtins::kPromiseConstructor);
|
||||
Builtins::kPromiseConstructor, JS_PROMISE_CONSTRUCTOR_TYPE);
|
||||
InstallWithIntrinsicDefaultProto(isolate_, promise_fun,
|
||||
Context::PROMISE_FUNCTION_INDEX);
|
||||
|
||||
@ -2453,14 +2473,13 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
|
||||
{ // -- R e g E x p
|
||||
// Builtin functions for RegExp.prototype.
|
||||
Handle<JSFunction> regexp_fun = InstallFunction(
|
||||
Handle<JSFunction> regexp_fun = InstallConstructor(
|
||||
isolate_, global, "RegExp", JS_REG_EXP_TYPE,
|
||||
JSRegExp::kHeaderSize + JSRegExp::kInObjectFieldCount * kTaggedSize,
|
||||
JSRegExp::kInObjectFieldCount, factory->the_hole_value(),
|
||||
Builtins::kRegExpConstructor);
|
||||
Builtins::kRegExpConstructor, JS_REG_EXP_CONSTRUCTOR_TYPE);
|
||||
InstallWithIntrinsicDefaultProto(isolate_, regexp_fun,
|
||||
Context::REGEXP_FUNCTION_INDEX);
|
||||
|
||||
Handle<SharedFunctionInfo> shared(regexp_fun->shared(), isolate_);
|
||||
shared->set_internal_formal_parameter_count(2);
|
||||
shared->set_length(2);
|
||||
@ -3432,12 +3451,12 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
}
|
||||
|
||||
{// -- T y p e d A r r a y s
|
||||
#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype) \
|
||||
{ \
|
||||
Handle<JSFunction> fun = \
|
||||
InstallTypedArray(#Type "Array", TYPE##_ELEMENTS); \
|
||||
InstallWithIntrinsicDefaultProto(isolate_, fun, \
|
||||
Context::TYPE##_ARRAY_FUN_INDEX); \
|
||||
#define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype) \
|
||||
{ \
|
||||
Handle<JSFunction> fun = InstallTypedArray( \
|
||||
#Type "Array", TYPE##_ELEMENTS, TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE); \
|
||||
InstallWithIntrinsicDefaultProto(isolate_, fun, \
|
||||
Context::TYPE##_ARRAY_FUN_INDEX); \
|
||||
}
|
||||
TYPED_ARRAYS(INSTALL_TYPED_ARRAY)
|
||||
#undef INSTALL_TYPED_ARRAY
|
||||
@ -4012,17 +4031,18 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
} // NOLINT(readability/fn_size)
|
||||
|
||||
Handle<JSFunction> Genesis::InstallTypedArray(const char* name,
|
||||
ElementsKind elements_kind) {
|
||||
ElementsKind elements_kind,
|
||||
InstanceType type) {
|
||||
Handle<JSObject> global =
|
||||
Handle<JSObject>(native_context()->global_object(), isolate());
|
||||
|
||||
Handle<JSObject> typed_array_prototype = isolate()->typed_array_prototype();
|
||||
Handle<JSFunction> typed_array_function = isolate()->typed_array_function();
|
||||
|
||||
Handle<JSFunction> result = InstallFunction(
|
||||
Handle<JSFunction> result = InstallConstructor(
|
||||
isolate(), global, name, JS_TYPED_ARRAY_TYPE,
|
||||
JSTypedArray::kSizeWithEmbedderFields, 0, factory()->the_hole_value(),
|
||||
Builtins::kTypedArrayConstructor);
|
||||
Builtins::kTypedArrayConstructor, type);
|
||||
result->initial_map().set_elements_kind(elements_kind);
|
||||
|
||||
result->shared().DontAdaptArguments();
|
||||
|
@ -929,8 +929,8 @@ TNode<Object> InterpreterAssembler::ConstructWithSpread(
|
||||
TNode<Uint16T> current_instance_type = LoadInstanceType(current);
|
||||
GotoIf(InstanceTypeEqual(current_instance_type, JS_BOUND_FUNCTION_TYPE),
|
||||
&if_boundfunction);
|
||||
Branch(InstanceTypeEqual(current_instance_type, JS_FUNCTION_TYPE),
|
||||
&if_function, &mark_megamorphic);
|
||||
Branch(IsJSFunctionInstanceType(current_instance_type), &if_function,
|
||||
&mark_megamorphic);
|
||||
|
||||
BIND(&if_function);
|
||||
{
|
||||
|
@ -58,3 +58,40 @@ StoreJSTypedArrayExternalPointerPtr(JSTypedArray, RawPtr);
|
||||
extern class JSDataView extends JSArrayBufferView {
|
||||
data_pointer: ExternalPointer;
|
||||
}
|
||||
|
||||
@abstract
|
||||
@doNotGenerateCast extern class TypedArrayConstructor extends JSFunction
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Uint8TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Int8TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Uint16TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Int16TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Uint32TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Int32TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Float32TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Float64TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Uint8ClampedTypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Biguint64TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
@doNotGenerateCast
|
||||
extern class Bigint64TypedArrayConstructor extends TypedArrayConstructor
|
||||
generates 'TNode<JSFunction>';
|
||||
|
@ -31,6 +31,10 @@ extern class JSArray extends JSObject {
|
||||
length: Number;
|
||||
}
|
||||
|
||||
@doNotGenerateCast
|
||||
extern class JSArrayConstructor extends JSFunction
|
||||
generates 'TNode<JSFunction>';
|
||||
|
||||
macro NewJSArray(implicit context: Context)(
|
||||
map: Map, elements: FixedArrayBase): JSArray {
|
||||
return new JSArray{
|
||||
|
@ -520,8 +520,15 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
|
||||
case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
|
||||
case JS_DATA_VIEW_TYPE:
|
||||
case JS_DATE_TYPE:
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_GENERATOR_OBJECT_TYPE:
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
case JS_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
|
||||
case JS_OBJECT_PROTOTYPE_TYPE:
|
||||
|
@ -2128,7 +2128,8 @@ MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
|
||||
DCHECK(constructor->IsConstructor());
|
||||
DCHECK(new_target->IsConstructor());
|
||||
DCHECK(!constructor->has_initial_map() ||
|
||||
constructor->initial_map().instance_type() != JS_FUNCTION_TYPE);
|
||||
!InstanceTypeChecker::IsJSFunction(
|
||||
constructor->initial_map().instance_type()));
|
||||
|
||||
Handle<Map> initial_map;
|
||||
ASSIGN_RETURN_ON_EXCEPTION(
|
||||
@ -2205,6 +2206,13 @@ int JSObject::GetHeaderSize(InstanceType type,
|
||||
case JS_BOUND_FUNCTION_TYPE:
|
||||
return JSBoundFunction::kHeaderSize;
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
return JSFunction::GetHeaderSize(function_has_prototype_slot);
|
||||
case JS_PRIMITIVE_WRAPPER_TYPE:
|
||||
return JSPrimitiveWrapper::kHeaderSize;
|
||||
@ -2527,6 +2535,13 @@ void JSObject::JSObjectShortPrint(StringStream* accumulator) {
|
||||
|
||||
break;
|
||||
}
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
case JS_FUNCTION_TYPE: {
|
||||
JSFunction function = JSFunction::cast(*this);
|
||||
std::unique_ptr<char[]> fun_name = function.shared().DebugNameCStr();
|
||||
|
@ -35,3 +35,7 @@ extern class JSPromise extends JSObject {
|
||||
reactions_or_result: Zero|PromiseReaction|JSAny;
|
||||
flags: SmiTagged<JSPromiseFlags>;
|
||||
}
|
||||
|
||||
@doNotGenerateCast
|
||||
extern class JSPromiseConstructor extends JSFunction
|
||||
generates 'TNode<JSFunction>';
|
||||
|
@ -48,6 +48,10 @@ extern shape JSRegExpResult extends JSArray {
|
||||
regexp_last_index: Smi;
|
||||
}
|
||||
|
||||
@doNotGenerateCast
|
||||
extern class JSRegExpConstructor extends JSFunction
|
||||
generates 'TNode<JSFunction>';
|
||||
|
||||
extern shape JSRegExpResultIndices extends JSArray {
|
||||
// In-object properties:
|
||||
// The groups field is externally exposed.
|
||||
|
@ -174,26 +174,6 @@ void LookupIterator::ReloadPropertyInformation() {
|
||||
DCHECK(IsFound() || !holder_->HasFastProperties(isolate_));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsTypedArrayFunctionInAnyContext(Isolate* isolate, HeapObject object) {
|
||||
static uint32_t context_slots[] = {
|
||||
#define TYPED_ARRAY_CONTEXT_SLOTS(Type, type, TYPE, ctype) \
|
||||
Context::TYPE##_ARRAY_FUN_INDEX,
|
||||
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONTEXT_SLOTS)
|
||||
#undef TYPED_ARRAY_CONTEXT_SLOTS
|
||||
};
|
||||
|
||||
if (!object.IsJSFunction(isolate)) return false;
|
||||
|
||||
return std::any_of(
|
||||
std::begin(context_slots), std::end(context_slots),
|
||||
[=](uint32_t slot) { return isolate->IsInAnyContext(object, slot); });
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void LookupIterator::InternalUpdateProtector(Isolate* isolate,
|
||||
Handle<Object> receiver_generic,
|
||||
@ -282,20 +262,18 @@ void LookupIterator::InternalUpdateProtector(Isolate* isolate,
|
||||
}
|
||||
// Setting the Symbol.species property of any Array, Promise or TypedArray
|
||||
// constructor invalidates the @@species protector
|
||||
if (isolate->IsInAnyContext(*receiver, Context::ARRAY_FUNCTION_INDEX)) {
|
||||
if (receiver->IsJSArrayConstructor()) {
|
||||
if (!Protectors::IsArraySpeciesLookupChainIntact(isolate)) return;
|
||||
isolate->CountUsage(
|
||||
v8::Isolate::UseCounterFeature::kArraySpeciesModified);
|
||||
Protectors::InvalidateArraySpeciesLookupChain(isolate);
|
||||
} else if (isolate->IsInAnyContext(*receiver,
|
||||
Context::PROMISE_FUNCTION_INDEX)) {
|
||||
} else if (receiver->IsJSPromiseConstructor()) {
|
||||
if (!Protectors::IsPromiseSpeciesLookupChainIntact(isolate)) return;
|
||||
Protectors::InvalidatePromiseSpeciesLookupChain(isolate);
|
||||
} else if (isolate->IsInAnyContext(*receiver,
|
||||
Context::REGEXP_FUNCTION_INDEX)) {
|
||||
} else if (receiver->IsJSRegExpConstructor()) {
|
||||
if (!Protectors::IsRegExpSpeciesLookupChainIntact(isolate)) return;
|
||||
Protectors::InvalidateRegExpSpeciesLookupChain(isolate);
|
||||
} else if (IsTypedArrayFunctionInAnyContext(isolate, *receiver)) {
|
||||
} else if (receiver->IsTypedArrayConstructor()) {
|
||||
if (!Protectors::IsTypedArraySpeciesLookupChainIntact(isolate)) return;
|
||||
Protectors::InvalidateTypedArraySpeciesLookupChain(isolate);
|
||||
}
|
||||
@ -337,7 +315,7 @@ void LookupIterator::InternalUpdateProtector(Isolate* isolate,
|
||||
if (!Protectors::IsPromiseResolveLookupChainIntact(isolate)) return;
|
||||
// Setting the "resolve" property on any %Promise% intrinsic object
|
||||
// invalidates the Promise.resolve protector.
|
||||
if (isolate->IsInAnyContext(*receiver, Context::PROMISE_FUNCTION_INDEX)) {
|
||||
if (receiver->IsJSPromiseConstructor()) {
|
||||
Protectors::InvalidatePromiseResolveLookupChain(isolate);
|
||||
}
|
||||
} else if (*name == roots.then_string()) {
|
||||
|
@ -222,6 +222,13 @@ VisitorId Map::GetVisitorId(Map map) {
|
||||
return kVisitJSDataView;
|
||||
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
return kVisitJSFunction;
|
||||
|
||||
case JS_TYPED_ARRAY_TYPE:
|
||||
@ -1911,7 +1918,7 @@ Handle<Map> Map::CopyAsElementsKind(Isolate* isolate, Handle<Map> map,
|
||||
|
||||
Handle<Map> Map::AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
|
||||
Handle<SharedFunctionInfo> shared_info) {
|
||||
DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
|
||||
DCHECK(InstanceTypeChecker::IsJSFunction(initial_map->instance_type()));
|
||||
// Initial map for sloppy mode function is stored in the function
|
||||
// constructor. Initial maps for strict mode are cached as special transitions
|
||||
// using |strict_function_transition_symbol| as a key.
|
||||
@ -2482,7 +2489,7 @@ bool Map::EquivalentToForTransition(const Map other) const {
|
||||
if (bit_field() != other.bit_field()) return false;
|
||||
if (new_target_is_base() != other.new_target_is_base()) return false;
|
||||
if (prototype() != other.prototype()) return false;
|
||||
if (instance_type() == JS_FUNCTION_TYPE) {
|
||||
if (InstanceTypeChecker::IsJSFunction(instance_type())) {
|
||||
// JSFunctions require more checks to ensure that sloppy function is
|
||||
// not equivalent to strict function.
|
||||
int nof =
|
||||
|
@ -265,6 +265,9 @@ class ZoneForwardList;
|
||||
V(FreeSpaceOrFiller) \
|
||||
V(FunctionContext) \
|
||||
V(JSApiObject) \
|
||||
V(JSPromiseConstructor) \
|
||||
V(JSArrayConstructor) \
|
||||
V(JSRegExpConstructor) \
|
||||
V(JSMapKeyIterator) \
|
||||
V(JSMapKeyValueIterator) \
|
||||
V(JSMapValueIterator) \
|
||||
@ -285,7 +288,19 @@ class ZoneForwardList;
|
||||
V(JSMapIteratorPrototype) \
|
||||
V(JSTypedArrayPrototype) \
|
||||
V(JSSetIteratorPrototype) \
|
||||
V(JSStringIteratorPrototype)
|
||||
V(JSStringIteratorPrototype) \
|
||||
V(TypedArrayConstructor) \
|
||||
V(Uint8TypedArrayConstructor) \
|
||||
V(Int8TypedArrayConstructor) \
|
||||
V(Uint16TypedArrayConstructor) \
|
||||
V(Int16TypedArrayConstructor) \
|
||||
V(Uint32TypedArrayConstructor) \
|
||||
V(Int32TypedArrayConstructor) \
|
||||
V(Float32TypedArrayConstructor) \
|
||||
V(Float64TypedArrayConstructor) \
|
||||
V(Uint8ClampedTypedArrayConstructor) \
|
||||
V(Biguint64TypedArrayConstructor) \
|
||||
V(Bigint64TypedArrayConstructor)
|
||||
|
||||
#define HEAP_OBJECT_TYPE_LIST(V) \
|
||||
HEAP_OBJECT_ORDINARY_TYPE_LIST(V) \
|
||||
|
@ -1011,6 +1011,13 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
|
||||
case JS_TYPED_ARRAY_TYPE:
|
||||
return Op::template apply<JSTypedArray::BodyDescriptor>(p1, p2, p3, p4);
|
||||
case JS_FUNCTION_TYPE:
|
||||
case JS_PROMISE_CONSTRUCTOR_TYPE:
|
||||
case JS_REG_EXP_CONSTRUCTOR_TYPE:
|
||||
case JS_ARRAY_CONSTRUCTOR_TYPE:
|
||||
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
|
||||
case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
|
||||
TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
|
||||
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
|
||||
return Op::template apply<JSFunction::BodyDescriptor>(p1, p2, p3, p4);
|
||||
case WEAK_CELL_TYPE:
|
||||
return Op::template apply<WeakCell::BodyDescriptor>(p1, p2, p3, p4);
|
||||
|
@ -167,51 +167,65 @@ INSTANCE_TYPES = {
|
||||
1054: "JS_ASYNC_GENERATOR_OBJECT_TYPE",
|
||||
1055: "JS_ARGUMENTS_OBJECT_TYPE",
|
||||
1056: "JS_API_OBJECT_TYPE",
|
||||
1058: "JS_MAP_KEY_ITERATOR_TYPE",
|
||||
1059: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
|
||||
1060: "JS_MAP_VALUE_ITERATOR_TYPE",
|
||||
1061: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
|
||||
1062: "JS_SET_VALUE_ITERATOR_TYPE",
|
||||
1063: "JS_DATA_VIEW_TYPE",
|
||||
1064: "JS_TYPED_ARRAY_TYPE",
|
||||
1065: "JS_MAP_TYPE",
|
||||
1066: "JS_SET_TYPE",
|
||||
1067: "JS_BOUND_FUNCTION_TYPE",
|
||||
1068: "JS_FUNCTION_TYPE",
|
||||
1069: "JS_WEAK_MAP_TYPE",
|
||||
1070: "JS_WEAK_SET_TYPE",
|
||||
1071: "JS_ARRAY_TYPE",
|
||||
1072: "JS_ARRAY_BUFFER_TYPE",
|
||||
1073: "JS_ARRAY_ITERATOR_TYPE",
|
||||
1074: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
|
||||
1075: "JS_COLLATOR_TYPE",
|
||||
1076: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
|
||||
1077: "JS_DATE_TYPE",
|
||||
1078: "JS_DATE_TIME_FORMAT_TYPE",
|
||||
1079: "JS_DISPLAY_NAMES_TYPE",
|
||||
1080: "JS_ERROR_TYPE",
|
||||
1081: "JS_FINALIZATION_REGISTRY_TYPE",
|
||||
1082: "JS_LIST_FORMAT_TYPE",
|
||||
1083: "JS_LOCALE_TYPE",
|
||||
1084: "JS_MESSAGE_OBJECT_TYPE",
|
||||
1085: "JS_NUMBER_FORMAT_TYPE",
|
||||
1086: "JS_PLURAL_RULES_TYPE",
|
||||
1087: "JS_PROMISE_TYPE",
|
||||
1088: "JS_REG_EXP_TYPE",
|
||||
1089: "JS_REG_EXP_STRING_ITERATOR_TYPE",
|
||||
1090: "JS_RELATIVE_TIME_FORMAT_TYPE",
|
||||
1091: "JS_SEGMENT_ITERATOR_TYPE",
|
||||
1092: "JS_SEGMENTER_TYPE",
|
||||
1093: "JS_SEGMENTS_TYPE",
|
||||
1094: "JS_STRING_ITERATOR_TYPE",
|
||||
1095: "JS_V8_BREAK_ITERATOR_TYPE",
|
||||
1096: "JS_WEAK_REF_TYPE",
|
||||
1097: "WASM_EXCEPTION_OBJECT_TYPE",
|
||||
1098: "WASM_GLOBAL_OBJECT_TYPE",
|
||||
1099: "WASM_INSTANCE_OBJECT_TYPE",
|
||||
1100: "WASM_MEMORY_OBJECT_TYPE",
|
||||
1101: "WASM_MODULE_OBJECT_TYPE",
|
||||
1102: "WASM_TABLE_OBJECT_TYPE",
|
||||
1058: "JS_BOUND_FUNCTION_TYPE",
|
||||
1059: "JS_FUNCTION_TYPE",
|
||||
1060: "BIGINT64_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1061: "BIGUINT64_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1062: "FLOAT32_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1063: "FLOAT64_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1064: "INT16_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1065: "INT32_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1066: "INT8_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1067: "UINT16_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1068: "UINT32_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1069: "UINT8_CLAMPED_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1070: "UINT8_TYPED_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1071: "JS_ARRAY_CONSTRUCTOR_TYPE",
|
||||
1072: "JS_PROMISE_CONSTRUCTOR_TYPE",
|
||||
1073: "JS_REG_EXP_CONSTRUCTOR_TYPE",
|
||||
1074: "JS_MAP_KEY_ITERATOR_TYPE",
|
||||
1075: "JS_MAP_KEY_VALUE_ITERATOR_TYPE",
|
||||
1076: "JS_MAP_VALUE_ITERATOR_TYPE",
|
||||
1077: "JS_SET_KEY_VALUE_ITERATOR_TYPE",
|
||||
1078: "JS_SET_VALUE_ITERATOR_TYPE",
|
||||
1079: "JS_DATA_VIEW_TYPE",
|
||||
1080: "JS_TYPED_ARRAY_TYPE",
|
||||
1081: "JS_MAP_TYPE",
|
||||
1082: "JS_SET_TYPE",
|
||||
1083: "JS_WEAK_MAP_TYPE",
|
||||
1084: "JS_WEAK_SET_TYPE",
|
||||
1085: "JS_ARRAY_TYPE",
|
||||
1086: "JS_ARRAY_BUFFER_TYPE",
|
||||
1087: "JS_ARRAY_ITERATOR_TYPE",
|
||||
1088: "JS_ASYNC_FROM_SYNC_ITERATOR_TYPE",
|
||||
1089: "JS_COLLATOR_TYPE",
|
||||
1090: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
|
||||
1091: "JS_DATE_TYPE",
|
||||
1092: "JS_DATE_TIME_FORMAT_TYPE",
|
||||
1093: "JS_DISPLAY_NAMES_TYPE",
|
||||
1094: "JS_ERROR_TYPE",
|
||||
1095: "JS_FINALIZATION_REGISTRY_TYPE",
|
||||
1096: "JS_LIST_FORMAT_TYPE",
|
||||
1097: "JS_LOCALE_TYPE",
|
||||
1098: "JS_MESSAGE_OBJECT_TYPE",
|
||||
1099: "JS_NUMBER_FORMAT_TYPE",
|
||||
1100: "JS_PLURAL_RULES_TYPE",
|
||||
1101: "JS_PROMISE_TYPE",
|
||||
1102: "JS_REG_EXP_TYPE",
|
||||
1103: "JS_REG_EXP_STRING_ITERATOR_TYPE",
|
||||
1104: "JS_RELATIVE_TIME_FORMAT_TYPE",
|
||||
1105: "JS_SEGMENT_ITERATOR_TYPE",
|
||||
1106: "JS_SEGMENTER_TYPE",
|
||||
1107: "JS_SEGMENTS_TYPE",
|
||||
1108: "JS_STRING_ITERATOR_TYPE",
|
||||
1109: "JS_V8_BREAK_ITERATOR_TYPE",
|
||||
1110: "JS_WEAK_REF_TYPE",
|
||||
1111: "WASM_EXCEPTION_OBJECT_TYPE",
|
||||
1112: "WASM_GLOBAL_OBJECT_TYPE",
|
||||
1113: "WASM_INSTANCE_OBJECT_TYPE",
|
||||
1114: "WASM_MEMORY_OBJECT_TYPE",
|
||||
1115: "WASM_MODULE_OBJECT_TYPE",
|
||||
1116: "WASM_TABLE_OBJECT_TYPE",
|
||||
}
|
||||
|
||||
# List of known V8 maps.
|
||||
@ -368,7 +382,7 @@ KNOWN_MAPS = {
|
||||
("read_only_space", 0x05d05): (78, "StoreHandler2Map"),
|
||||
("read_only_space", 0x05d2d): (78, "StoreHandler3Map"),
|
||||
("map_space", 0x02115): (1057, "ExternalMap"),
|
||||
("map_space", 0x0213d): (1084, "JSMessageObjectMap"),
|
||||
("map_space", 0x0213d): (1098, "JSMessageObjectMap"),
|
||||
("map_space", 0x02165): (181, "WasmRttEqrefMap"),
|
||||
("map_space", 0x0218d): (181, "WasmRttAnyrefMap"),
|
||||
("map_space", 0x021b5): (181, "WasmRttExternrefMap"),
|
||||
|
Loading…
Reference in New Issue
Block a user