Reland of [refactoring] Split CodeAssemblerState out of CodeAssembler
This is in preparation for introducing more specialized CodeStubAssembler subclasses. The state object can be handed around, while the Assembler instances are temporary-scoped. BUG=v8:5628 Original review: https://codereview.chromium.org/2498073002/ Review-Url: https://codereview.chromium.org/2502293002 Cr-Commit-Position: refs/heads/master@{#41028}
This commit is contained in:
parent
c93bdaaff1
commit
87a65911b9
File diff suppressed because it is too large
Load Diff
@ -34,28 +34,32 @@ BUILTIN(BooleanConstructor_ConstructStub) {
|
||||
}
|
||||
|
||||
// ES6 section 19.3.3.2 Boolean.prototype.toString ( )
|
||||
void Builtins::Generate_BooleanPrototypeToString(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_BooleanPrototypeToString(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* value = assembler->ToThisValue(
|
||||
Node* value = assembler.ToThisValue(
|
||||
context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.toString");
|
||||
Node* result = assembler->LoadObjectField(value, Oddball::kToStringOffset);
|
||||
assembler->Return(result);
|
||||
Node* result = assembler.LoadObjectField(value, Oddball::kToStringOffset);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 19.3.3.3 Boolean.prototype.valueOf ( )
|
||||
void Builtins::Generate_BooleanPrototypeValueOf(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_BooleanPrototypeValueOf(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* result = assembler->ToThisValue(
|
||||
Node* result = assembler.ToThisValue(
|
||||
context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.valueOf");
|
||||
assembler->Return(result);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -95,110 +95,117 @@ void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler,
|
||||
} // anonymous namespace
|
||||
|
||||
void Builtins::Generate_NonPrimitiveToPrimitive_Default(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kDefault);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kDefault);
|
||||
}
|
||||
|
||||
void Builtins::Generate_NonPrimitiveToPrimitive_Number(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kNumber);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kNumber);
|
||||
}
|
||||
|
||||
void Builtins::Generate_NonPrimitiveToPrimitive_String(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kString);
|
||||
}
|
||||
|
||||
void Builtins::Generate_StringToNumber(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringToNumber(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* input = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* input = assembler.Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->StringToNumber(context, input));
|
||||
assembler.Return(assembler.StringToNumber(context, input));
|
||||
}
|
||||
|
||||
void Builtins::Generate_ToName(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToName(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* input = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* input = assembler.Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->ToName(context, input));
|
||||
assembler.Return(assembler.ToName(context, input));
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_NonNumberToNumber(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* input = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* input = assembler.Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->NonNumberToNumber(context, input));
|
||||
assembler.Return(assembler.NonNumberToNumber(context, input));
|
||||
}
|
||||
|
||||
// ES6 section 7.1.3 ToNumber ( argument )
|
||||
void Builtins::Generate_ToNumber(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToNumber(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* input = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* input = assembler.Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->ToNumber(context, input));
|
||||
assembler.Return(assembler.ToNumber(context, input));
|
||||
}
|
||||
|
||||
void Builtins::Generate_ToString(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToString(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* input = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* input = assembler.Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
Label is_number(assembler);
|
||||
Label runtime(assembler);
|
||||
Label is_number(&assembler);
|
||||
Label runtime(&assembler);
|
||||
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(input), &is_number);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(input), &is_number);
|
||||
|
||||
Node* input_map = assembler->LoadMap(input);
|
||||
Node* input_instance_type = assembler->LoadMapInstanceType(input_map);
|
||||
Node* input_map = assembler.LoadMap(input);
|
||||
Node* input_instance_type = assembler.LoadMapInstanceType(input_map);
|
||||
|
||||
Label not_string(assembler);
|
||||
assembler->GotoUnless(assembler->IsStringInstanceType(input_instance_type),
|
||||
¬_string);
|
||||
assembler->Return(input);
|
||||
Label not_string(&assembler);
|
||||
assembler.GotoUnless(assembler.IsStringInstanceType(input_instance_type),
|
||||
¬_string);
|
||||
assembler.Return(input);
|
||||
|
||||
Label not_heap_number(assembler);
|
||||
Label not_heap_number(&assembler);
|
||||
|
||||
assembler->Bind(¬_string);
|
||||
assembler.Bind(¬_string);
|
||||
{
|
||||
assembler->GotoUnless(
|
||||
assembler->WordEqual(input_map, assembler->HeapNumberMapConstant()),
|
||||
assembler.GotoUnless(
|
||||
assembler.WordEqual(input_map, assembler.HeapNumberMapConstant()),
|
||||
¬_heap_number);
|
||||
assembler->Goto(&is_number);
|
||||
assembler.Goto(&is_number);
|
||||
}
|
||||
|
||||
assembler->Bind(&is_number);
|
||||
{ assembler->Return(assembler->NumberToString(context, input)); }
|
||||
assembler.Bind(&is_number);
|
||||
{ assembler.Return(assembler.NumberToString(context, input)); }
|
||||
|
||||
assembler->Bind(¬_heap_number);
|
||||
assembler.Bind(¬_heap_number);
|
||||
{
|
||||
assembler->GotoIf(
|
||||
assembler->Word32NotEqual(input_instance_type,
|
||||
assembler->Int32Constant(ODDBALL_TYPE)),
|
||||
assembler.GotoIf(
|
||||
assembler.Word32NotEqual(input_instance_type,
|
||||
assembler.Int32Constant(ODDBALL_TYPE)),
|
||||
&runtime);
|
||||
assembler->Return(
|
||||
assembler->LoadObjectField(input, Oddball::kToStringOffset));
|
||||
assembler.Return(
|
||||
assembler.LoadObjectField(input, Oddball::kToStringOffset));
|
||||
}
|
||||
|
||||
assembler->Bind(&runtime);
|
||||
assembler.Bind(&runtime);
|
||||
{
|
||||
assembler->Return(
|
||||
assembler->CallRuntime(Runtime::kToString, context, input));
|
||||
assembler.Return(assembler.CallRuntime(Runtime::kToString, context, input));
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,194 +290,201 @@ void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler,
|
||||
} // anonymous namespace
|
||||
|
||||
void Builtins::Generate_OrdinaryToPrimitive_Number(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kNumber);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kNumber);
|
||||
}
|
||||
|
||||
void Builtins::Generate_OrdinaryToPrimitive_String(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kString);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kString);
|
||||
}
|
||||
|
||||
// ES6 section 7.1.2 ToBoolean ( argument )
|
||||
void Builtins::Generate_ToBoolean(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToBoolean(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* value = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* value = assembler.Parameter(Descriptor::kArgument);
|
||||
|
||||
Label return_true(assembler), return_false(assembler);
|
||||
assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false);
|
||||
Label return_true(&assembler), return_false(&assembler);
|
||||
assembler.BranchIfToBooleanIsTrue(value, &return_true, &return_false);
|
||||
|
||||
assembler->Bind(&return_true);
|
||||
assembler->Return(assembler->BooleanConstant(true));
|
||||
assembler.Bind(&return_true);
|
||||
assembler.Return(assembler.BooleanConstant(true));
|
||||
|
||||
assembler->Bind(&return_false);
|
||||
assembler->Return(assembler->BooleanConstant(false));
|
||||
assembler.Bind(&return_false);
|
||||
assembler.Return(assembler.BooleanConstant(false));
|
||||
}
|
||||
|
||||
void Builtins::Generate_ToLength(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToLength(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* context = assembler->Parameter(1);
|
||||
Node* context = assembler.Parameter(1);
|
||||
|
||||
// We might need to loop once for ToNumber conversion.
|
||||
Variable var_len(assembler, MachineRepresentation::kTagged);
|
||||
Label loop(assembler, &var_len);
|
||||
var_len.Bind(assembler->Parameter(0));
|
||||
assembler->Goto(&loop);
|
||||
assembler->Bind(&loop);
|
||||
Variable var_len(&assembler, MachineRepresentation::kTagged);
|
||||
Label loop(&assembler, &var_len);
|
||||
var_len.Bind(assembler.Parameter(0));
|
||||
assembler.Goto(&loop);
|
||||
assembler.Bind(&loop);
|
||||
{
|
||||
// Shared entry points.
|
||||
Label return_len(assembler),
|
||||
return_two53minus1(assembler, Label::kDeferred),
|
||||
return_zero(assembler, Label::kDeferred);
|
||||
Label return_len(&assembler),
|
||||
return_two53minus1(&assembler, Label::kDeferred),
|
||||
return_zero(&assembler, Label::kDeferred);
|
||||
|
||||
// Load the current {len} value.
|
||||
Node* len = var_len.value();
|
||||
|
||||
// Check if {len} is a positive Smi.
|
||||
assembler->GotoIf(assembler->WordIsPositiveSmi(len), &return_len);
|
||||
assembler.GotoIf(assembler.WordIsPositiveSmi(len), &return_len);
|
||||
|
||||
// Check if {len} is a (negative) Smi.
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(len), &return_zero);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(len), &return_zero);
|
||||
|
||||
// Check if {len} is a HeapNumber.
|
||||
Label if_lenisheapnumber(assembler),
|
||||
if_lenisnotheapnumber(assembler, Label::kDeferred);
|
||||
assembler->Branch(assembler->IsHeapNumberMap(assembler->LoadMap(len)),
|
||||
&if_lenisheapnumber, &if_lenisnotheapnumber);
|
||||
Label if_lenisheapnumber(&assembler),
|
||||
if_lenisnotheapnumber(&assembler, Label::kDeferred);
|
||||
assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(len)),
|
||||
&if_lenisheapnumber, &if_lenisnotheapnumber);
|
||||
|
||||
assembler->Bind(&if_lenisheapnumber);
|
||||
assembler.Bind(&if_lenisheapnumber);
|
||||
{
|
||||
// Load the floating-point value of {len}.
|
||||
Node* len_value = assembler->LoadHeapNumberValue(len);
|
||||
Node* len_value = assembler.LoadHeapNumberValue(len);
|
||||
|
||||
// Check if {len} is not greater than zero.
|
||||
assembler->GotoUnless(assembler->Float64GreaterThan(
|
||||
len_value, assembler->Float64Constant(0.0)),
|
||||
&return_zero);
|
||||
assembler.GotoUnless(assembler.Float64GreaterThan(
|
||||
len_value, assembler.Float64Constant(0.0)),
|
||||
&return_zero);
|
||||
|
||||
// Check if {len} is greater than or equal to 2^53-1.
|
||||
assembler->GotoIf(
|
||||
assembler->Float64GreaterThanOrEqual(
|
||||
len_value, assembler->Float64Constant(kMaxSafeInteger)),
|
||||
assembler.GotoIf(
|
||||
assembler.Float64GreaterThanOrEqual(
|
||||
len_value, assembler.Float64Constant(kMaxSafeInteger)),
|
||||
&return_two53minus1);
|
||||
|
||||
// Round the {len} towards -Infinity.
|
||||
Node* value = assembler->Float64Floor(len_value);
|
||||
Node* result = assembler->ChangeFloat64ToTagged(value);
|
||||
assembler->Return(result);
|
||||
Node* value = assembler.Float64Floor(len_value);
|
||||
Node* result = assembler.ChangeFloat64ToTagged(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_lenisnotheapnumber);
|
||||
assembler.Bind(&if_lenisnotheapnumber);
|
||||
{
|
||||
// Need to convert {len} to a Number first.
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate());
|
||||
var_len.Bind(assembler->CallStub(callable, context, len));
|
||||
assembler->Goto(&loop);
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
|
||||
var_len.Bind(assembler.CallStub(callable, context, len));
|
||||
assembler.Goto(&loop);
|
||||
}
|
||||
|
||||
assembler->Bind(&return_len);
|
||||
assembler->Return(var_len.value());
|
||||
assembler.Bind(&return_len);
|
||||
assembler.Return(var_len.value());
|
||||
|
||||
assembler->Bind(&return_two53minus1);
|
||||
assembler->Return(assembler->NumberConstant(kMaxSafeInteger));
|
||||
assembler.Bind(&return_two53minus1);
|
||||
assembler.Return(assembler.NumberConstant(kMaxSafeInteger));
|
||||
|
||||
assembler->Bind(&return_zero);
|
||||
assembler->Return(assembler->SmiConstant(Smi::kZero));
|
||||
assembler.Bind(&return_zero);
|
||||
assembler.Return(assembler.SmiConstant(Smi::kZero));
|
||||
}
|
||||
}
|
||||
|
||||
void Builtins::Generate_ToInteger(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToInteger(compiler::CodeAssemblerState* state) {
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
compiler::Node* input = assembler->Parameter(Descriptor::kArgument);
|
||||
compiler::Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
compiler::Node* input = assembler.Parameter(Descriptor::kArgument);
|
||||
compiler::Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->ToInteger(context, input));
|
||||
assembler.Return(assembler.ToInteger(context, input));
|
||||
}
|
||||
|
||||
// ES6 section 7.1.13 ToObject (argument)
|
||||
void Builtins::Generate_ToObject(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ToObject(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
typedef TypeConversionDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Label if_number(assembler, Label::kDeferred), if_notsmi(assembler),
|
||||
if_jsreceiver(assembler), if_noconstructor(assembler, Label::kDeferred),
|
||||
if_wrapjsvalue(assembler);
|
||||
Label if_number(&assembler, Label::kDeferred), if_notsmi(&assembler),
|
||||
if_jsreceiver(&assembler), if_noconstructor(&assembler, Label::kDeferred),
|
||||
if_wrapjsvalue(&assembler);
|
||||
|
||||
Node* object = assembler->Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* object = assembler.Parameter(Descriptor::kArgument);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
Variable constructor_function_index_var(assembler,
|
||||
Variable constructor_function_index_var(&assembler,
|
||||
MachineType::PointerRepresentation());
|
||||
|
||||
assembler->Branch(assembler->TaggedIsSmi(object), &if_number, &if_notsmi);
|
||||
assembler.Branch(assembler.TaggedIsSmi(object), &if_number, &if_notsmi);
|
||||
|
||||
assembler->Bind(&if_notsmi);
|
||||
Node* map = assembler->LoadMap(object);
|
||||
assembler.Bind(&if_notsmi);
|
||||
Node* map = assembler.LoadMap(object);
|
||||
|
||||
assembler->GotoIf(assembler->IsHeapNumberMap(map), &if_number);
|
||||
assembler.GotoIf(assembler.IsHeapNumberMap(map), &if_number);
|
||||
|
||||
Node* instance_type = assembler->LoadMapInstanceType(map);
|
||||
assembler->GotoIf(assembler->IsJSReceiverInstanceType(instance_type),
|
||||
&if_jsreceiver);
|
||||
Node* instance_type = assembler.LoadMapInstanceType(map);
|
||||
assembler.GotoIf(assembler.IsJSReceiverInstanceType(instance_type),
|
||||
&if_jsreceiver);
|
||||
|
||||
Node* constructor_function_index =
|
||||
assembler->LoadMapConstructorFunctionIndex(map);
|
||||
assembler->GotoIf(assembler->WordEqual(constructor_function_index,
|
||||
assembler->IntPtrConstant(
|
||||
Map::kNoConstructorFunctionIndex)),
|
||||
&if_noconstructor);
|
||||
assembler.LoadMapConstructorFunctionIndex(map);
|
||||
assembler.GotoIf(assembler.WordEqual(constructor_function_index,
|
||||
assembler.IntPtrConstant(
|
||||
Map::kNoConstructorFunctionIndex)),
|
||||
&if_noconstructor);
|
||||
constructor_function_index_var.Bind(constructor_function_index);
|
||||
assembler->Goto(&if_wrapjsvalue);
|
||||
assembler.Goto(&if_wrapjsvalue);
|
||||
|
||||
assembler->Bind(&if_number);
|
||||
assembler.Bind(&if_number);
|
||||
constructor_function_index_var.Bind(
|
||||
assembler->IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
|
||||
assembler->Goto(&if_wrapjsvalue);
|
||||
assembler.IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
|
||||
assembler.Goto(&if_wrapjsvalue);
|
||||
|
||||
assembler->Bind(&if_wrapjsvalue);
|
||||
Node* native_context = assembler->LoadNativeContext(context);
|
||||
Node* constructor = assembler->LoadFixedArrayElement(
|
||||
assembler.Bind(&if_wrapjsvalue);
|
||||
Node* native_context = assembler.LoadNativeContext(context);
|
||||
Node* constructor = assembler.LoadFixedArrayElement(
|
||||
native_context, constructor_function_index_var.value(), 0,
|
||||
CodeStubAssembler::INTPTR_PARAMETERS);
|
||||
Node* initial_map = assembler->LoadObjectField(
|
||||
Node* initial_map = assembler.LoadObjectField(
|
||||
constructor, JSFunction::kPrototypeOrInitialMapOffset);
|
||||
Node* js_value = assembler->Allocate(JSValue::kSize);
|
||||
assembler->StoreMapNoWriteBarrier(js_value, initial_map);
|
||||
assembler->StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler->StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler->StoreObjectField(js_value, JSValue::kValueOffset, object);
|
||||
assembler->Return(js_value);
|
||||
Node* js_value = assembler.Allocate(JSValue::kSize);
|
||||
assembler.StoreMapNoWriteBarrier(js_value, initial_map);
|
||||
assembler.StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler.StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler.StoreObjectField(js_value, JSValue::kValueOffset, object);
|
||||
assembler.Return(js_value);
|
||||
|
||||
assembler->Bind(&if_noconstructor);
|
||||
assembler->TailCallRuntime(
|
||||
assembler.Bind(&if_noconstructor);
|
||||
assembler.TailCallRuntime(
|
||||
Runtime::kThrowUndefinedOrNullToObject, context,
|
||||
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
|
||||
"ToObject", TENURED)));
|
||||
assembler.HeapConstant(
|
||||
assembler.factory()->NewStringFromAsciiChecked("ToObject", TENURED)));
|
||||
|
||||
assembler->Bind(&if_jsreceiver);
|
||||
assembler->Return(object);
|
||||
assembler.Bind(&if_jsreceiver);
|
||||
assembler.Return(object);
|
||||
}
|
||||
|
||||
// ES6 section 12.5.5 typeof operator
|
||||
void Builtins::Generate_Typeof(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_Typeof(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef TypeofDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* object = assembler->Parameter(Descriptor::kObject);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* object = assembler.Parameter(Descriptor::kObject);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->Typeof(object, context));
|
||||
assembler.Return(assembler.Typeof(object, context));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -908,9 +908,10 @@ BUILTIN(DatePrototypeToJson) {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
|
||||
int field_index) {
|
||||
namespace {
|
||||
|
||||
void Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
|
||||
int field_index) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
|
||||
@ -965,100 +966,132 @@ void Builtins::Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetDate(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kDay);
|
||||
void Builtins::Generate_DatePrototypeGetDate(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kDay);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetDay(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kWeekday);
|
||||
void Builtins::Generate_DatePrototypeGetDay(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kWeekday);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetFullYear(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kYear);
|
||||
void Builtins::Generate_DatePrototypeGetFullYear(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kYear);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetHours(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kHour);
|
||||
void Builtins::Generate_DatePrototypeGetHours(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kHour);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetMilliseconds(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kMillisecond);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecond);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetMinutes(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kMinute);
|
||||
void Builtins::Generate_DatePrototypeGetMinutes(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kMinute);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetMonth(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kMonth);
|
||||
void Builtins::Generate_DatePrototypeGetMonth(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kMonth);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetSeconds(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kSecond);
|
||||
void Builtins::Generate_DatePrototypeGetSeconds(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kSecond);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetTime(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kDateValue);
|
||||
void Builtins::Generate_DatePrototypeGetTime(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kDateValue);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetTimezoneOffset(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kTimezoneOffset);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kTimezoneOffset);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCDate(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kDayUTC);
|
||||
void Builtins::Generate_DatePrototypeGetUTCDate(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kDayUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCDay(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kWeekdayUTC);
|
||||
void Builtins::Generate_DatePrototypeGetUTCDay(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kWeekdayUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCFullYear(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kYearUTC);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kYearUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCHours(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kHourUTC);
|
||||
void Builtins::Generate_DatePrototypeGetUTCHours(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kHourUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCMilliseconds(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kMillisecondUTC);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecondUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCMinutes(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kMinuteUTC);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kMinuteUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCMonth(CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kMonthUTC);
|
||||
void Builtins::Generate_DatePrototypeGetUTCMonth(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kMonthUTC);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_DatePrototypeGetUTCSeconds(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_DatePrototype_GetField(assembler, JSDate::kSecondUTC);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_DatePrototype_GetField(&assembler, JSDate::kSecondUTC);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -283,14 +283,15 @@ BUILTIN(FunctionPrototypeToString) {
|
||||
|
||||
// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
|
||||
void Builtins::Generate_FunctionPrototypeHasInstance(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* f = assembler->Parameter(0);
|
||||
Node* v = assembler->Parameter(1);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* result = assembler->OrdinaryHasInstance(context, f, v);
|
||||
assembler->Return(result);
|
||||
Node* f = assembler.Parameter(0);
|
||||
Node* v = assembler.Parameter(1);
|
||||
Node* context = assembler.Parameter(4);
|
||||
Node* result = assembler.OrdinaryHasInstance(context, f, v);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -96,20 +96,26 @@ void Generate_GeneratorPrototypeResume(
|
||||
} // anonymous namespace
|
||||
|
||||
// ES6 section 25.3.1.2 Generator.prototype.next ( value )
|
||||
void Builtins::Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler) {
|
||||
Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kNext,
|
||||
void Builtins::Generate_GeneratorPrototypeNext(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kNext,
|
||||
"[Generator].prototype.next");
|
||||
}
|
||||
|
||||
// ES6 section 25.3.1.3 Generator.prototype.return ( value )
|
||||
void Builtins::Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler) {
|
||||
Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kReturn,
|
||||
void Builtins::Generate_GeneratorPrototypeReturn(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kReturn,
|
||||
"[Generator].prototype.return");
|
||||
}
|
||||
|
||||
// ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
|
||||
void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) {
|
||||
Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow,
|
||||
void Builtins::Generate_GeneratorPrototypeThrow(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kThrow,
|
||||
"[Generator].prototype.throw");
|
||||
}
|
||||
|
||||
|
@ -101,111 +101,112 @@ BUILTIN(GlobalEval) {
|
||||
}
|
||||
|
||||
// ES6 section 18.2.2 isFinite ( number )
|
||||
void Builtins::Generate_GlobalIsFinite(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_GlobalIsFinite(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
Label return_true(assembler), return_false(assembler);
|
||||
Label return_true(&assembler), return_false(&assembler);
|
||||
|
||||
// We might need to loop once for ToNumber conversion.
|
||||
Variable var_num(assembler, MachineRepresentation::kTagged);
|
||||
Label loop(assembler, &var_num);
|
||||
var_num.Bind(assembler->Parameter(1));
|
||||
assembler->Goto(&loop);
|
||||
assembler->Bind(&loop);
|
||||
Variable var_num(&assembler, MachineRepresentation::kTagged);
|
||||
Label loop(&assembler, &var_num);
|
||||
var_num.Bind(assembler.Parameter(1));
|
||||
assembler.Goto(&loop);
|
||||
assembler.Bind(&loop);
|
||||
{
|
||||
// Load the current {num} value.
|
||||
Node* num = var_num.value();
|
||||
|
||||
// Check if {num} is a Smi or a HeapObject.
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(num), &return_true);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(num), &return_true);
|
||||
|
||||
// Check if {num} is a HeapNumber.
|
||||
Label if_numisheapnumber(assembler),
|
||||
if_numisnotheapnumber(assembler, Label::kDeferred);
|
||||
assembler->Branch(assembler->WordEqual(assembler->LoadMap(num),
|
||||
assembler->HeapNumberMapConstant()),
|
||||
&if_numisheapnumber, &if_numisnotheapnumber);
|
||||
Label if_numisheapnumber(&assembler),
|
||||
if_numisnotheapnumber(&assembler, Label::kDeferred);
|
||||
assembler.Branch(assembler.WordEqual(assembler.LoadMap(num),
|
||||
assembler.HeapNumberMapConstant()),
|
||||
&if_numisheapnumber, &if_numisnotheapnumber);
|
||||
|
||||
assembler->Bind(&if_numisheapnumber);
|
||||
assembler.Bind(&if_numisheapnumber);
|
||||
{
|
||||
// Check if {num} contains a finite, non-NaN value.
|
||||
Node* num_value = assembler->LoadHeapNumberValue(num);
|
||||
assembler->BranchIfFloat64IsNaN(
|
||||
assembler->Float64Sub(num_value, num_value), &return_false,
|
||||
&return_true);
|
||||
Node* num_value = assembler.LoadHeapNumberValue(num);
|
||||
assembler.BranchIfFloat64IsNaN(assembler.Float64Sub(num_value, num_value),
|
||||
&return_false, &return_true);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_numisnotheapnumber);
|
||||
assembler.Bind(&if_numisnotheapnumber);
|
||||
{
|
||||
// Need to convert {num} to a Number first.
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate());
|
||||
var_num.Bind(assembler->CallStub(callable, context, num));
|
||||
assembler->Goto(&loop);
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
|
||||
var_num.Bind(assembler.CallStub(callable, context, num));
|
||||
assembler.Goto(&loop);
|
||||
}
|
||||
}
|
||||
|
||||
assembler->Bind(&return_true);
|
||||
assembler->Return(assembler->BooleanConstant(true));
|
||||
assembler.Bind(&return_true);
|
||||
assembler.Return(assembler.BooleanConstant(true));
|
||||
|
||||
assembler->Bind(&return_false);
|
||||
assembler->Return(assembler->BooleanConstant(false));
|
||||
assembler.Bind(&return_false);
|
||||
assembler.Return(assembler.BooleanConstant(false));
|
||||
}
|
||||
|
||||
// ES6 section 18.2.3 isNaN ( number )
|
||||
void Builtins::Generate_GlobalIsNaN(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_GlobalIsNaN(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
Label return_true(assembler), return_false(assembler);
|
||||
Label return_true(&assembler), return_false(&assembler);
|
||||
|
||||
// We might need to loop once for ToNumber conversion.
|
||||
Variable var_num(assembler, MachineRepresentation::kTagged);
|
||||
Label loop(assembler, &var_num);
|
||||
var_num.Bind(assembler->Parameter(1));
|
||||
assembler->Goto(&loop);
|
||||
assembler->Bind(&loop);
|
||||
Variable var_num(&assembler, MachineRepresentation::kTagged);
|
||||
Label loop(&assembler, &var_num);
|
||||
var_num.Bind(assembler.Parameter(1));
|
||||
assembler.Goto(&loop);
|
||||
assembler.Bind(&loop);
|
||||
{
|
||||
// Load the current {num} value.
|
||||
Node* num = var_num.value();
|
||||
|
||||
// Check if {num} is a Smi or a HeapObject.
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(num), &return_false);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(num), &return_false);
|
||||
|
||||
// Check if {num} is a HeapNumber.
|
||||
Label if_numisheapnumber(assembler),
|
||||
if_numisnotheapnumber(assembler, Label::kDeferred);
|
||||
assembler->Branch(assembler->WordEqual(assembler->LoadMap(num),
|
||||
assembler->HeapNumberMapConstant()),
|
||||
&if_numisheapnumber, &if_numisnotheapnumber);
|
||||
Label if_numisheapnumber(&assembler),
|
||||
if_numisnotheapnumber(&assembler, Label::kDeferred);
|
||||
assembler.Branch(assembler.WordEqual(assembler.LoadMap(num),
|
||||
assembler.HeapNumberMapConstant()),
|
||||
&if_numisheapnumber, &if_numisnotheapnumber);
|
||||
|
||||
assembler->Bind(&if_numisheapnumber);
|
||||
assembler.Bind(&if_numisheapnumber);
|
||||
{
|
||||
// Check if {num} contains a NaN.
|
||||
Node* num_value = assembler->LoadHeapNumberValue(num);
|
||||
assembler->BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
|
||||
Node* num_value = assembler.LoadHeapNumberValue(num);
|
||||
assembler.BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_numisnotheapnumber);
|
||||
assembler.Bind(&if_numisnotheapnumber);
|
||||
{
|
||||
// Need to convert {num} to a Number first.
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate());
|
||||
var_num.Bind(assembler->CallStub(callable, context, num));
|
||||
assembler->Goto(&loop);
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
|
||||
var_num.Bind(assembler.CallStub(callable, context, num));
|
||||
assembler.Goto(&loop);
|
||||
}
|
||||
}
|
||||
|
||||
assembler->Bind(&return_true);
|
||||
assembler->Return(assembler->BooleanConstant(true));
|
||||
assembler.Bind(&return_true);
|
||||
assembler.Return(assembler.BooleanConstant(true));
|
||||
|
||||
assembler->Bind(&return_false);
|
||||
assembler->Return(assembler->BooleanConstant(false));
|
||||
assembler.Bind(&return_false);
|
||||
assembler.Return(assembler.BooleanConstant(false));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -12,18 +12,19 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void Builtins::Generate_KeyedLoadIC_Megamorphic_TF(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef LoadWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler->Parameter(Descriptor::kName);
|
||||
Node* slot = assembler->Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler->Parameter(Descriptor::kVector);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler.Parameter(Descriptor::kName);
|
||||
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
CodeStubAssembler::LoadICParameters p(context, receiver, name, slot, vector);
|
||||
assembler->KeyedLoadICGeneric(&p);
|
||||
assembler.KeyedLoadICGeneric(&p);
|
||||
}
|
||||
|
||||
void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
|
||||
@ -41,30 +42,14 @@ void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
|
||||
KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
|
||||
}
|
||||
|
||||
void KeyedStoreICMegamorphic(CodeStubAssembler* assembler, LanguageMode mode) {
|
||||
typedef compiler::Node Node;
|
||||
typedef StoreWithVectorDescriptor Descriptor;
|
||||
|
||||
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler->Parameter(Descriptor::kName);
|
||||
Node* value = assembler->Parameter(Descriptor::kValue);
|
||||
Node* slot = assembler->Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler->Parameter(Descriptor::kVector);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
|
||||
CodeStubAssembler::StoreICParameters p(context, receiver, name, value, slot,
|
||||
vector);
|
||||
KeyedStoreGenericGenerator::Generate(assembler, &p, mode);
|
||||
}
|
||||
|
||||
void Builtins::Generate_KeyedStoreIC_Megamorphic_TF(
|
||||
CodeStubAssembler* assembler) {
|
||||
KeyedStoreICMegamorphic(assembler, SLOPPY);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
KeyedStoreGenericGenerator::Generate(state, SLOPPY);
|
||||
}
|
||||
|
||||
void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict_TF(
|
||||
CodeStubAssembler* assembler) {
|
||||
KeyedStoreICMegamorphic(assembler, STRICT);
|
||||
compiler::CodeAssemblerState* state) {
|
||||
KeyedStoreGenericGenerator::Generate(state, STRICT);
|
||||
}
|
||||
|
||||
void Builtins::Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
|
||||
@ -75,76 +60,79 @@ void Builtins::Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
|
||||
KeyedStoreIC::GenerateSlow(masm);
|
||||
}
|
||||
|
||||
void Builtins::Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_LoadGlobalIC_Miss(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef LoadGlobalWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* slot = assembler->Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler->Parameter(Descriptor::kVector);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot,
|
||||
vector);
|
||||
assembler.TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot, vector);
|
||||
}
|
||||
|
||||
void Builtins::Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_LoadGlobalIC_Slow(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef LoadGlobalWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* slot = assembler->Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler->Parameter(Descriptor::kVector);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot,
|
||||
vector);
|
||||
assembler.TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot, vector);
|
||||
}
|
||||
|
||||
void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
|
||||
NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
|
||||
}
|
||||
|
||||
void Builtins::Generate_LoadIC_Miss(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_LoadIC_Miss(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef LoadWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler->Parameter(Descriptor::kName);
|
||||
Node* slot = assembler->Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler->Parameter(Descriptor::kVector);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler.Parameter(Descriptor::kName);
|
||||
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
|
||||
slot, vector);
|
||||
assembler.TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
|
||||
slot, vector);
|
||||
}
|
||||
|
||||
void Builtins::Generate_LoadIC_Normal(MacroAssembler* masm) {
|
||||
LoadIC::GenerateNormal(masm);
|
||||
}
|
||||
|
||||
void Builtins::Generate_LoadIC_Slow(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_LoadIC_Slow(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef LoadWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler->Parameter(Descriptor::kName);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler.Parameter(Descriptor::kName);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
|
||||
assembler.TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
|
||||
}
|
||||
|
||||
void Builtins::Generate_StoreIC_Miss(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StoreIC_Miss(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef StoreWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler->Parameter(Descriptor::kName);
|
||||
Node* value = assembler->Parameter(Descriptor::kValue);
|
||||
Node* slot = assembler->Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler->Parameter(Descriptor::kVector);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler.Parameter(Descriptor::kName);
|
||||
Node* value = assembler.Parameter(Descriptor::kValue);
|
||||
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot,
|
||||
vector, receiver, name);
|
||||
assembler.TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot,
|
||||
vector, receiver, name);
|
||||
}
|
||||
|
||||
void Builtins::Generate_StoreIC_Normal(MacroAssembler* masm) {
|
||||
@ -156,30 +144,33 @@ void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
|
||||
}
|
||||
|
||||
namespace {
|
||||
void Generate_StoreIC_Slow(CodeStubAssembler* assembler,
|
||||
void Generate_StoreIC_Slow(compiler::CodeAssemblerState* state,
|
||||
LanguageMode language_mode) {
|
||||
typedef compiler::Node Node;
|
||||
typedef StoreWithVectorDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler->Parameter(Descriptor::kName);
|
||||
Node* value = assembler->Parameter(Descriptor::kValue);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* lang_mode = assembler->SmiConstant(Smi::FromInt(language_mode));
|
||||
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler.Parameter(Descriptor::kName);
|
||||
Node* value = assembler.Parameter(Descriptor::kValue);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
Node* lang_mode = assembler.SmiConstant(Smi::FromInt(language_mode));
|
||||
|
||||
// The slow case calls into the runtime to complete the store without causing
|
||||
// an IC miss that would otherwise cause a transition to the generic stub.
|
||||
assembler->TailCallRuntime(Runtime::kSetProperty, context, receiver, name,
|
||||
value, lang_mode);
|
||||
assembler.TailCallRuntime(Runtime::kSetProperty, context, receiver, name,
|
||||
value, lang_mode);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
void Builtins::Generate_StoreIC_SlowSloppy(CodeStubAssembler* assembler) {
|
||||
Generate_StoreIC_Slow(assembler, SLOPPY);
|
||||
void Builtins::Generate_StoreIC_SlowSloppy(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_StoreIC_Slow(state, SLOPPY);
|
||||
}
|
||||
|
||||
void Builtins::Generate_StoreIC_SlowStrict(CodeStubAssembler* assembler) {
|
||||
Generate_StoreIC_Slow(assembler, STRICT);
|
||||
void Builtins::Generate_StoreIC_SlowStrict(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_StoreIC_Slow(state, STRICT);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -54,86 +54,90 @@ void Builtins::Generate_StackCheck(MacroAssembler* masm) {
|
||||
// TurboFan support builtins.
|
||||
|
||||
void Builtins::Generate_CopyFastSmiOrObjectElements(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CopyFastSmiOrObjectElementsDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* object = assembler->Parameter(Descriptor::kObject);
|
||||
Node* object = assembler.Parameter(Descriptor::kObject);
|
||||
|
||||
// Load the {object}s elements.
|
||||
Node* source = assembler->LoadObjectField(object, JSObject::kElementsOffset);
|
||||
Node* source = assembler.LoadObjectField(object, JSObject::kElementsOffset);
|
||||
|
||||
CodeStubAssembler::ParameterMode mode = assembler->OptimalParameterMode();
|
||||
Node* length = assembler->UntagParameter(
|
||||
assembler->LoadFixedArrayBaseLength(source), mode);
|
||||
CodeStubAssembler::ParameterMode mode = assembler.OptimalParameterMode();
|
||||
Node* length = assembler.UntagParameter(
|
||||
assembler.LoadFixedArrayBaseLength(source), mode);
|
||||
|
||||
// Check if we can allocate in new space.
|
||||
ElementsKind kind = FAST_ELEMENTS;
|
||||
int max_elements = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
|
||||
Label if_newspace(assembler), if_oldspace(assembler);
|
||||
assembler->Branch(
|
||||
assembler->UintPtrLessThan(
|
||||
length, assembler->IntPtrOrSmiConstant(max_elements, mode)),
|
||||
Label if_newspace(&assembler), if_oldspace(&assembler);
|
||||
assembler.Branch(
|
||||
assembler.UintPtrLessThan(
|
||||
length, assembler.IntPtrOrSmiConstant(max_elements, mode)),
|
||||
&if_newspace, &if_oldspace);
|
||||
|
||||
assembler->Bind(&if_newspace);
|
||||
assembler.Bind(&if_newspace);
|
||||
{
|
||||
Node* target = assembler->AllocateFixedArray(kind, length, mode);
|
||||
assembler->CopyFixedArrayElements(kind, source, target, length,
|
||||
SKIP_WRITE_BARRIER, mode);
|
||||
assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
|
||||
assembler->Return(target);
|
||||
Node* target = assembler.AllocateFixedArray(kind, length, mode);
|
||||
assembler.CopyFixedArrayElements(kind, source, target, length,
|
||||
SKIP_WRITE_BARRIER, mode);
|
||||
assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
|
||||
assembler.Return(target);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_oldspace);
|
||||
assembler.Bind(&if_oldspace);
|
||||
{
|
||||
Node* target = assembler->AllocateFixedArray(
|
||||
kind, length, mode, CodeStubAssembler::kPretenured);
|
||||
assembler->CopyFixedArrayElements(kind, source, target, length,
|
||||
UPDATE_WRITE_BARRIER, mode);
|
||||
assembler->StoreObjectField(object, JSObject::kElementsOffset, target);
|
||||
assembler->Return(target);
|
||||
Node* target = assembler.AllocateFixedArray(kind, length, mode,
|
||||
CodeStubAssembler::kPretenured);
|
||||
assembler.CopyFixedArrayElements(kind, source, target, length,
|
||||
UPDATE_WRITE_BARRIER, mode);
|
||||
assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
|
||||
assembler.Return(target);
|
||||
}
|
||||
}
|
||||
|
||||
void Builtins::Generate_GrowFastDoubleElements(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_GrowFastDoubleElements(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef GrowArrayElementsDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* object = assembler->Parameter(Descriptor::kObject);
|
||||
Node* key = assembler->Parameter(Descriptor::kKey);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* object = assembler.Parameter(Descriptor::kObject);
|
||||
Node* key = assembler.Parameter(Descriptor::kKey);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
Label runtime(assembler, CodeStubAssembler::Label::kDeferred);
|
||||
Node* elements = assembler->LoadElements(object);
|
||||
elements = assembler->TryGrowElementsCapacity(
|
||||
Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
|
||||
Node* elements = assembler.LoadElements(object);
|
||||
elements = assembler.TryGrowElementsCapacity(
|
||||
object, elements, FAST_DOUBLE_ELEMENTS, key, &runtime);
|
||||
assembler->Return(elements);
|
||||
assembler.Return(elements);
|
||||
|
||||
assembler->Bind(&runtime);
|
||||
assembler->TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
|
||||
assembler.Bind(&runtime);
|
||||
assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
|
||||
}
|
||||
|
||||
void Builtins::Generate_GrowFastSmiOrObjectElements(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef GrowArrayElementsDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* object = assembler->Parameter(Descriptor::kObject);
|
||||
Node* key = assembler->Parameter(Descriptor::kKey);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* object = assembler.Parameter(Descriptor::kObject);
|
||||
Node* key = assembler.Parameter(Descriptor::kKey);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
Label runtime(assembler, CodeStubAssembler::Label::kDeferred);
|
||||
Node* elements = assembler->LoadElements(object);
|
||||
elements = assembler->TryGrowElementsCapacity(object, elements, FAST_ELEMENTS,
|
||||
key, &runtime);
|
||||
assembler->Return(elements);
|
||||
Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
|
||||
Node* elements = assembler.LoadElements(object);
|
||||
elements = assembler.TryGrowElementsCapacity(object, elements, FAST_ELEMENTS,
|
||||
key, &runtime);
|
||||
assembler.Return(elements);
|
||||
|
||||
assembler->Bind(&runtime);
|
||||
assembler->TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
|
||||
assembler.Bind(&runtime);
|
||||
assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -10,8 +10,9 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
void Builtins::Generate_IteratorPrototypeIterator(
|
||||
CodeStubAssembler* assembler) {
|
||||
assembler->Return(assembler->Parameter(0));
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
assembler.Return(assembler.Parameter(0));
|
||||
}
|
||||
|
||||
BUILTIN(ModuleNamespaceIterator) {
|
||||
|
@ -14,92 +14,91 @@ namespace internal {
|
||||
// ES6 section 20.2.2 Function Properties of the Math Object
|
||||
|
||||
// ES6 section - 20.2.2.1 Math.abs ( x )
|
||||
void Builtins::Generate_MathAbs(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathAbs(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
// We might need to loop once for ToNumber conversion.
|
||||
Variable var_x(assembler, MachineRepresentation::kTagged);
|
||||
Label loop(assembler, &var_x);
|
||||
var_x.Bind(assembler->Parameter(1));
|
||||
assembler->Goto(&loop);
|
||||
assembler->Bind(&loop);
|
||||
Variable var_x(&assembler, MachineRepresentation::kTagged);
|
||||
Label loop(&assembler, &var_x);
|
||||
var_x.Bind(assembler.Parameter(1));
|
||||
assembler.Goto(&loop);
|
||||
assembler.Bind(&loop);
|
||||
{
|
||||
// Load the current {x} value.
|
||||
Node* x = var_x.value();
|
||||
|
||||
// Check if {x} is a Smi or a HeapObject.
|
||||
Label if_xissmi(assembler), if_xisnotsmi(assembler);
|
||||
assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
|
||||
Label if_xissmi(&assembler), if_xisnotsmi(&assembler);
|
||||
assembler.Branch(assembler.TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
|
||||
|
||||
assembler->Bind(&if_xissmi);
|
||||
assembler.Bind(&if_xissmi);
|
||||
{
|
||||
// Check if {x} is already positive.
|
||||
Label if_xispositive(assembler), if_xisnotpositive(assembler);
|
||||
assembler->BranchIfSmiLessThanOrEqual(
|
||||
assembler->SmiConstant(Smi::FromInt(0)), x, &if_xispositive,
|
||||
Label if_xispositive(&assembler), if_xisnotpositive(&assembler);
|
||||
assembler.BranchIfSmiLessThanOrEqual(
|
||||
assembler.SmiConstant(Smi::FromInt(0)), x, &if_xispositive,
|
||||
&if_xisnotpositive);
|
||||
|
||||
assembler->Bind(&if_xispositive);
|
||||
assembler.Bind(&if_xispositive);
|
||||
{
|
||||
// Just return the input {x}.
|
||||
assembler->Return(x);
|
||||
assembler.Return(x);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_xisnotpositive);
|
||||
assembler.Bind(&if_xisnotpositive);
|
||||
{
|
||||
// Try to negate the {x} value.
|
||||
Node* pair = assembler->IntPtrSubWithOverflow(
|
||||
assembler->IntPtrConstant(0), assembler->BitcastTaggedToWord(x));
|
||||
Node* overflow = assembler->Projection(1, pair);
|
||||
Label if_overflow(assembler, Label::kDeferred),
|
||||
if_notoverflow(assembler);
|
||||
assembler->Branch(overflow, &if_overflow, &if_notoverflow);
|
||||
Node* pair = assembler.IntPtrSubWithOverflow(
|
||||
assembler.IntPtrConstant(0), assembler.BitcastTaggedToWord(x));
|
||||
Node* overflow = assembler.Projection(1, pair);
|
||||
Label if_overflow(&assembler, Label::kDeferred),
|
||||
if_notoverflow(&assembler);
|
||||
assembler.Branch(overflow, &if_overflow, &if_notoverflow);
|
||||
|
||||
assembler->Bind(&if_notoverflow);
|
||||
assembler.Bind(&if_notoverflow);
|
||||
{
|
||||
// There is a Smi representation for negated {x}.
|
||||
Node* result = assembler->Projection(0, pair);
|
||||
result = assembler->BitcastWordToTagged(result);
|
||||
assembler->Return(result);
|
||||
Node* result = assembler.Projection(0, pair);
|
||||
result = assembler.BitcastWordToTagged(result);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_overflow);
|
||||
assembler.Bind(&if_overflow);
|
||||
{
|
||||
Node* result = assembler->NumberConstant(0.0 - Smi::kMinValue);
|
||||
assembler->Return(result);
|
||||
Node* result = assembler.NumberConstant(0.0 - Smi::kMinValue);
|
||||
assembler.Return(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assembler->Bind(&if_xisnotsmi);
|
||||
assembler.Bind(&if_xisnotsmi);
|
||||
{
|
||||
// Check if {x} is a HeapNumber.
|
||||
Label if_xisheapnumber(assembler),
|
||||
if_xisnotheapnumber(assembler, Label::kDeferred);
|
||||
assembler->Branch(
|
||||
assembler->WordEqual(assembler->LoadMap(x),
|
||||
assembler->HeapNumberMapConstant()),
|
||||
&if_xisheapnumber, &if_xisnotheapnumber);
|
||||
Label if_xisheapnumber(&assembler),
|
||||
if_xisnotheapnumber(&assembler, Label::kDeferred);
|
||||
assembler.Branch(assembler.WordEqual(assembler.LoadMap(x),
|
||||
assembler.HeapNumberMapConstant()),
|
||||
&if_xisheapnumber, &if_xisnotheapnumber);
|
||||
|
||||
assembler->Bind(&if_xisheapnumber);
|
||||
assembler.Bind(&if_xisheapnumber);
|
||||
{
|
||||
Node* x_value = assembler->LoadHeapNumberValue(x);
|
||||
Node* value = assembler->Float64Abs(x_value);
|
||||
Node* result = assembler->AllocateHeapNumberWithValue(value);
|
||||
assembler->Return(result);
|
||||
Node* x_value = assembler.LoadHeapNumberValue(x);
|
||||
Node* value = assembler.Float64Abs(x_value);
|
||||
Node* result = assembler.AllocateHeapNumberWithValue(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_xisnotheapnumber);
|
||||
assembler.Bind(&if_xisnotheapnumber);
|
||||
{
|
||||
// Need to convert {x} to a Number first.
|
||||
Callable callable =
|
||||
CodeFactory::NonNumberToNumber(assembler->isolate());
|
||||
var_x.Bind(assembler->CallStub(callable, context, x));
|
||||
assembler->Goto(&loop);
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
|
||||
var_x.Bind(assembler.CallStub(callable, context, x));
|
||||
assembler.Goto(&loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -182,163 +181,177 @@ void Generate_MathUnaryOperation(
|
||||
} // namespace
|
||||
|
||||
// ES6 section 20.2.2.2 Math.acos ( x )
|
||||
void Builtins::Generate_MathAcos(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Acos);
|
||||
void Builtins::Generate_MathAcos(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Acos);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.3 Math.acosh ( x )
|
||||
void Builtins::Generate_MathAcosh(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Acosh);
|
||||
void Builtins::Generate_MathAcosh(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Acosh);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.4 Math.asin ( x )
|
||||
void Builtins::Generate_MathAsin(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Asin);
|
||||
void Builtins::Generate_MathAsin(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Asin);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.5 Math.asinh ( x )
|
||||
void Builtins::Generate_MathAsinh(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Asinh);
|
||||
void Builtins::Generate_MathAsinh(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Asinh);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.6 Math.atan ( x )
|
||||
void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Atan);
|
||||
void Builtins::Generate_MathAtan(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Atan);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.7 Math.atanh ( x )
|
||||
void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Atanh);
|
||||
void Builtins::Generate_MathAtanh(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Atanh);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.8 Math.atan2 ( y, x )
|
||||
void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathAtan2(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* y = assembler->Parameter(1);
|
||||
Node* x = assembler->Parameter(2);
|
||||
Node* context = assembler->Parameter(5);
|
||||
Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
|
||||
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
|
||||
Node* value = assembler->Float64Atan2(y_value, x_value);
|
||||
Node* result = assembler->AllocateHeapNumberWithValue(value);
|
||||
assembler->Return(result);
|
||||
Node* y = assembler.Parameter(1);
|
||||
Node* x = assembler.Parameter(2);
|
||||
Node* context = assembler.Parameter(5);
|
||||
Node* y_value = assembler.TruncateTaggedToFloat64(context, y);
|
||||
Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
|
||||
Node* value = assembler.Float64Atan2(y_value, x_value);
|
||||
Node* result = assembler.AllocateHeapNumberWithValue(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.10 Math.ceil ( x )
|
||||
void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
|
||||
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
|
||||
void Builtins::Generate_MathCeil(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Ceil);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.9 Math.cbrt ( x )
|
||||
void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cbrt);
|
||||
void Builtins::Generate_MathCbrt(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Cbrt);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.11 Math.clz32 ( x )
|
||||
void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathClz32(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
// Shared entry point for the clz32 operation.
|
||||
Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
|
||||
Label do_clz32(assembler);
|
||||
Variable var_clz32_x(&assembler, MachineRepresentation::kWord32);
|
||||
Label do_clz32(&assembler);
|
||||
|
||||
// We might need to loop once for ToNumber conversion.
|
||||
Variable var_x(assembler, MachineRepresentation::kTagged);
|
||||
Label loop(assembler, &var_x);
|
||||
var_x.Bind(assembler->Parameter(1));
|
||||
assembler->Goto(&loop);
|
||||
assembler->Bind(&loop);
|
||||
Variable var_x(&assembler, MachineRepresentation::kTagged);
|
||||
Label loop(&assembler, &var_x);
|
||||
var_x.Bind(assembler.Parameter(1));
|
||||
assembler.Goto(&loop);
|
||||
assembler.Bind(&loop);
|
||||
{
|
||||
// Load the current {x} value.
|
||||
Node* x = var_x.value();
|
||||
|
||||
// Check if {x} is a Smi or a HeapObject.
|
||||
Label if_xissmi(assembler), if_xisnotsmi(assembler);
|
||||
assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
|
||||
Label if_xissmi(&assembler), if_xisnotsmi(&assembler);
|
||||
assembler.Branch(assembler.TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
|
||||
|
||||
assembler->Bind(&if_xissmi);
|
||||
assembler.Bind(&if_xissmi);
|
||||
{
|
||||
var_clz32_x.Bind(assembler->SmiToWord32(x));
|
||||
assembler->Goto(&do_clz32);
|
||||
var_clz32_x.Bind(assembler.SmiToWord32(x));
|
||||
assembler.Goto(&do_clz32);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_xisnotsmi);
|
||||
assembler.Bind(&if_xisnotsmi);
|
||||
{
|
||||
// Check if {x} is a HeapNumber.
|
||||
Label if_xisheapnumber(assembler),
|
||||
if_xisnotheapnumber(assembler, Label::kDeferred);
|
||||
assembler->Branch(
|
||||
assembler->WordEqual(assembler->LoadMap(x),
|
||||
assembler->HeapNumberMapConstant()),
|
||||
&if_xisheapnumber, &if_xisnotheapnumber);
|
||||
Label if_xisheapnumber(&assembler),
|
||||
if_xisnotheapnumber(&assembler, Label::kDeferred);
|
||||
assembler.Branch(assembler.WordEqual(assembler.LoadMap(x),
|
||||
assembler.HeapNumberMapConstant()),
|
||||
&if_xisheapnumber, &if_xisnotheapnumber);
|
||||
|
||||
assembler->Bind(&if_xisheapnumber);
|
||||
assembler.Bind(&if_xisheapnumber);
|
||||
{
|
||||
var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
|
||||
assembler->Goto(&do_clz32);
|
||||
var_clz32_x.Bind(assembler.TruncateHeapNumberValueToWord32(x));
|
||||
assembler.Goto(&do_clz32);
|
||||
}
|
||||
|
||||
assembler->Bind(&if_xisnotheapnumber);
|
||||
assembler.Bind(&if_xisnotheapnumber);
|
||||
{
|
||||
// Need to convert {x} to a Number first.
|
||||
Callable callable =
|
||||
CodeFactory::NonNumberToNumber(assembler->isolate());
|
||||
var_x.Bind(assembler->CallStub(callable, context, x));
|
||||
assembler->Goto(&loop);
|
||||
Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
|
||||
var_x.Bind(assembler.CallStub(callable, context, x));
|
||||
assembler.Goto(&loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assembler->Bind(&do_clz32);
|
||||
assembler.Bind(&do_clz32);
|
||||
{
|
||||
Node* x_value = var_clz32_x.value();
|
||||
Node* value = assembler->Word32Clz(x_value);
|
||||
Node* result = assembler->ChangeInt32ToTagged(value);
|
||||
assembler->Return(result);
|
||||
Node* value = assembler.Word32Clz(x_value);
|
||||
Node* result = assembler.ChangeInt32ToTagged(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.12 Math.cos ( x )
|
||||
void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cos);
|
||||
void Builtins::Generate_MathCos(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Cos);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.13 Math.cosh ( x )
|
||||
void Builtins::Generate_MathCosh(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cosh);
|
||||
void Builtins::Generate_MathCosh(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Cosh);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.14 Math.exp ( x )
|
||||
void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Exp);
|
||||
void Builtins::Generate_MathExp(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Exp);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.15 Math.expm1 ( x )
|
||||
void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Expm1);
|
||||
void Builtins::Generate_MathExpm1(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Expm1);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.16 Math.floor ( x )
|
||||
void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
|
||||
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
|
||||
void Builtins::Generate_MathFloor(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Floor);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.17 Math.fround ( x )
|
||||
void Builtins::Generate_MathFround(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathFround(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* x = assembler->Parameter(1);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
|
||||
Node* value32 = assembler->TruncateFloat64ToFloat32(x_value);
|
||||
Node* value = assembler->ChangeFloat32ToFloat64(value32);
|
||||
Node* result = assembler->AllocateHeapNumberWithValue(value);
|
||||
assembler->Return(result);
|
||||
Node* x = assembler.Parameter(1);
|
||||
Node* context = assembler.Parameter(4);
|
||||
Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
|
||||
Node* value32 = assembler.TruncateFloat64ToFloat32(x_value);
|
||||
Node* value = assembler.ChangeFloat32ToFloat64(value32);
|
||||
Node* result = assembler.AllocateHeapNumberWithValue(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values )
|
||||
@ -394,153 +407,168 @@ BUILTIN(MathHypot) {
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.19 Math.imul ( x, y )
|
||||
void Builtins::Generate_MathImul(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathImul(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* x = assembler->Parameter(1);
|
||||
Node* y = assembler->Parameter(2);
|
||||
Node* context = assembler->Parameter(5);
|
||||
Node* x_value = assembler->TruncateTaggedToWord32(context, x);
|
||||
Node* y_value = assembler->TruncateTaggedToWord32(context, y);
|
||||
Node* value = assembler->Int32Mul(x_value, y_value);
|
||||
Node* result = assembler->ChangeInt32ToTagged(value);
|
||||
assembler->Return(result);
|
||||
Node* x = assembler.Parameter(1);
|
||||
Node* y = assembler.Parameter(2);
|
||||
Node* context = assembler.Parameter(5);
|
||||
Node* x_value = assembler.TruncateTaggedToWord32(context, x);
|
||||
Node* y_value = assembler.TruncateTaggedToWord32(context, y);
|
||||
Node* value = assembler.Int32Mul(x_value, y_value);
|
||||
Node* result = assembler.ChangeInt32ToTagged(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.20 Math.log ( x )
|
||||
void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log);
|
||||
void Builtins::Generate_MathLog(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.21 Math.log1p ( x )
|
||||
void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log1p);
|
||||
void Builtins::Generate_MathLog1p(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log1p);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.22 Math.log10 ( x )
|
||||
void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log10);
|
||||
void Builtins::Generate_MathLog10(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log10);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.23 Math.log2 ( x )
|
||||
void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log2);
|
||||
void Builtins::Generate_MathLog2(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log2);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.26 Math.pow ( x, y )
|
||||
void Builtins::Generate_MathPow(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathPow(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* x = assembler->Parameter(1);
|
||||
Node* y = assembler->Parameter(2);
|
||||
Node* context = assembler->Parameter(5);
|
||||
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
|
||||
Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
|
||||
Node* value = assembler->Float64Pow(x_value, y_value);
|
||||
Node* result = assembler->ChangeFloat64ToTagged(value);
|
||||
assembler->Return(result);
|
||||
Node* x = assembler.Parameter(1);
|
||||
Node* y = assembler.Parameter(2);
|
||||
Node* context = assembler.Parameter(5);
|
||||
Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
|
||||
Node* y_value = assembler.TruncateTaggedToFloat64(context, y);
|
||||
Node* value = assembler.Float64Pow(x_value, y_value);
|
||||
Node* result = assembler.ChangeFloat64ToTagged(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.27 Math.random ( )
|
||||
void Builtins::Generate_MathRandom(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathRandom(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* native_context = assembler->LoadNativeContext(context);
|
||||
Node* context = assembler.Parameter(3);
|
||||
Node* native_context = assembler.LoadNativeContext(context);
|
||||
|
||||
// Load cache index.
|
||||
CodeStubAssembler::Variable smi_index(assembler,
|
||||
CodeStubAssembler::Variable smi_index(&assembler,
|
||||
MachineRepresentation::kTagged);
|
||||
smi_index.Bind(assembler->LoadContextElement(
|
||||
smi_index.Bind(assembler.LoadContextElement(
|
||||
native_context, Context::MATH_RANDOM_INDEX_INDEX));
|
||||
|
||||
// Cached random numbers are exhausted if index is 0. Go to slow path.
|
||||
CodeStubAssembler::Label if_cached(assembler);
|
||||
assembler->GotoIf(assembler->SmiAbove(smi_index.value(),
|
||||
assembler->SmiConstant(Smi::kZero)),
|
||||
&if_cached);
|
||||
CodeStubAssembler::Label if_cached(&assembler);
|
||||
assembler.GotoIf(
|
||||
assembler.SmiAbove(smi_index.value(), assembler.SmiConstant(Smi::kZero)),
|
||||
&if_cached);
|
||||
|
||||
// Cache exhausted, populate the cache. Return value is the new index.
|
||||
smi_index.Bind(
|
||||
assembler->CallRuntime(Runtime::kGenerateRandomNumbers, context));
|
||||
assembler->Goto(&if_cached);
|
||||
assembler.CallRuntime(Runtime::kGenerateRandomNumbers, context));
|
||||
assembler.Goto(&if_cached);
|
||||
|
||||
// Compute next index by decrement.
|
||||
assembler->Bind(&if_cached);
|
||||
Node* new_smi_index = assembler->SmiSub(
|
||||
smi_index.value(), assembler->SmiConstant(Smi::FromInt(1)));
|
||||
assembler->StoreContextElement(
|
||||
assembler.Bind(&if_cached);
|
||||
Node* new_smi_index = assembler.SmiSub(
|
||||
smi_index.value(), assembler.SmiConstant(Smi::FromInt(1)));
|
||||
assembler.StoreContextElement(
|
||||
native_context, Context::MATH_RANDOM_INDEX_INDEX, new_smi_index);
|
||||
|
||||
// Load and return next cached random number.
|
||||
Node* array = assembler->LoadContextElement(native_context,
|
||||
Context::MATH_RANDOM_CACHE_INDEX);
|
||||
Node* random = assembler->LoadFixedDoubleArrayElement(
|
||||
Node* array = assembler.LoadContextElement(native_context,
|
||||
Context::MATH_RANDOM_CACHE_INDEX);
|
||||
Node* random = assembler.LoadFixedDoubleArrayElement(
|
||||
array, new_smi_index, MachineType::Float64(), 0,
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
assembler->Return(assembler->AllocateHeapNumberWithValue(random));
|
||||
assembler.Return(assembler.AllocateHeapNumberWithValue(random));
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.28 Math.round ( x )
|
||||
void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
|
||||
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
|
||||
void Builtins::Generate_MathRound(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Round);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.29 Math.sign ( x )
|
||||
void Builtins::Generate_MathSign(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_MathSign(compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
using compiler::Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
// Convert the {x} value to a Number.
|
||||
Node* x = assembler->Parameter(1);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
|
||||
Node* x = assembler.Parameter(1);
|
||||
Node* context = assembler.Parameter(4);
|
||||
Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
|
||||
|
||||
// Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself.
|
||||
Label if_xisnegative(assembler), if_xispositive(assembler);
|
||||
assembler->GotoIf(
|
||||
assembler->Float64LessThan(x_value, assembler->Float64Constant(0.0)),
|
||||
Label if_xisnegative(&assembler), if_xispositive(&assembler);
|
||||
assembler.GotoIf(
|
||||
assembler.Float64LessThan(x_value, assembler.Float64Constant(0.0)),
|
||||
&if_xisnegative);
|
||||
assembler->GotoIf(
|
||||
assembler->Float64LessThan(assembler->Float64Constant(0.0), x_value),
|
||||
assembler.GotoIf(
|
||||
assembler.Float64LessThan(assembler.Float64Constant(0.0), x_value),
|
||||
&if_xispositive);
|
||||
assembler->Return(assembler->ChangeFloat64ToTagged(x_value));
|
||||
assembler.Return(assembler.ChangeFloat64ToTagged(x_value));
|
||||
|
||||
assembler->Bind(&if_xisnegative);
|
||||
assembler->Return(assembler->SmiConstant(Smi::FromInt(-1)));
|
||||
assembler.Bind(&if_xisnegative);
|
||||
assembler.Return(assembler.SmiConstant(Smi::FromInt(-1)));
|
||||
|
||||
assembler->Bind(&if_xispositive);
|
||||
assembler->Return(assembler->SmiConstant(Smi::FromInt(1)));
|
||||
assembler.Bind(&if_xispositive);
|
||||
assembler.Return(assembler.SmiConstant(Smi::FromInt(1)));
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.30 Math.sin ( x )
|
||||
void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sin);
|
||||
void Builtins::Generate_MathSin(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Sin);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.31 Math.sinh ( x )
|
||||
void Builtins::Generate_MathSinh(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sinh);
|
||||
void Builtins::Generate_MathSinh(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Sinh);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.32 Math.sqrt ( x )
|
||||
void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sqrt);
|
||||
void Builtins::Generate_MathSqrt(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Sqrt);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.33 Math.tan ( x )
|
||||
void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Tan);
|
||||
void Builtins::Generate_MathTan(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Tan);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.34 Math.tanh ( x )
|
||||
void Builtins::Generate_MathTanh(CodeStubAssembler* assembler) {
|
||||
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Tanh);
|
||||
void Builtins::Generate_MathTanh(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Tanh);
|
||||
}
|
||||
|
||||
// ES6 section 20.2.2.35 Math.trunc ( x )
|
||||
void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
|
||||
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
|
||||
void Builtins::Generate_MathTrunc(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Trunc);
|
||||
}
|
||||
|
||||
void Builtins::Generate_MathMax(MacroAssembler* masm) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,50 +14,52 @@ namespace internal {
|
||||
// -----------------------------------------------------------------------------
|
||||
// ES6 section 19.1 Object Objects
|
||||
|
||||
void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ObjectHasOwnProperty(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* object = assembler->Parameter(0);
|
||||
Node* key = assembler->Parameter(1);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* object = assembler.Parameter(0);
|
||||
Node* key = assembler.Parameter(1);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
Label call_runtime(assembler), return_true(assembler),
|
||||
return_false(assembler);
|
||||
Label call_runtime(&assembler), return_true(&assembler),
|
||||
return_false(&assembler);
|
||||
|
||||
// Smi receivers do not have own properties.
|
||||
Label if_objectisnotsmi(assembler);
|
||||
assembler->Branch(assembler->TaggedIsSmi(object), &return_false,
|
||||
&if_objectisnotsmi);
|
||||
assembler->Bind(&if_objectisnotsmi);
|
||||
Label if_objectisnotsmi(&assembler);
|
||||
assembler.Branch(assembler.TaggedIsSmi(object), &return_false,
|
||||
&if_objectisnotsmi);
|
||||
assembler.Bind(&if_objectisnotsmi);
|
||||
|
||||
Node* map = assembler->LoadMap(object);
|
||||
Node* instance_type = assembler->LoadMapInstanceType(map);
|
||||
Node* map = assembler.LoadMap(object);
|
||||
Node* instance_type = assembler.LoadMapInstanceType(map);
|
||||
|
||||
Variable var_index(assembler, MachineType::PointerRepresentation());
|
||||
Variable var_index(&assembler, MachineType::PointerRepresentation());
|
||||
|
||||
Label keyisindex(assembler), if_iskeyunique(assembler);
|
||||
assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
|
||||
&call_runtime);
|
||||
Label keyisindex(&assembler), if_iskeyunique(&assembler);
|
||||
assembler.TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
|
||||
&call_runtime);
|
||||
|
||||
assembler->Bind(&if_iskeyunique);
|
||||
assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true,
|
||||
&return_false, &call_runtime);
|
||||
assembler.Bind(&if_iskeyunique);
|
||||
assembler.TryHasOwnProperty(object, map, instance_type, key, &return_true,
|
||||
&return_false, &call_runtime);
|
||||
|
||||
assembler->Bind(&keyisindex);
|
||||
assembler->TryLookupElement(object, map, instance_type, var_index.value(),
|
||||
&return_true, &return_false, &call_runtime);
|
||||
assembler.Bind(&keyisindex);
|
||||
assembler.TryLookupElement(object, map, instance_type, var_index.value(),
|
||||
&return_true, &return_false, &call_runtime);
|
||||
|
||||
assembler->Bind(&return_true);
|
||||
assembler->Return(assembler->BooleanConstant(true));
|
||||
assembler.Bind(&return_true);
|
||||
assembler.Return(assembler.BooleanConstant(true));
|
||||
|
||||
assembler->Bind(&return_false);
|
||||
assembler->Return(assembler->BooleanConstant(false));
|
||||
assembler.Bind(&return_false);
|
||||
assembler.Return(assembler.BooleanConstant(false));
|
||||
|
||||
assembler->Bind(&call_runtime);
|
||||
assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty,
|
||||
context, object, key));
|
||||
assembler.Bind(&call_runtime);
|
||||
assembler.Return(assembler.CallRuntime(Runtime::kObjectHasOwnProperty,
|
||||
context, object, key));
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -273,76 +275,78 @@ void ReturnIfPrimitive(CodeStubAssembler* assembler,
|
||||
} // namespace
|
||||
|
||||
// ES6 section 19.1.3.6 Object.prototype.toString
|
||||
void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ObjectProtoToString(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Label return_undefined(assembler, Label::kDeferred),
|
||||
return_null(assembler, Label::kDeferred),
|
||||
return_arguments(assembler, Label::kDeferred), return_array(assembler),
|
||||
return_api(assembler, Label::kDeferred), return_object(assembler),
|
||||
return_regexp(assembler), return_function(assembler),
|
||||
return_error(assembler), return_date(assembler), return_string(assembler),
|
||||
return_boolean(assembler), return_jsvalue(assembler),
|
||||
return_jsproxy(assembler, Label::kDeferred), return_number(assembler);
|
||||
Label return_undefined(&assembler, Label::kDeferred),
|
||||
return_null(&assembler, Label::kDeferred),
|
||||
return_arguments(&assembler, Label::kDeferred), return_array(&assembler),
|
||||
return_api(&assembler, Label::kDeferred), return_object(&assembler),
|
||||
return_regexp(&assembler), return_function(&assembler),
|
||||
return_error(&assembler), return_date(&assembler),
|
||||
return_string(&assembler), return_boolean(&assembler),
|
||||
return_jsvalue(&assembler), return_jsproxy(&assembler, Label::kDeferred),
|
||||
return_number(&assembler);
|
||||
|
||||
Label if_isproxy(assembler, Label::kDeferred);
|
||||
Label if_isproxy(&assembler, Label::kDeferred);
|
||||
|
||||
Label checkstringtag(assembler);
|
||||
Label if_tostringtag(assembler), if_notostringtag(assembler);
|
||||
Label checkstringtag(&assembler);
|
||||
Label if_tostringtag(&assembler), if_notostringtag(&assembler);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
assembler->GotoIf(
|
||||
assembler->WordEqual(receiver, assembler->UndefinedConstant()),
|
||||
&return_undefined);
|
||||
assembler.GotoIf(assembler.WordEqual(receiver, assembler.UndefinedConstant()),
|
||||
&return_undefined);
|
||||
|
||||
assembler->GotoIf(assembler->WordEqual(receiver, assembler->NullConstant()),
|
||||
&return_null);
|
||||
assembler.GotoIf(assembler.WordEqual(receiver, assembler.NullConstant()),
|
||||
&return_null);
|
||||
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(receiver), &return_number);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(receiver), &return_number);
|
||||
|
||||
Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
|
||||
ReturnIfPrimitive(assembler, receiver_instance_type, &return_string,
|
||||
Node* receiver_instance_type = assembler.LoadInstanceType(receiver);
|
||||
ReturnIfPrimitive(&assembler, receiver_instance_type, &return_string,
|
||||
&return_boolean, &return_number);
|
||||
|
||||
// for proxies, check IsArray before getting @@toStringTag
|
||||
Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged);
|
||||
var_proxy_is_array.Bind(assembler->BooleanConstant(false));
|
||||
Variable var_proxy_is_array(&assembler, MachineRepresentation::kTagged);
|
||||
var_proxy_is_array.Bind(assembler.BooleanConstant(false));
|
||||
|
||||
assembler->Branch(
|
||||
assembler->Word32Equal(receiver_instance_type,
|
||||
assembler->Int32Constant(JS_PROXY_TYPE)),
|
||||
assembler.Branch(
|
||||
assembler.Word32Equal(receiver_instance_type,
|
||||
assembler.Int32Constant(JS_PROXY_TYPE)),
|
||||
&if_isproxy, &checkstringtag);
|
||||
|
||||
assembler->Bind(&if_isproxy);
|
||||
assembler.Bind(&if_isproxy);
|
||||
{
|
||||
// This can throw
|
||||
var_proxy_is_array.Bind(
|
||||
assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver));
|
||||
assembler->Goto(&checkstringtag);
|
||||
assembler.CallRuntime(Runtime::kArrayIsArray, context, receiver));
|
||||
assembler.Goto(&checkstringtag);
|
||||
}
|
||||
|
||||
assembler->Bind(&checkstringtag);
|
||||
assembler.Bind(&checkstringtag);
|
||||
{
|
||||
Node* to_string_tag_symbol = assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->to_string_tag_symbol());
|
||||
Node* to_string_tag_symbol = assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->to_string_tag_symbol());
|
||||
|
||||
GetPropertyStub stub(assembler->isolate());
|
||||
GetPropertyStub stub(assembler.isolate());
|
||||
Callable get_property =
|
||||
Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
|
||||
Node* to_string_tag_value = assembler->CallStub(
|
||||
Node* to_string_tag_value = assembler.CallStub(
|
||||
get_property, context, receiver, to_string_tag_symbol);
|
||||
|
||||
IsString(assembler, to_string_tag_value, &if_tostringtag,
|
||||
IsString(&assembler, to_string_tag_value, &if_tostringtag,
|
||||
&if_notostringtag);
|
||||
|
||||
assembler->Bind(&if_tostringtag);
|
||||
ReturnToStringFormat(assembler, context, to_string_tag_value);
|
||||
assembler.Bind(&if_tostringtag);
|
||||
ReturnToStringFormat(&assembler, context, to_string_tag_value);
|
||||
}
|
||||
assembler->Bind(&if_notostringtag);
|
||||
assembler.Bind(&if_notostringtag);
|
||||
{
|
||||
size_t const kNumCases = 11;
|
||||
Label* case_labels[kNumCases];
|
||||
@ -370,178 +374,179 @@ void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
|
||||
case_labels[10] = &return_jsproxy;
|
||||
case_values[10] = JS_PROXY_TYPE;
|
||||
|
||||
assembler->Switch(receiver_instance_type, &return_object, case_values,
|
||||
case_labels, arraysize(case_values));
|
||||
assembler.Switch(receiver_instance_type, &return_object, case_values,
|
||||
case_labels, arraysize(case_values));
|
||||
|
||||
assembler->Bind(&return_undefined);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->undefined_to_string()));
|
||||
assembler.Bind(&return_undefined);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->undefined_to_string()));
|
||||
|
||||
assembler->Bind(&return_null);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->null_to_string()));
|
||||
assembler.Bind(&return_null);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->null_to_string()));
|
||||
|
||||
assembler->Bind(&return_number);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->number_to_string()));
|
||||
assembler.Bind(&return_number);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->number_to_string()));
|
||||
|
||||
assembler->Bind(&return_string);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->string_to_string()));
|
||||
assembler.Bind(&return_string);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->string_to_string()));
|
||||
|
||||
assembler->Bind(&return_boolean);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->boolean_to_string()));
|
||||
assembler.Bind(&return_boolean);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->boolean_to_string()));
|
||||
|
||||
assembler->Bind(&return_arguments);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->arguments_to_string()));
|
||||
assembler.Bind(&return_arguments);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->arguments_to_string()));
|
||||
|
||||
assembler->Bind(&return_array);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->array_to_string()));
|
||||
assembler.Bind(&return_array);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->array_to_string()));
|
||||
|
||||
assembler->Bind(&return_function);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->function_to_string()));
|
||||
assembler.Bind(&return_function);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->function_to_string()));
|
||||
|
||||
assembler->Bind(&return_error);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->error_to_string()));
|
||||
assembler.Bind(&return_error);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->error_to_string()));
|
||||
|
||||
assembler->Bind(&return_date);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->date_to_string()));
|
||||
assembler.Bind(&return_date);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->date_to_string()));
|
||||
|
||||
assembler->Bind(&return_regexp);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->regexp_to_string()));
|
||||
assembler.Bind(&return_regexp);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->regexp_to_string()));
|
||||
|
||||
assembler->Bind(&return_api);
|
||||
assembler.Bind(&return_api);
|
||||
{
|
||||
Node* class_name =
|
||||
assembler->CallRuntime(Runtime::kClassOf, context, receiver);
|
||||
ReturnToStringFormat(assembler, context, class_name);
|
||||
assembler.CallRuntime(Runtime::kClassOf, context, receiver);
|
||||
ReturnToStringFormat(&assembler, context, class_name);
|
||||
}
|
||||
|
||||
assembler->Bind(&return_jsvalue);
|
||||
assembler.Bind(&return_jsvalue);
|
||||
{
|
||||
Node* value = assembler->LoadJSValueValue(receiver);
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(value), &return_number);
|
||||
Node* value = assembler.LoadJSValueValue(receiver);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(value), &return_number);
|
||||
|
||||
ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value),
|
||||
ReturnIfPrimitive(&assembler, assembler.LoadInstanceType(value),
|
||||
&return_string, &return_boolean, &return_number);
|
||||
assembler->Goto(&return_object);
|
||||
assembler.Goto(&return_object);
|
||||
}
|
||||
|
||||
assembler->Bind(&return_jsproxy);
|
||||
assembler.Bind(&return_jsproxy);
|
||||
{
|
||||
assembler->GotoIf(assembler->WordEqual(var_proxy_is_array.value(),
|
||||
assembler->BooleanConstant(true)),
|
||||
&return_array);
|
||||
assembler.GotoIf(assembler.WordEqual(var_proxy_is_array.value(),
|
||||
assembler.BooleanConstant(true)),
|
||||
&return_array);
|
||||
|
||||
Node* map = assembler->LoadMap(receiver);
|
||||
Node* map = assembler.LoadMap(receiver);
|
||||
|
||||
// Return object if the proxy {receiver} is not callable.
|
||||
assembler->Branch(assembler->IsCallableMap(map), &return_function,
|
||||
&return_object);
|
||||
assembler.Branch(assembler.IsCallableMap(map), &return_function,
|
||||
&return_object);
|
||||
}
|
||||
|
||||
// Default
|
||||
assembler->Bind(&return_object);
|
||||
assembler->Return(assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->object_to_string()));
|
||||
assembler.Bind(&return_object);
|
||||
assembler.Return(assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->object_to_string()));
|
||||
}
|
||||
}
|
||||
|
||||
void Builtins::Generate_ObjectCreate(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_ObjectCreate(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Node* prototype = a->Parameter(1);
|
||||
Node* properties = a->Parameter(2);
|
||||
Node* context = a->Parameter(3 + 2);
|
||||
Node* prototype = a.Parameter(1);
|
||||
Node* properties = a.Parameter(2);
|
||||
Node* context = a.Parameter(3 + 2);
|
||||
|
||||
Label call_runtime(a, Label::kDeferred), prototype_valid(a), no_properties(a);
|
||||
Label call_runtime(&a, Label::kDeferred), prototype_valid(&a),
|
||||
no_properties(&a);
|
||||
{
|
||||
a->Comment("Argument 1 check: prototype");
|
||||
a->GotoIf(a->WordEqual(prototype, a->NullConstant()), &prototype_valid);
|
||||
a->BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime);
|
||||
a.Comment("Argument 1 check: prototype");
|
||||
a.GotoIf(a.WordEqual(prototype, a.NullConstant()), &prototype_valid);
|
||||
a.BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime);
|
||||
}
|
||||
|
||||
a->Bind(&prototype_valid);
|
||||
a.Bind(&prototype_valid);
|
||||
{
|
||||
a->Comment("Argument 2 check: properties");
|
||||
a.Comment("Argument 2 check: properties");
|
||||
// Check that we have a simple object
|
||||
a->GotoIf(a->TaggedIsSmi(properties), &call_runtime);
|
||||
a.GotoIf(a.TaggedIsSmi(properties), &call_runtime);
|
||||
// Undefined implies no properties.
|
||||
a->GotoIf(a->WordEqual(properties, a->UndefinedConstant()), &no_properties);
|
||||
Node* properties_map = a->LoadMap(properties);
|
||||
a->GotoIf(a->IsSpecialReceiverMap(properties_map), &call_runtime);
|
||||
a.GotoIf(a.WordEqual(properties, a.UndefinedConstant()), &no_properties);
|
||||
Node* properties_map = a.LoadMap(properties);
|
||||
a.GotoIf(a.IsSpecialReceiverMap(properties_map), &call_runtime);
|
||||
// Stay on the fast path only if there are no elements.
|
||||
a->GotoUnless(a->WordEqual(a->LoadElements(properties),
|
||||
a->LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
|
||||
&call_runtime);
|
||||
a.GotoUnless(a.WordEqual(a.LoadElements(properties),
|
||||
a.LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
|
||||
&call_runtime);
|
||||
// Handle dictionary objects or fast objects with properties in runtime.
|
||||
Node* bit_field3 = a->LoadMapBitField3(properties_map);
|
||||
a->GotoIf(a->IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
|
||||
a->Branch(a->IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
|
||||
&call_runtime, &no_properties);
|
||||
Node* bit_field3 = a.LoadMapBitField3(properties_map);
|
||||
a.GotoIf(a.IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
|
||||
a.Branch(a.IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
|
||||
&call_runtime, &no_properties);
|
||||
}
|
||||
|
||||
// Create a new object with the given prototype.
|
||||
a->Bind(&no_properties);
|
||||
a.Bind(&no_properties);
|
||||
{
|
||||
Variable map(a, MachineRepresentation::kTagged);
|
||||
Variable properties(a, MachineRepresentation::kTagged);
|
||||
Label non_null_proto(a), instantiate_map(a), good(a);
|
||||
Variable map(&a, MachineRepresentation::kTagged);
|
||||
Variable properties(&a, MachineRepresentation::kTagged);
|
||||
Label non_null_proto(&a), instantiate_map(&a), good(&a);
|
||||
|
||||
a->Branch(a->WordEqual(prototype, a->NullConstant()), &good,
|
||||
&non_null_proto);
|
||||
a.Branch(a.WordEqual(prototype, a.NullConstant()), &good, &non_null_proto);
|
||||
|
||||
a->Bind(&good);
|
||||
a.Bind(&good);
|
||||
{
|
||||
map.Bind(a->LoadContextElement(
|
||||
map.Bind(a.LoadContextElement(
|
||||
context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
|
||||
properties.Bind(
|
||||
a->AllocateNameDictionary(NameDictionary::kInitialCapacity));
|
||||
a->Goto(&instantiate_map);
|
||||
a.AllocateNameDictionary(NameDictionary::kInitialCapacity));
|
||||
a.Goto(&instantiate_map);
|
||||
}
|
||||
|
||||
a->Bind(&non_null_proto);
|
||||
a.Bind(&non_null_proto);
|
||||
{
|
||||
properties.Bind(a->EmptyFixedArrayConstant());
|
||||
properties.Bind(a.EmptyFixedArrayConstant());
|
||||
Node* object_function =
|
||||
a->LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
|
||||
Node* object_function_map = a->LoadObjectField(
|
||||
a.LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
|
||||
Node* object_function_map = a.LoadObjectField(
|
||||
object_function, JSFunction::kPrototypeOrInitialMapOffset);
|
||||
map.Bind(object_function_map);
|
||||
a->GotoIf(a->WordEqual(prototype, a->LoadMapPrototype(map.value())),
|
||||
&instantiate_map);
|
||||
a.GotoIf(a.WordEqual(prototype, a.LoadMapPrototype(map.value())),
|
||||
&instantiate_map);
|
||||
// Try loading the prototype info.
|
||||
Node* prototype_info =
|
||||
a->LoadMapPrototypeInfo(a->LoadMap(prototype), &call_runtime);
|
||||
a->Comment("Load ObjectCreateMap from PrototypeInfo");
|
||||
a.LoadMapPrototypeInfo(a.LoadMap(prototype), &call_runtime);
|
||||
a.Comment("Load ObjectCreateMap from PrototypeInfo");
|
||||
Node* weak_cell =
|
||||
a->LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
|
||||
a->GotoIf(a->WordEqual(weak_cell, a->UndefinedConstant()), &call_runtime);
|
||||
map.Bind(a->LoadWeakCellValue(weak_cell, &call_runtime));
|
||||
a->Goto(&instantiate_map);
|
||||
a.LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
|
||||
a.GotoIf(a.WordEqual(weak_cell, a.UndefinedConstant()), &call_runtime);
|
||||
map.Bind(a.LoadWeakCellValue(weak_cell, &call_runtime));
|
||||
a.Goto(&instantiate_map);
|
||||
}
|
||||
|
||||
a->Bind(&instantiate_map);
|
||||
a.Bind(&instantiate_map);
|
||||
{
|
||||
Node* instance =
|
||||
a->AllocateJSObjectFromMap(map.value(), properties.value());
|
||||
a->Return(instance);
|
||||
a.AllocateJSObjectFromMap(map.value(), properties.value());
|
||||
a.Return(instance);
|
||||
}
|
||||
}
|
||||
|
||||
a->Bind(&call_runtime);
|
||||
a.Bind(&call_runtime);
|
||||
{
|
||||
a->Return(
|
||||
a->CallRuntime(Runtime::kObjectCreate, context, prototype, properties));
|
||||
a.Return(
|
||||
a.CallRuntime(Runtime::kObjectCreate, context, prototype, properties));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1018,37 +1023,41 @@ BUILTIN(ObjectSeal) {
|
||||
return *object;
|
||||
}
|
||||
|
||||
void Builtins::Generate_HasProperty(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_HasProperty(compiler::CodeAssemblerState* state) {
|
||||
typedef HasPropertyDescriptor Descriptor;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* key = assembler->Parameter(Descriptor::kKey);
|
||||
Node* object = assembler->Parameter(Descriptor::kObject);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* key = assembler.Parameter(Descriptor::kKey);
|
||||
Node* object = assembler.Parameter(Descriptor::kObject);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(
|
||||
assembler->HasProperty(object, key, context, Runtime::kHasProperty));
|
||||
assembler.Return(
|
||||
assembler.HasProperty(object, key, context, Runtime::kHasProperty));
|
||||
}
|
||||
|
||||
void Builtins::Generate_ForInFilter(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_ForInFilter(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef ForInFilterDescriptor Descriptor;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* key = assembler->Parameter(Descriptor::kKey);
|
||||
Node* object = assembler->Parameter(Descriptor::kObject);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
Node* key = assembler.Parameter(Descriptor::kKey);
|
||||
Node* object = assembler.Parameter(Descriptor::kObject);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler->Return(assembler->ForInFilter(key, object, context));
|
||||
assembler.Return(assembler.ForInFilter(key, object, context));
|
||||
}
|
||||
|
||||
void Builtins::Generate_InstanceOf(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_InstanceOf(compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CompareDescriptor Descriptor;
|
||||
Node* object = assembler->Parameter(Descriptor::kLeft);
|
||||
Node* callable = assembler->Parameter(Descriptor::kRight);
|
||||
Node* context = assembler->Parameter(Descriptor::kContext);
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
assembler->Return(assembler->InstanceOf(object, callable, context));
|
||||
Node* object = assembler.Parameter(Descriptor::kLeft);
|
||||
Node* callable = assembler.Parameter(Descriptor::kRight);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
assembler.Return(assembler.InstanceOf(object, callable, context));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -481,16 +481,18 @@ compiler::Node* RegExpPrototypeExecInternal(CodeStubAssembler* a,
|
||||
|
||||
// ES#sec-regexp.prototype.exec
|
||||
// RegExp.prototype.exec ( string )
|
||||
void Builtins::Generate_RegExpPrototypeExec(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_RegExpPrototypeExec(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Node* const maybe_receiver = a->Parameter(0);
|
||||
Node* const maybe_string = a->Parameter(1);
|
||||
Node* const context = a->Parameter(4);
|
||||
Node* const maybe_receiver = a.Parameter(0);
|
||||
Node* const maybe_string = a.Parameter(1);
|
||||
Node* const context = a.Parameter(4);
|
||||
|
||||
Node* const result =
|
||||
RegExpPrototypeExecInternal(a, context, maybe_receiver, maybe_string);
|
||||
a->Return(result);
|
||||
RegExpPrototypeExecInternal(&a, context, maybe_receiver, maybe_string);
|
||||
a.Return(result);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -585,58 +587,59 @@ void BranchIfFastPath(CodeStubAssembler* a, compiler::Node* context,
|
||||
|
||||
} // namespace
|
||||
|
||||
void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_RegExpPrototypeFlagsGetter(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Node* const receiver = a->Parameter(0);
|
||||
Node* const context = a->Parameter(3);
|
||||
Node* const receiver = a.Parameter(0);
|
||||
Node* const context = a.Parameter(3);
|
||||
|
||||
Isolate* isolate = a->isolate();
|
||||
Node* const int_zero = a->IntPtrConstant(0);
|
||||
Node* const int_one = a->IntPtrConstant(1);
|
||||
Isolate* isolate = a.isolate();
|
||||
Node* const int_zero = a.IntPtrConstant(0);
|
||||
Node* const int_one = a.IntPtrConstant(1);
|
||||
|
||||
Node* const map = ThrowIfNotJSReceiver(a, isolate, context, receiver,
|
||||
Node* const map = ThrowIfNotJSReceiver(&a, isolate, context, receiver,
|
||||
MessageTemplate::kRegExpNonObject,
|
||||
"RegExp.prototype.flags");
|
||||
|
||||
Variable var_length(a, MachineType::PointerRepresentation());
|
||||
Variable var_flags(a, MachineType::PointerRepresentation());
|
||||
Variable var_length(&a, MachineType::PointerRepresentation());
|
||||
Variable var_flags(&a, MachineType::PointerRepresentation());
|
||||
|
||||
// First, count the number of characters we will need and check which flags
|
||||
// are set.
|
||||
|
||||
var_length.Bind(int_zero);
|
||||
|
||||
Label if_isunmodifiedjsregexp(a),
|
||||
if_isnotunmodifiedjsregexp(a, Label::kDeferred);
|
||||
a->Branch(IsInitialRegExpMap(a, context, map), &if_isunmodifiedjsregexp,
|
||||
&if_isnotunmodifiedjsregexp);
|
||||
Label if_isunmodifiedjsregexp(&a),
|
||||
if_isnotunmodifiedjsregexp(&a, Label::kDeferred);
|
||||
a.Branch(IsInitialRegExpMap(&a, context, map), &if_isunmodifiedjsregexp,
|
||||
&if_isnotunmodifiedjsregexp);
|
||||
|
||||
Label construct_string(a);
|
||||
a->Bind(&if_isunmodifiedjsregexp);
|
||||
Label construct_string(&a);
|
||||
a.Bind(&if_isunmodifiedjsregexp);
|
||||
{
|
||||
// Refer to JSRegExp's flag property on the fast-path.
|
||||
Node* const flags_smi =
|
||||
a->LoadObjectField(receiver, JSRegExp::kFlagsOffset);
|
||||
Node* const flags_intptr = a->SmiUntag(flags_smi);
|
||||
Node* const flags_smi = a.LoadObjectField(receiver, JSRegExp::kFlagsOffset);
|
||||
Node* const flags_intptr = a.SmiUntag(flags_smi);
|
||||
var_flags.Bind(flags_intptr);
|
||||
|
||||
Label label_global(a), label_ignorecase(a), label_multiline(a),
|
||||
label_unicode(a), label_sticky(a);
|
||||
Label label_global(&a), label_ignorecase(&a), label_multiline(&a),
|
||||
label_unicode(&a), label_sticky(&a);
|
||||
|
||||
#define CASE_FOR_FLAG(FLAG, LABEL, NEXT_LABEL) \
|
||||
do { \
|
||||
a->Bind(&LABEL); \
|
||||
Node* const mask = a->IntPtrConstant(FLAG); \
|
||||
a->GotoIf(a->WordEqual(a->WordAnd(flags_intptr, mask), int_zero), \
|
||||
&NEXT_LABEL); \
|
||||
var_length.Bind(a->IntPtrAdd(var_length.value(), int_one)); \
|
||||
a->Goto(&NEXT_LABEL); \
|
||||
#define CASE_FOR_FLAG(FLAG, LABEL, NEXT_LABEL) \
|
||||
do { \
|
||||
a.Bind(&LABEL); \
|
||||
Node* const mask = a.IntPtrConstant(FLAG); \
|
||||
a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \
|
||||
&NEXT_LABEL); \
|
||||
var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \
|
||||
a.Goto(&NEXT_LABEL); \
|
||||
} while (false)
|
||||
|
||||
a->Goto(&label_global);
|
||||
a.Goto(&label_global);
|
||||
CASE_FOR_FLAG(JSRegExp::kGlobal, label_global, label_ignorecase);
|
||||
CASE_FOR_FLAG(JSRegExp::kIgnoreCase, label_ignorecase, label_multiline);
|
||||
CASE_FOR_FLAG(JSRegExp::kMultiline, label_multiline, label_unicode);
|
||||
@ -645,31 +648,31 @@ void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) {
|
||||
#undef CASE_FOR_FLAG
|
||||
}
|
||||
|
||||
a->Bind(&if_isnotunmodifiedjsregexp);
|
||||
a.Bind(&if_isnotunmodifiedjsregexp);
|
||||
{
|
||||
// Fall back to GetProperty stub on the slow-path.
|
||||
var_flags.Bind(int_zero);
|
||||
|
||||
Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
|
||||
Label label_global(a), label_ignorecase(a), label_multiline(a),
|
||||
label_unicode(a), label_sticky(a);
|
||||
Callable getproperty_callable = CodeFactory::GetProperty(a.isolate());
|
||||
Label label_global(&a), label_ignorecase(&a), label_multiline(&a),
|
||||
label_unicode(&a), label_sticky(&a);
|
||||
|
||||
#define CASE_FOR_FLAG(NAME, FLAG, LABEL, NEXT_LABEL) \
|
||||
do { \
|
||||
a->Bind(&LABEL); \
|
||||
Node* const name = \
|
||||
a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked(NAME)); \
|
||||
Node* const flag = \
|
||||
a->CallStub(getproperty_callable, context, receiver, name); \
|
||||
Label if_isflagset(a); \
|
||||
a->BranchIfToBooleanIsTrue(flag, &if_isflagset, &NEXT_LABEL); \
|
||||
a->Bind(&if_isflagset); \
|
||||
var_length.Bind(a->IntPtrAdd(var_length.value(), int_one)); \
|
||||
var_flags.Bind(a->WordOr(var_flags.value(), a->IntPtrConstant(FLAG))); \
|
||||
a->Goto(&NEXT_LABEL); \
|
||||
#define CASE_FOR_FLAG(NAME, FLAG, LABEL, NEXT_LABEL) \
|
||||
do { \
|
||||
a.Bind(&LABEL); \
|
||||
Node* const name = \
|
||||
a.HeapConstant(isolate->factory()->NewStringFromAsciiChecked(NAME)); \
|
||||
Node* const flag = \
|
||||
a.CallStub(getproperty_callable, context, receiver, name); \
|
||||
Label if_isflagset(&a); \
|
||||
a.BranchIfToBooleanIsTrue(flag, &if_isflagset, &NEXT_LABEL); \
|
||||
a.Bind(&if_isflagset); \
|
||||
var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \
|
||||
var_flags.Bind(a.WordOr(var_flags.value(), a.IntPtrConstant(FLAG))); \
|
||||
a.Goto(&NEXT_LABEL); \
|
||||
} while (false)
|
||||
|
||||
a->Goto(&label_global);
|
||||
a.Goto(&label_global);
|
||||
CASE_FOR_FLAG("global", JSRegExp::kGlobal, label_global, label_ignorecase);
|
||||
CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase, label_ignorecase,
|
||||
label_multiline);
|
||||
@ -683,33 +686,33 @@ void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) {
|
||||
// Allocate a string of the required length and fill it with the corresponding
|
||||
// char for each set flag.
|
||||
|
||||
a->Bind(&construct_string);
|
||||
a.Bind(&construct_string);
|
||||
{
|
||||
Node* const result =
|
||||
a->AllocateSeqOneByteString(context, var_length.value());
|
||||
a.AllocateSeqOneByteString(context, var_length.value());
|
||||
Node* const flags_intptr = var_flags.value();
|
||||
|
||||
Variable var_offset(a, MachineType::PointerRepresentation());
|
||||
Variable var_offset(&a, MachineType::PointerRepresentation());
|
||||
var_offset.Bind(
|
||||
a->IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||
a.IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||
|
||||
Label label_global(a), label_ignorecase(a), label_multiline(a),
|
||||
label_unicode(a), label_sticky(a), out(a);
|
||||
Label label_global(&a), label_ignorecase(&a), label_multiline(&a),
|
||||
label_unicode(&a), label_sticky(&a), out(&a);
|
||||
|
||||
#define CASE_FOR_FLAG(FLAG, CHAR, LABEL, NEXT_LABEL) \
|
||||
do { \
|
||||
a->Bind(&LABEL); \
|
||||
Node* const mask = a->IntPtrConstant(FLAG); \
|
||||
a->GotoIf(a->WordEqual(a->WordAnd(flags_intptr, mask), int_zero), \
|
||||
&NEXT_LABEL); \
|
||||
Node* const value = a->IntPtrConstant(CHAR); \
|
||||
a->StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
|
||||
var_offset.value(), value); \
|
||||
var_offset.Bind(a->IntPtrAdd(var_offset.value(), int_one)); \
|
||||
a->Goto(&NEXT_LABEL); \
|
||||
#define CASE_FOR_FLAG(FLAG, CHAR, LABEL, NEXT_LABEL) \
|
||||
do { \
|
||||
a.Bind(&LABEL); \
|
||||
Node* const mask = a.IntPtrConstant(FLAG); \
|
||||
a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \
|
||||
&NEXT_LABEL); \
|
||||
Node* const value = a.IntPtrConstant(CHAR); \
|
||||
a.StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
|
||||
var_offset.value(), value); \
|
||||
var_offset.Bind(a.IntPtrAdd(var_offset.value(), int_one)); \
|
||||
a.Goto(&NEXT_LABEL); \
|
||||
} while (false)
|
||||
|
||||
a->Goto(&label_global);
|
||||
a.Goto(&label_global);
|
||||
CASE_FOR_FLAG(JSRegExp::kGlobal, 'g', label_global, label_ignorecase);
|
||||
CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i', label_ignorecase,
|
||||
label_multiline);
|
||||
@ -718,8 +721,8 @@ void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) {
|
||||
CASE_FOR_FLAG(JSRegExp::kSticky, 'y', label_sticky, out);
|
||||
#undef CASE_FOR_FLAG
|
||||
|
||||
a->Bind(&out);
|
||||
a->Return(result);
|
||||
a.Bind(&out);
|
||||
a.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -869,36 +872,46 @@ void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
|
||||
} // namespace
|
||||
|
||||
// ES6 21.2.5.4.
|
||||
void Builtins::Generate_RegExpPrototypeGlobalGetter(CodeStubAssembler* a) {
|
||||
Generate_FlagGetter(a, JSRegExp::kGlobal,
|
||||
void Builtins::Generate_RegExpPrototypeGlobalGetter(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler a(state);
|
||||
Generate_FlagGetter(&a, JSRegExp::kGlobal,
|
||||
v8::Isolate::kRegExpPrototypeOldFlagGetter,
|
||||
"RegExp.prototype.global");
|
||||
}
|
||||
|
||||
// ES6 21.2.5.5.
|
||||
void Builtins::Generate_RegExpPrototypeIgnoreCaseGetter(CodeStubAssembler* a) {
|
||||
Generate_FlagGetter(a, JSRegExp::kIgnoreCase,
|
||||
void Builtins::Generate_RegExpPrototypeIgnoreCaseGetter(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler a(state);
|
||||
Generate_FlagGetter(&a, JSRegExp::kIgnoreCase,
|
||||
v8::Isolate::kRegExpPrototypeOldFlagGetter,
|
||||
"RegExp.prototype.ignoreCase");
|
||||
}
|
||||
|
||||
// ES6 21.2.5.7.
|
||||
void Builtins::Generate_RegExpPrototypeMultilineGetter(CodeStubAssembler* a) {
|
||||
Generate_FlagGetter(a, JSRegExp::kMultiline,
|
||||
void Builtins::Generate_RegExpPrototypeMultilineGetter(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler a(state);
|
||||
Generate_FlagGetter(&a, JSRegExp::kMultiline,
|
||||
v8::Isolate::kRegExpPrototypeOldFlagGetter,
|
||||
"RegExp.prototype.multiline");
|
||||
}
|
||||
|
||||
// ES6 21.2.5.12.
|
||||
void Builtins::Generate_RegExpPrototypeStickyGetter(CodeStubAssembler* a) {
|
||||
Generate_FlagGetter(a, JSRegExp::kSticky,
|
||||
void Builtins::Generate_RegExpPrototypeStickyGetter(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler a(state);
|
||||
Generate_FlagGetter(&a, JSRegExp::kSticky,
|
||||
v8::Isolate::kRegExpPrototypeStickyGetter,
|
||||
"RegExp.prototype.sticky");
|
||||
}
|
||||
|
||||
// ES6 21.2.5.15.
|
||||
void Builtins::Generate_RegExpPrototypeUnicodeGetter(CodeStubAssembler* a) {
|
||||
Generate_FlagGetter(a, JSRegExp::kUnicode,
|
||||
void Builtins::Generate_RegExpPrototypeUnicodeGetter(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler a(state);
|
||||
Generate_FlagGetter(&a, JSRegExp::kUnicode,
|
||||
v8::Isolate::kRegExpPrototypeUnicodeGetter,
|
||||
"RegExp.prototype.unicode");
|
||||
}
|
||||
@ -1061,31 +1074,33 @@ compiler::Node* RegExpExec(CodeStubAssembler* a, compiler::Node* context,
|
||||
|
||||
// ES#sec-regexp.prototype.test
|
||||
// RegExp.prototype.test ( S )
|
||||
void Builtins::Generate_RegExpPrototypeTest(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_RegExpPrototypeTest(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Isolate* const isolate = a->isolate();
|
||||
Isolate* const isolate = a.isolate();
|
||||
|
||||
Node* const maybe_receiver = a->Parameter(0);
|
||||
Node* const maybe_string = a->Parameter(1);
|
||||
Node* const context = a->Parameter(4);
|
||||
Node* const maybe_receiver = a.Parameter(0);
|
||||
Node* const maybe_string = a.Parameter(1);
|
||||
Node* const context = a.Parameter(4);
|
||||
|
||||
// Ensure {maybe_receiver} is a JSReceiver.
|
||||
ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver,
|
||||
ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
|
||||
MessageTemplate::kIncompatibleMethodReceiver,
|
||||
"RegExp.prototype.test");
|
||||
Node* const receiver = maybe_receiver;
|
||||
|
||||
// Convert {maybe_string} to a String.
|
||||
Node* const string = a->ToString(context, maybe_string);
|
||||
Node* const string = a.ToString(context, maybe_string);
|
||||
|
||||
// Call exec.
|
||||
Node* const match_indices = RegExpExec(a, context, receiver, string);
|
||||
Node* const match_indices = RegExpExec(&a, context, receiver, string);
|
||||
|
||||
// Return true iff exec matched successfully.
|
||||
Node* const result = a->Select(a->WordEqual(match_indices, a->NullConstant()),
|
||||
a->FalseConstant(), a->TrueConstant());
|
||||
a->Return(result);
|
||||
Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()),
|
||||
a.FalseConstant(), a.TrueConstant());
|
||||
a.Return(result);
|
||||
}
|
||||
|
||||
// ES#sec-regexp.prototype-@@match
|
||||
@ -1253,34 +1268,36 @@ void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
|
||||
|
||||
// ES#sec-regexp.prototype-@@search
|
||||
// RegExp.prototype [ @@search ] ( string )
|
||||
void Builtins::Generate_RegExpPrototypeSearch(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_RegExpPrototypeSearch(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Isolate* const isolate = a->isolate();
|
||||
Isolate* const isolate = a.isolate();
|
||||
|
||||
Node* const maybe_receiver = a->Parameter(0);
|
||||
Node* const maybe_string = a->Parameter(1);
|
||||
Node* const context = a->Parameter(4);
|
||||
Node* const maybe_receiver = a.Parameter(0);
|
||||
Node* const maybe_string = a.Parameter(1);
|
||||
Node* const context = a.Parameter(4);
|
||||
|
||||
// Ensure {maybe_receiver} is a JSReceiver.
|
||||
Node* const map =
|
||||
ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver,
|
||||
ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
|
||||
MessageTemplate::kIncompatibleMethodReceiver,
|
||||
"RegExp.prototype.@@search");
|
||||
Node* const receiver = maybe_receiver;
|
||||
|
||||
// Convert {maybe_string} to a String.
|
||||
Node* const string = a->ToString(context, maybe_string);
|
||||
Node* const string = a.ToString(context, maybe_string);
|
||||
|
||||
Label fast_path(a), slow_path(a);
|
||||
BranchIfFastPath(a, context, map, &fast_path, &slow_path);
|
||||
Label fast_path(&a), slow_path(&a);
|
||||
BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
|
||||
|
||||
a->Bind(&fast_path);
|
||||
Generate_RegExpPrototypeSearchBody(a, receiver, string, context, true);
|
||||
a.Bind(&fast_path);
|
||||
Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true);
|
||||
|
||||
a->Bind(&slow_path);
|
||||
Generate_RegExpPrototypeSearchBody(a, receiver, string, context, false);
|
||||
a.Bind(&slow_path);
|
||||
Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1974,130 +1991,134 @@ compiler::Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a,
|
||||
|
||||
// ES#sec-regexp.prototype-@@replace
|
||||
// RegExp.prototype [ @@replace ] ( string, replaceValue )
|
||||
void Builtins::Generate_RegExpPrototypeReplace(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_RegExpPrototypeReplace(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Isolate* const isolate = a->isolate();
|
||||
Isolate* const isolate = a.isolate();
|
||||
|
||||
Node* const maybe_receiver = a->Parameter(0);
|
||||
Node* const maybe_string = a->Parameter(1);
|
||||
Node* const replace_value = a->Parameter(2);
|
||||
Node* const context = a->Parameter(5);
|
||||
Node* const maybe_receiver = a.Parameter(0);
|
||||
Node* const maybe_string = a.Parameter(1);
|
||||
Node* const replace_value = a.Parameter(2);
|
||||
Node* const context = a.Parameter(5);
|
||||
|
||||
Node* const int_zero = a->IntPtrConstant(0);
|
||||
Node* const int_zero = a.IntPtrConstant(0);
|
||||
|
||||
// Ensure {maybe_receiver} is a JSReceiver.
|
||||
Node* const map =
|
||||
ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver,
|
||||
ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
|
||||
MessageTemplate::kIncompatibleMethodReceiver,
|
||||
"RegExp.prototype.@@replace");
|
||||
Node* const receiver = maybe_receiver;
|
||||
|
||||
// Convert {maybe_string} to a String.
|
||||
Callable tostring_callable = CodeFactory::ToString(isolate);
|
||||
Node* const string = a->CallStub(tostring_callable, context, maybe_string);
|
||||
Node* const string = a.CallStub(tostring_callable, context, maybe_string);
|
||||
|
||||
// Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance?
|
||||
Label checkreplacecallable(a), runtime(a, Label::kDeferred), fastpath(a);
|
||||
BranchIfFastPath(a, context, map, &checkreplacecallable, &runtime);
|
||||
Label checkreplacecallable(&a), runtime(&a, Label::kDeferred), fastpath(&a);
|
||||
BranchIfFastPath(&a, context, map, &checkreplacecallable, &runtime);
|
||||
|
||||
a->Bind(&checkreplacecallable);
|
||||
a.Bind(&checkreplacecallable);
|
||||
Node* const regexp = receiver;
|
||||
|
||||
// 2. Is {replace_value} callable?
|
||||
Label checkreplacestring(a), if_iscallable(a);
|
||||
a->GotoIf(a->TaggedIsSmi(replace_value), &checkreplacestring);
|
||||
Label checkreplacestring(&a), if_iscallable(&a);
|
||||
a.GotoIf(a.TaggedIsSmi(replace_value), &checkreplacestring);
|
||||
|
||||
Node* const replace_value_map = a->LoadMap(replace_value);
|
||||
a->Branch(a->IsCallableMap(replace_value_map), &if_iscallable,
|
||||
&checkreplacestring);
|
||||
Node* const replace_value_map = a.LoadMap(replace_value);
|
||||
a.Branch(a.IsCallableMap(replace_value_map), &if_iscallable,
|
||||
&checkreplacestring);
|
||||
|
||||
// 3. Does ToString({replace_value}) contain '$'?
|
||||
a->Bind(&checkreplacestring);
|
||||
a.Bind(&checkreplacestring);
|
||||
{
|
||||
Node* const replace_string =
|
||||
a->CallStub(tostring_callable, context, replace_value);
|
||||
a.CallStub(tostring_callable, context, replace_value);
|
||||
|
||||
Node* const dollar_char = a->IntPtrConstant('$');
|
||||
Node* const smi_minusone = a->SmiConstant(Smi::FromInt(-1));
|
||||
a->GotoUnless(a->SmiEqual(a->StringIndexOfChar(context, replace_string,
|
||||
dollar_char, int_zero),
|
||||
smi_minusone),
|
||||
&runtime);
|
||||
Node* const dollar_char = a.IntPtrConstant('$');
|
||||
Node* const smi_minusone = a.SmiConstant(Smi::FromInt(-1));
|
||||
a.GotoUnless(a.SmiEqual(a.StringIndexOfChar(context, replace_string,
|
||||
dollar_char, int_zero),
|
||||
smi_minusone),
|
||||
&runtime);
|
||||
|
||||
a->Return(ReplaceSimpleStringFastPath(a, context, regexp, string,
|
||||
replace_string));
|
||||
a.Return(ReplaceSimpleStringFastPath(&a, context, regexp, string,
|
||||
replace_string));
|
||||
}
|
||||
|
||||
// {regexp} is unmodified and {replace_value} is callable.
|
||||
a->Bind(&if_iscallable);
|
||||
a.Bind(&if_iscallable);
|
||||
{
|
||||
Node* const replace_callable = replace_value;
|
||||
|
||||
// Check if the {regexp} is global.
|
||||
Label if_isglobal(a), if_isnotglobal(a);
|
||||
Node* const is_global = FastFlagGetter(a, regexp, JSRegExp::kGlobal);
|
||||
a->Branch(is_global, &if_isglobal, &if_isnotglobal);
|
||||
Label if_isglobal(&a), if_isnotglobal(&a);
|
||||
Node* const is_global = FastFlagGetter(&a, regexp, JSRegExp::kGlobal);
|
||||
a.Branch(is_global, &if_isglobal, &if_isnotglobal);
|
||||
|
||||
a->Bind(&if_isglobal);
|
||||
a.Bind(&if_isglobal);
|
||||
{
|
||||
Node* const result = ReplaceGlobalCallableFastPath(
|
||||
a, context, regexp, string, replace_callable);
|
||||
a->Return(result);
|
||||
&a, context, regexp, string, replace_callable);
|
||||
a.Return(result);
|
||||
}
|
||||
|
||||
a->Bind(&if_isnotglobal);
|
||||
a.Bind(&if_isnotglobal);
|
||||
{
|
||||
Node* const result =
|
||||
a->CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction,
|
||||
context, string, regexp, replace_callable);
|
||||
a->Return(result);
|
||||
a.CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction,
|
||||
context, string, regexp, replace_callable);
|
||||
a.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
a->Bind(&runtime);
|
||||
a.Bind(&runtime);
|
||||
{
|
||||
Node* const result = a->CallRuntime(Runtime::kRegExpReplace, context,
|
||||
receiver, string, replace_value);
|
||||
a->Return(result);
|
||||
Node* const result = a.CallRuntime(Runtime::kRegExpReplace, context,
|
||||
receiver, string, replace_value);
|
||||
a.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Simple string matching functionality for internal use which does not modify
|
||||
// the last match info.
|
||||
void Builtins::Generate_RegExpInternalMatch(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_RegExpInternalMatch(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Isolate* const isolate = a->isolate();
|
||||
Isolate* const isolate = a.isolate();
|
||||
|
||||
Node* const regexp = a->Parameter(1);
|
||||
Node* const string = a->Parameter(2);
|
||||
Node* const context = a->Parameter(5);
|
||||
Node* const regexp = a.Parameter(1);
|
||||
Node* const string = a.Parameter(2);
|
||||
Node* const context = a.Parameter(5);
|
||||
|
||||
Node* const null = a->NullConstant();
|
||||
Node* const smi_zero = a->SmiConstant(Smi::FromInt(0));
|
||||
Node* const null = a.NullConstant();
|
||||
Node* const smi_zero = a.SmiConstant(Smi::FromInt(0));
|
||||
|
||||
Node* const native_context = a->LoadNativeContext(context);
|
||||
Node* const internal_match_info = a->LoadContextElement(
|
||||
Node* const native_context = a.LoadNativeContext(context);
|
||||
Node* const internal_match_info = a.LoadContextElement(
|
||||
native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
|
||||
|
||||
Callable exec_callable = CodeFactory::RegExpExec(isolate);
|
||||
Node* const match_indices = a->CallStub(
|
||||
exec_callable, context, regexp, string, smi_zero, internal_match_info);
|
||||
Node* const match_indices = a.CallStub(exec_callable, context, regexp, string,
|
||||
smi_zero, internal_match_info);
|
||||
|
||||
Label if_matched(a), if_didnotmatch(a);
|
||||
a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
|
||||
Label if_matched(&a), if_didnotmatch(&a);
|
||||
a.Branch(a.WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
|
||||
|
||||
a->Bind(&if_didnotmatch);
|
||||
a->Return(null);
|
||||
a.Bind(&if_didnotmatch);
|
||||
a.Return(null);
|
||||
|
||||
a->Bind(&if_matched);
|
||||
a.Bind(&if_matched);
|
||||
{
|
||||
Node* result = ConstructNewResultFromMatchInfo(isolate, a, context,
|
||||
Node* result = ConstructNewResultFromMatchInfo(isolate, &a, context,
|
||||
match_indices, string);
|
||||
a->Return(result);
|
||||
a.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
|
||||
compiler::Node* context,
|
||||
compiler::Node** out_instance_type,
|
||||
compiler::Node** out_backing_store) {
|
||||
using namespace compiler;
|
||||
using compiler::Node;
|
||||
CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a),
|
||||
not_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
|
||||
not_float_or_clamped(a), invalid(a);
|
||||
@ -95,7 +95,7 @@ void ValidateSharedTypedArray(CodeStubAssembler* a, compiler::Node* tagged,
|
||||
compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
|
||||
compiler::Node* tagged,
|
||||
compiler::Node* context) {
|
||||
using namespace compiler;
|
||||
using compiler::Node;
|
||||
CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
|
||||
|
||||
Callable to_number = CodeFactory::ToNumber(a->isolate());
|
||||
@ -139,7 +139,7 @@ compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
|
||||
void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
|
||||
compiler::Node* array_length_word,
|
||||
compiler::Node* context) {
|
||||
using namespace compiler;
|
||||
using compiler::Node;
|
||||
// Check if the index is in bounds. If not, throw RangeError.
|
||||
CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
|
||||
// TODO(jkummerow): Use unsigned comparison instead of "i<0 || i>length".
|
||||
@ -155,24 +155,25 @@ void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
|
||||
using namespace compiler;
|
||||
Node* array = a->Parameter(1);
|
||||
Node* index = a->Parameter(2);
|
||||
Node* context = a->Parameter(3 + 2);
|
||||
void Builtins::Generate_AtomicsLoad(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler a(state);
|
||||
Node* array = a.Parameter(1);
|
||||
Node* index = a.Parameter(2);
|
||||
Node* context = a.Parameter(3 + 2);
|
||||
|
||||
Node* instance_type;
|
||||
Node* backing_store;
|
||||
ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
|
||||
ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store);
|
||||
|
||||
Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
|
||||
Node* array_length_word32 = a->TruncateTaggedToWord32(
|
||||
context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
|
||||
ValidateAtomicIndex(a, index_word32, array_length_word32, context);
|
||||
Node* index_word = a->ChangeUint32ToWord(index_word32);
|
||||
Node* index_word32 = ConvertTaggedAtomicIndexToWord32(&a, index, context);
|
||||
Node* array_length_word32 = a.TruncateTaggedToWord32(
|
||||
context, a.LoadObjectField(array, JSTypedArray::kLengthOffset));
|
||||
ValidateAtomicIndex(&a, index_word32, array_length_word32, context);
|
||||
Node* index_word = a.ChangeUint32ToWord(index_word32);
|
||||
|
||||
CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a),
|
||||
other(a);
|
||||
CodeStubAssembler::Label i8(&a), u8(&a), i16(&a), u16(&a), i32(&a), u32(&a),
|
||||
other(&a);
|
||||
int32_t case_values[] = {
|
||||
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
|
||||
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
|
||||
@ -180,59 +181,60 @@ void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) {
|
||||
CodeStubAssembler::Label* case_labels[] = {
|
||||
&i8, &u8, &i16, &u16, &i32, &u32,
|
||||
};
|
||||
a->Switch(instance_type, &other, case_values, case_labels,
|
||||
arraysize(case_labels));
|
||||
a.Switch(instance_type, &other, case_values, case_labels,
|
||||
arraysize(case_labels));
|
||||
|
||||
a->Bind(&i8);
|
||||
a->Return(
|
||||
a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word)));
|
||||
a.Bind(&i8);
|
||||
a.Return(
|
||||
a.SmiTag(a.AtomicLoad(MachineType::Int8(), backing_store, index_word)));
|
||||
|
||||
a->Bind(&u8);
|
||||
a->Return(a->SmiTag(
|
||||
a->AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
|
||||
a.Bind(&u8);
|
||||
a.Return(
|
||||
a.SmiTag(a.AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
|
||||
|
||||
a->Bind(&i16);
|
||||
a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store,
|
||||
a->WordShl(index_word, 1))));
|
||||
a.Bind(&i16);
|
||||
a.Return(a.SmiTag(a.AtomicLoad(MachineType::Int16(), backing_store,
|
||||
a.WordShl(index_word, 1))));
|
||||
|
||||
a->Bind(&u16);
|
||||
a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store,
|
||||
a->WordShl(index_word, 1))));
|
||||
a.Bind(&u16);
|
||||
a.Return(a.SmiTag(a.AtomicLoad(MachineType::Uint16(), backing_store,
|
||||
a.WordShl(index_word, 1))));
|
||||
|
||||
a->Bind(&i32);
|
||||
a->Return(a->ChangeInt32ToTagged(a->AtomicLoad(
|
||||
MachineType::Int32(), backing_store, a->WordShl(index_word, 2))));
|
||||
a.Bind(&i32);
|
||||
a.Return(a.ChangeInt32ToTagged(a.AtomicLoad(
|
||||
MachineType::Int32(), backing_store, a.WordShl(index_word, 2))));
|
||||
|
||||
a->Bind(&u32);
|
||||
a->Return(a->ChangeUint32ToTagged(a->AtomicLoad(
|
||||
MachineType::Uint32(), backing_store, a->WordShl(index_word, 2))));
|
||||
a.Bind(&u32);
|
||||
a.Return(a.ChangeUint32ToTagged(a.AtomicLoad(
|
||||
MachineType::Uint32(), backing_store, a.WordShl(index_word, 2))));
|
||||
|
||||
// This shouldn't happen, we've already validated the type.
|
||||
a->Bind(&other);
|
||||
a->Return(a->Int32Constant(0));
|
||||
a.Bind(&other);
|
||||
a.Return(a.Int32Constant(0));
|
||||
}
|
||||
|
||||
void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
|
||||
using namespace compiler;
|
||||
Node* array = a->Parameter(1);
|
||||
Node* index = a->Parameter(2);
|
||||
Node* value = a->Parameter(3);
|
||||
Node* context = a->Parameter(4 + 2);
|
||||
void Builtins::Generate_AtomicsStore(compiler::CodeAssemblerState* state) {
|
||||
using compiler::Node;
|
||||
CodeStubAssembler a(state);
|
||||
Node* array = a.Parameter(1);
|
||||
Node* index = a.Parameter(2);
|
||||
Node* value = a.Parameter(3);
|
||||
Node* context = a.Parameter(4 + 2);
|
||||
|
||||
Node* instance_type;
|
||||
Node* backing_store;
|
||||
ValidateSharedTypedArray(a, array, context, &instance_type, &backing_store);
|
||||
ValidateSharedTypedArray(&a, array, context, &instance_type, &backing_store);
|
||||
|
||||
Node* index_word32 = ConvertTaggedAtomicIndexToWord32(a, index, context);
|
||||
Node* array_length_word32 = a->TruncateTaggedToWord32(
|
||||
context, a->LoadObjectField(array, JSTypedArray::kLengthOffset));
|
||||
ValidateAtomicIndex(a, index_word32, array_length_word32, context);
|
||||
Node* index_word = a->ChangeUint32ToWord(index_word32);
|
||||
Node* index_word32 = ConvertTaggedAtomicIndexToWord32(&a, index, context);
|
||||
Node* array_length_word32 = a.TruncateTaggedToWord32(
|
||||
context, a.LoadObjectField(array, JSTypedArray::kLengthOffset));
|
||||
ValidateAtomicIndex(&a, index_word32, array_length_word32, context);
|
||||
Node* index_word = a.ChangeUint32ToWord(index_word32);
|
||||
|
||||
Node* value_integer = a->ToInteger(context, value);
|
||||
Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer);
|
||||
Node* value_integer = a.ToInteger(context, value);
|
||||
Node* value_word32 = a.TruncateTaggedToWord32(context, value_integer);
|
||||
|
||||
CodeStubAssembler::Label u8(a), u16(a), u32(a), other(a);
|
||||
CodeStubAssembler::Label u8(&a), u16(&a), u32(&a), other(&a);
|
||||
int32_t case_values[] = {
|
||||
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
|
||||
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_ARRAY_TYPE,
|
||||
@ -240,27 +242,27 @@ void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) {
|
||||
CodeStubAssembler::Label* case_labels[] = {
|
||||
&u8, &u8, &u16, &u16, &u32, &u32,
|
||||
};
|
||||
a->Switch(instance_type, &other, case_values, case_labels,
|
||||
arraysize(case_labels));
|
||||
a.Switch(instance_type, &other, case_values, case_labels,
|
||||
arraysize(case_labels));
|
||||
|
||||
a->Bind(&u8);
|
||||
a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
|
||||
value_word32);
|
||||
a->Return(value_integer);
|
||||
a.Bind(&u8);
|
||||
a.AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
|
||||
value_word32);
|
||||
a.Return(value_integer);
|
||||
|
||||
a->Bind(&u16);
|
||||
a->AtomicStore(MachineRepresentation::kWord16, backing_store,
|
||||
a->WordShl(index_word, 1), value_word32);
|
||||
a->Return(value_integer);
|
||||
a.Bind(&u16);
|
||||
a.AtomicStore(MachineRepresentation::kWord16, backing_store,
|
||||
a.WordShl(index_word, 1), value_word32);
|
||||
a.Return(value_integer);
|
||||
|
||||
a->Bind(&u32);
|
||||
a->AtomicStore(MachineRepresentation::kWord32, backing_store,
|
||||
a->WordShl(index_word, 2), value_word32);
|
||||
a->Return(value_integer);
|
||||
a.Bind(&u32);
|
||||
a.AtomicStore(MachineRepresentation::kWord32, backing_store,
|
||||
a.WordShl(index_word, 2), value_word32);
|
||||
a.Return(value_integer);
|
||||
|
||||
// This shouldn't happen, we've already validated the type.
|
||||
a->Bind(&other);
|
||||
a->Return(a->Int32Constant(0));
|
||||
a.Bind(&other);
|
||||
a.Return(a.Int32Constant(0));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -382,87 +382,97 @@ void GenerateStringRelationalComparison(CodeStubAssembler* assembler,
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void Builtins::Generate_StringEqual(CodeStubAssembler* assembler) {
|
||||
GenerateStringEqual(assembler, ResultMode::kDontNegateResult);
|
||||
void Builtins::Generate_StringEqual(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
GenerateStringEqual(&assembler, ResultMode::kDontNegateResult);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_StringNotEqual(CodeStubAssembler* assembler) {
|
||||
GenerateStringEqual(assembler, ResultMode::kNegateResult);
|
||||
void Builtins::Generate_StringNotEqual(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
GenerateStringEqual(&assembler, ResultMode::kNegateResult);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_StringLessThan(CodeStubAssembler* assembler) {
|
||||
GenerateStringRelationalComparison(assembler,
|
||||
void Builtins::Generate_StringLessThan(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
GenerateStringRelationalComparison(&assembler,
|
||||
RelationalComparisonMode::kLessThan);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_StringLessThanOrEqual(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringLessThanOrEqual(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
GenerateStringRelationalComparison(
|
||||
assembler, RelationalComparisonMode::kLessThanOrEqual);
|
||||
&assembler, RelationalComparisonMode::kLessThanOrEqual);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_StringGreaterThan(CodeStubAssembler* assembler) {
|
||||
GenerateStringRelationalComparison(assembler,
|
||||
void Builtins::Generate_StringGreaterThan(compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
GenerateStringRelationalComparison(&assembler,
|
||||
RelationalComparisonMode::kGreaterThan);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_StringGreaterThanOrEqual(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringGreaterThanOrEqual(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
CodeStubAssembler assembler(state);
|
||||
GenerateStringRelationalComparison(
|
||||
assembler, RelationalComparisonMode::kGreaterThanOrEqual);
|
||||
&assembler, RelationalComparisonMode::kGreaterThanOrEqual);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ES6 section 21.1 String Objects
|
||||
|
||||
// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits )
|
||||
void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringFromCharCode(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* argc = assembler->ChangeInt32ToIntPtr(
|
||||
assembler->Parameter(BuiltinDescriptor::kArgumentsCount));
|
||||
Node* context = assembler->Parameter(BuiltinDescriptor::kContext);
|
||||
Node* argc = assembler.ChangeInt32ToIntPtr(
|
||||
assembler.Parameter(BuiltinDescriptor::kArgumentsCount));
|
||||
Node* context = assembler.Parameter(BuiltinDescriptor::kContext);
|
||||
|
||||
CodeStubArguments arguments(assembler, argc);
|
||||
CodeStubArguments arguments(&assembler, argc);
|
||||
|
||||
// Check if we have exactly one argument (plus the implicit receiver), i.e.
|
||||
// if the parent frame is not an arguments adaptor frame.
|
||||
Label if_oneargument(assembler), if_notoneargument(assembler);
|
||||
assembler->Branch(assembler->WordEqual(argc, assembler->IntPtrConstant(1)),
|
||||
&if_oneargument, &if_notoneargument);
|
||||
Label if_oneargument(&assembler), if_notoneargument(&assembler);
|
||||
assembler.Branch(assembler.WordEqual(argc, assembler.IntPtrConstant(1)),
|
||||
&if_oneargument, &if_notoneargument);
|
||||
|
||||
assembler->Bind(&if_oneargument);
|
||||
assembler.Bind(&if_oneargument);
|
||||
{
|
||||
// Single argument case, perform fast single character string cache lookup
|
||||
// for one-byte code units, or fall back to creating a single character
|
||||
// string on the fly otherwise.
|
||||
Node* code = arguments.AtIndex(0);
|
||||
Node* code32 = assembler->TruncateTaggedToWord32(context, code);
|
||||
Node* code16 = assembler->Word32And(
|
||||
code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit));
|
||||
Node* result = assembler->StringFromCharCode(code16);
|
||||
Node* code32 = assembler.TruncateTaggedToWord32(context, code);
|
||||
Node* code16 = assembler.Word32And(
|
||||
code32, assembler.Int32Constant(String::kMaxUtf16CodeUnit));
|
||||
Node* result = assembler.StringFromCharCode(code16);
|
||||
arguments.PopAndReturn(result);
|
||||
}
|
||||
|
||||
Node* code16 = nullptr;
|
||||
assembler->Bind(&if_notoneargument);
|
||||
assembler.Bind(&if_notoneargument);
|
||||
{
|
||||
Label two_byte(assembler);
|
||||
Label two_byte(&assembler);
|
||||
// Assume that the resulting string contains only one-byte characters.
|
||||
Node* one_byte_result = assembler->AllocateSeqOneByteString(context, argc);
|
||||
Node* one_byte_result = assembler.AllocateSeqOneByteString(context, argc);
|
||||
|
||||
Variable max_index(assembler, MachineType::PointerRepresentation());
|
||||
max_index.Bind(assembler->IntPtrConstant(0));
|
||||
Variable max_index(&assembler, MachineType::PointerRepresentation());
|
||||
max_index.Bind(assembler.IntPtrConstant(0));
|
||||
|
||||
// Iterate over the incoming arguments, converting them to 8-bit character
|
||||
// codes. Stop if any of the conversions generates a code that doesn't fit
|
||||
// in 8 bits.
|
||||
CodeStubAssembler::VariableList vars({&max_index}, assembler->zone());
|
||||
CodeStubAssembler::VariableList vars({&max_index}, assembler.zone());
|
||||
arguments.ForEach(vars, [context, &two_byte, &max_index, &code16,
|
||||
one_byte_result](CodeStubAssembler* assembler,
|
||||
Node* arg) {
|
||||
@ -487,30 +497,30 @@ void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
|
||||
});
|
||||
arguments.PopAndReturn(one_byte_result);
|
||||
|
||||
assembler->Bind(&two_byte);
|
||||
assembler.Bind(&two_byte);
|
||||
|
||||
// At least one of the characters in the string requires a 16-bit
|
||||
// representation. Allocate a SeqTwoByteString to hold the resulting
|
||||
// string.
|
||||
Node* two_byte_result = assembler->AllocateSeqTwoByteString(context, argc);
|
||||
Node* two_byte_result = assembler.AllocateSeqTwoByteString(context, argc);
|
||||
|
||||
// Copy the characters that have already been put in the 8-bit string into
|
||||
// their corresponding positions in the new 16-bit string.
|
||||
Node* zero = assembler->IntPtrConstant(0);
|
||||
assembler->CopyStringCharacters(
|
||||
one_byte_result, two_byte_result, zero, zero, max_index.value(),
|
||||
String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
|
||||
CodeStubAssembler::INTPTR_PARAMETERS);
|
||||
Node* zero = assembler.IntPtrConstant(0);
|
||||
assembler.CopyStringCharacters(one_byte_result, two_byte_result, zero, zero,
|
||||
max_index.value(), String::ONE_BYTE_ENCODING,
|
||||
String::TWO_BYTE_ENCODING,
|
||||
CodeStubAssembler::INTPTR_PARAMETERS);
|
||||
|
||||
// Write the character that caused the 8-bit to 16-bit fault.
|
||||
Node* max_index_offset = assembler->ElementOffsetFromIndex(
|
||||
Node* max_index_offset = assembler.ElementOffsetFromIndex(
|
||||
max_index.value(), UINT16_ELEMENTS,
|
||||
CodeStubAssembler::INTPTR_PARAMETERS,
|
||||
SeqTwoByteString::kHeaderSize - kHeapObjectTag);
|
||||
assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16,
|
||||
two_byte_result, max_index_offset, code16);
|
||||
assembler.StoreNoWriteBarrier(MachineRepresentation::kWord16,
|
||||
two_byte_result, max_index_offset, code16);
|
||||
max_index.Bind(
|
||||
assembler->IntPtrAdd(max_index.value(), assembler->IntPtrConstant(1)));
|
||||
assembler.IntPtrAdd(max_index.value(), assembler.IntPtrConstant(1)));
|
||||
|
||||
// Resume copying the passed-in arguments from the same place where the
|
||||
// 8-bit copy stopped, but this time copying over all of the characters
|
||||
@ -632,91 +642,93 @@ BUILTIN(StringFromCodePoint) {
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.1 String.prototype.charAt ( pos )
|
||||
void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringPrototypeCharAt(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* position = assembler->Parameter(1);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* position = assembler.Parameter(1);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
// Check that {receiver} is coercible to Object and convert it to a String.
|
||||
receiver =
|
||||
assembler->ToThisString(context, receiver, "String.prototype.charAt");
|
||||
assembler.ToThisString(context, receiver, "String.prototype.charAt");
|
||||
|
||||
// Convert the {position} to a Smi and check that it's in bounds of the
|
||||
// {receiver}.
|
||||
{
|
||||
Label return_emptystring(assembler, Label::kDeferred);
|
||||
position = assembler->ToInteger(context, position,
|
||||
CodeStubAssembler::kTruncateMinusZero);
|
||||
assembler->GotoUnless(assembler->TaggedIsSmi(position),
|
||||
&return_emptystring);
|
||||
Label return_emptystring(&assembler, Label::kDeferred);
|
||||
position = assembler.ToInteger(context, position,
|
||||
CodeStubAssembler::kTruncateMinusZero);
|
||||
assembler.GotoUnless(assembler.TaggedIsSmi(position), &return_emptystring);
|
||||
|
||||
// Determine the actual length of the {receiver} String.
|
||||
Node* receiver_length =
|
||||
assembler->LoadObjectField(receiver, String::kLengthOffset);
|
||||
assembler.LoadObjectField(receiver, String::kLengthOffset);
|
||||
|
||||
// Return "" if the Smi {position} is outside the bounds of the {receiver}.
|
||||
Label if_positioninbounds(assembler);
|
||||
assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
|
||||
&return_emptystring, &if_positioninbounds);
|
||||
Label if_positioninbounds(&assembler);
|
||||
assembler.Branch(assembler.SmiAboveOrEqual(position, receiver_length),
|
||||
&return_emptystring, &if_positioninbounds);
|
||||
|
||||
assembler->Bind(&return_emptystring);
|
||||
assembler->Return(assembler->EmptyStringConstant());
|
||||
assembler.Bind(&return_emptystring);
|
||||
assembler.Return(assembler.EmptyStringConstant());
|
||||
|
||||
assembler->Bind(&if_positioninbounds);
|
||||
assembler.Bind(&if_positioninbounds);
|
||||
}
|
||||
|
||||
// Load the character code at the {position} from the {receiver}.
|
||||
Node* code = assembler->StringCharCodeAt(receiver, position);
|
||||
Node* code = assembler.StringCharCodeAt(receiver, position);
|
||||
|
||||
// And return the single character string with only that {code}.
|
||||
Node* result = assembler->StringFromCharCode(code);
|
||||
assembler->Return(result);
|
||||
Node* result = assembler.StringFromCharCode(code);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
|
||||
void Builtins::Generate_StringPrototypeCharCodeAt(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* position = assembler->Parameter(1);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* position = assembler.Parameter(1);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
// Check that {receiver} is coercible to Object and convert it to a String.
|
||||
receiver =
|
||||
assembler->ToThisString(context, receiver, "String.prototype.charCodeAt");
|
||||
assembler.ToThisString(context, receiver, "String.prototype.charCodeAt");
|
||||
|
||||
// Convert the {position} to a Smi and check that it's in bounds of the
|
||||
// {receiver}.
|
||||
{
|
||||
Label return_nan(assembler, Label::kDeferred);
|
||||
position = assembler->ToInteger(context, position,
|
||||
CodeStubAssembler::kTruncateMinusZero);
|
||||
assembler->GotoUnless(assembler->TaggedIsSmi(position), &return_nan);
|
||||
Label return_nan(&assembler, Label::kDeferred);
|
||||
position = assembler.ToInteger(context, position,
|
||||
CodeStubAssembler::kTruncateMinusZero);
|
||||
assembler.GotoUnless(assembler.TaggedIsSmi(position), &return_nan);
|
||||
|
||||
// Determine the actual length of the {receiver} String.
|
||||
Node* receiver_length =
|
||||
assembler->LoadObjectField(receiver, String::kLengthOffset);
|
||||
assembler.LoadObjectField(receiver, String::kLengthOffset);
|
||||
|
||||
// Return NaN if the Smi {position} is outside the bounds of the {receiver}.
|
||||
Label if_positioninbounds(assembler);
|
||||
assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
|
||||
&return_nan, &if_positioninbounds);
|
||||
Label if_positioninbounds(&assembler);
|
||||
assembler.Branch(assembler.SmiAboveOrEqual(position, receiver_length),
|
||||
&return_nan, &if_positioninbounds);
|
||||
|
||||
assembler->Bind(&return_nan);
|
||||
assembler->Return(assembler->NaNConstant());
|
||||
assembler.Bind(&return_nan);
|
||||
assembler.Return(assembler.NaNConstant());
|
||||
|
||||
assembler->Bind(&if_positioninbounds);
|
||||
assembler.Bind(&if_positioninbounds);
|
||||
}
|
||||
|
||||
// Load the character at the {position} from the {receiver}.
|
||||
Node* value = assembler->StringCharCodeAt(receiver, position);
|
||||
Node* result = assembler->SmiFromWord32(value);
|
||||
assembler->Return(result);
|
||||
Node* value = assembler.StringCharCodeAt(receiver, position);
|
||||
Node* result = assembler.SmiFromWord32(value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.6
|
||||
@ -908,125 +920,127 @@ BUILTIN(StringPrototypeNormalize) {
|
||||
}
|
||||
|
||||
// ES6 section B.2.3.1 String.prototype.substr ( start, length )
|
||||
void Builtins::Generate_StringPrototypeSubstr(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_StringPrototypeSubstr(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Label out(a), handle_length(a);
|
||||
Label out(&a), handle_length(&a);
|
||||
|
||||
Variable var_start(a, MachineRepresentation::kTagged);
|
||||
Variable var_length(a, MachineRepresentation::kTagged);
|
||||
Variable var_start(&a, MachineRepresentation::kTagged);
|
||||
Variable var_length(&a, MachineRepresentation::kTagged);
|
||||
|
||||
Node* const receiver = a->Parameter(0);
|
||||
Node* const start = a->Parameter(1);
|
||||
Node* const length = a->Parameter(2);
|
||||
Node* const context = a->Parameter(5);
|
||||
Node* const receiver = a.Parameter(0);
|
||||
Node* const start = a.Parameter(1);
|
||||
Node* const length = a.Parameter(2);
|
||||
Node* const context = a.Parameter(5);
|
||||
|
||||
Node* const zero = a->SmiConstant(Smi::kZero);
|
||||
Node* const zero = a.SmiConstant(Smi::kZero);
|
||||
|
||||
// Check that {receiver} is coercible to Object and convert it to a String.
|
||||
Node* const string =
|
||||
a->ToThisString(context, receiver, "String.prototype.substr");
|
||||
a.ToThisString(context, receiver, "String.prototype.substr");
|
||||
|
||||
Node* const string_length = a->LoadStringLength(string);
|
||||
Node* const string_length = a.LoadStringLength(string);
|
||||
|
||||
// Conversions and bounds-checks for {start}.
|
||||
{
|
||||
Node* const start_int =
|
||||
a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero);
|
||||
a.ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero);
|
||||
|
||||
Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
|
||||
a->Branch(a->TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber);
|
||||
Label if_issmi(&a), if_isheapnumber(&a, Label::kDeferred);
|
||||
a.Branch(a.TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber);
|
||||
|
||||
a->Bind(&if_issmi);
|
||||
a.Bind(&if_issmi);
|
||||
{
|
||||
Node* const length_plus_start = a->SmiAdd(string_length, start_int);
|
||||
var_start.Bind(a->Select(a->SmiLessThan(start_int, zero),
|
||||
a->SmiMax(length_plus_start, zero), start_int));
|
||||
a->Goto(&handle_length);
|
||||
Node* const length_plus_start = a.SmiAdd(string_length, start_int);
|
||||
var_start.Bind(a.Select(a.SmiLessThan(start_int, zero),
|
||||
a.SmiMax(length_plus_start, zero), start_int));
|
||||
a.Goto(&handle_length);
|
||||
}
|
||||
|
||||
a->Bind(&if_isheapnumber);
|
||||
a.Bind(&if_isheapnumber);
|
||||
{
|
||||
// If {start} is a heap number, it is definitely out of bounds. If it is
|
||||
// negative, {start} = max({string_length} + {start}),0) = 0'. If it is
|
||||
// positive, set {start} to {string_length} which ultimately results in
|
||||
// returning an empty string.
|
||||
Node* const float_zero = a->Float64Constant(0.);
|
||||
Node* const start_float = a->LoadHeapNumberValue(start_int);
|
||||
var_start.Bind(a->Select(a->Float64LessThan(start_float, float_zero),
|
||||
zero, string_length));
|
||||
a->Goto(&handle_length);
|
||||
Node* const float_zero = a.Float64Constant(0.);
|
||||
Node* const start_float = a.LoadHeapNumberValue(start_int);
|
||||
var_start.Bind(a.Select(a.Float64LessThan(start_float, float_zero), zero,
|
||||
string_length));
|
||||
a.Goto(&handle_length);
|
||||
}
|
||||
}
|
||||
|
||||
// Conversions and bounds-checks for {length}.
|
||||
a->Bind(&handle_length);
|
||||
a.Bind(&handle_length);
|
||||
{
|
||||
Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
|
||||
Label if_issmi(&a), if_isheapnumber(&a, Label::kDeferred);
|
||||
|
||||
// Default to {string_length} if {length} is undefined.
|
||||
{
|
||||
Label if_isundefined(a, Label::kDeferred), if_isnotundefined(a);
|
||||
a->Branch(a->WordEqual(length, a->UndefinedConstant()), &if_isundefined,
|
||||
&if_isnotundefined);
|
||||
Label if_isundefined(&a, Label::kDeferred), if_isnotundefined(&a);
|
||||
a.Branch(a.WordEqual(length, a.UndefinedConstant()), &if_isundefined,
|
||||
&if_isnotundefined);
|
||||
|
||||
a->Bind(&if_isundefined);
|
||||
a.Bind(&if_isundefined);
|
||||
var_length.Bind(string_length);
|
||||
a->Goto(&if_issmi);
|
||||
a.Goto(&if_issmi);
|
||||
|
||||
a->Bind(&if_isnotundefined);
|
||||
a.Bind(&if_isnotundefined);
|
||||
var_length.Bind(
|
||||
a->ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero));
|
||||
a.ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero));
|
||||
}
|
||||
|
||||
a->Branch(a->TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);
|
||||
a.Branch(a.TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);
|
||||
|
||||
// Set {length} to min(max({length}, 0), {string_length} - {start}
|
||||
a->Bind(&if_issmi);
|
||||
a.Bind(&if_issmi);
|
||||
{
|
||||
Node* const positive_length = a->SmiMax(var_length.value(), zero);
|
||||
Node* const positive_length = a.SmiMax(var_length.value(), zero);
|
||||
|
||||
Node* const minimal_length = a->SmiSub(string_length, var_start.value());
|
||||
var_length.Bind(a->SmiMin(positive_length, minimal_length));
|
||||
Node* const minimal_length = a.SmiSub(string_length, var_start.value());
|
||||
var_length.Bind(a.SmiMin(positive_length, minimal_length));
|
||||
|
||||
a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out);
|
||||
a->Return(a->EmptyStringConstant());
|
||||
a.GotoUnless(a.SmiLessThanOrEqual(var_length.value(), zero), &out);
|
||||
a.Return(a.EmptyStringConstant());
|
||||
}
|
||||
|
||||
a->Bind(&if_isheapnumber);
|
||||
a.Bind(&if_isheapnumber);
|
||||
{
|
||||
// If {length} is a heap number, it is definitely out of bounds. There are
|
||||
// two cases according to the spec: if it is negative, "" is returned; if
|
||||
// it is positive, then length is set to {string_length} - {start}.
|
||||
|
||||
CSA_ASSERT(a, a->WordEqual(a->LoadMap(var_length.value()),
|
||||
a->HeapNumberMapConstant()));
|
||||
CSA_ASSERT(&a, a.WordEqual(a.LoadMap(var_length.value()),
|
||||
a.HeapNumberMapConstant()));
|
||||
|
||||
Label if_isnegative(a), if_ispositive(a);
|
||||
Node* const float_zero = a->Float64Constant(0.);
|
||||
Node* const length_float = a->LoadHeapNumberValue(var_length.value());
|
||||
a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative,
|
||||
&if_ispositive);
|
||||
Label if_isnegative(&a), if_ispositive(&a);
|
||||
Node* const float_zero = a.Float64Constant(0.);
|
||||
Node* const length_float = a.LoadHeapNumberValue(var_length.value());
|
||||
a.Branch(a.Float64LessThan(length_float, float_zero), &if_isnegative,
|
||||
&if_ispositive);
|
||||
|
||||
a->Bind(&if_isnegative);
|
||||
a->Return(a->EmptyStringConstant());
|
||||
a.Bind(&if_isnegative);
|
||||
a.Return(a.EmptyStringConstant());
|
||||
|
||||
a->Bind(&if_ispositive);
|
||||
a.Bind(&if_ispositive);
|
||||
{
|
||||
var_length.Bind(a->SmiSub(string_length, var_start.value()));
|
||||
a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out);
|
||||
a->Return(a->EmptyStringConstant());
|
||||
var_length.Bind(a.SmiSub(string_length, var_start.value()));
|
||||
a.GotoUnless(a.SmiLessThanOrEqual(var_length.value(), zero), &out);
|
||||
a.Return(a.EmptyStringConstant());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a->Bind(&out);
|
||||
a.Bind(&out);
|
||||
{
|
||||
Node* const end = a->SmiAdd(var_start.value(), var_length.value());
|
||||
Node* const result = a->SubString(context, string, var_start.value(), end);
|
||||
a->Return(result);
|
||||
Node* const end = a.SmiAdd(var_start.value(), var_length.value());
|
||||
Node* const result = a.SubString(context, string, var_start.value(), end);
|
||||
a.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1089,55 +1103,57 @@ compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a,
|
||||
} // namespace
|
||||
|
||||
// ES6 section 21.1.3.19 String.prototype.substring ( start, end )
|
||||
void Builtins::Generate_StringPrototypeSubstring(CodeStubAssembler* a) {
|
||||
void Builtins::Generate_StringPrototypeSubstring(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler a(state);
|
||||
|
||||
Label out(a);
|
||||
Label out(&a);
|
||||
|
||||
Variable var_start(a, MachineRepresentation::kTagged);
|
||||
Variable var_end(a, MachineRepresentation::kTagged);
|
||||
Variable var_start(&a, MachineRepresentation::kTagged);
|
||||
Variable var_end(&a, MachineRepresentation::kTagged);
|
||||
|
||||
Node* const receiver = a->Parameter(0);
|
||||
Node* const start = a->Parameter(1);
|
||||
Node* const end = a->Parameter(2);
|
||||
Node* const context = a->Parameter(5);
|
||||
Node* const receiver = a.Parameter(0);
|
||||
Node* const start = a.Parameter(1);
|
||||
Node* const end = a.Parameter(2);
|
||||
Node* const context = a.Parameter(5);
|
||||
|
||||
// Check that {receiver} is coercible to Object and convert it to a String.
|
||||
Node* const string =
|
||||
a->ToThisString(context, receiver, "String.prototype.substring");
|
||||
a.ToThisString(context, receiver, "String.prototype.substring");
|
||||
|
||||
Node* const length = a->LoadStringLength(string);
|
||||
Node* const length = a.LoadStringLength(string);
|
||||
|
||||
// Conversion and bounds-checks for {start}.
|
||||
var_start.Bind(ToSmiBetweenZeroAnd(a, context, start, length));
|
||||
var_start.Bind(ToSmiBetweenZeroAnd(&a, context, start, length));
|
||||
|
||||
// Conversion and bounds-checks for {end}.
|
||||
{
|
||||
var_end.Bind(length);
|
||||
a->GotoIf(a->WordEqual(end, a->UndefinedConstant()), &out);
|
||||
a.GotoIf(a.WordEqual(end, a.UndefinedConstant()), &out);
|
||||
|
||||
var_end.Bind(ToSmiBetweenZeroAnd(a, context, end, length));
|
||||
var_end.Bind(ToSmiBetweenZeroAnd(&a, context, end, length));
|
||||
|
||||
Label if_endislessthanstart(a);
|
||||
a->Branch(a->SmiLessThan(var_end.value(), var_start.value()),
|
||||
&if_endislessthanstart, &out);
|
||||
Label if_endislessthanstart(&a);
|
||||
a.Branch(a.SmiLessThan(var_end.value(), var_start.value()),
|
||||
&if_endislessthanstart, &out);
|
||||
|
||||
a->Bind(&if_endislessthanstart);
|
||||
a.Bind(&if_endislessthanstart);
|
||||
{
|
||||
Node* const tmp = var_end.value();
|
||||
var_end.Bind(var_start.value());
|
||||
var_start.Bind(tmp);
|
||||
a->Goto(&out);
|
||||
a.Goto(&out);
|
||||
}
|
||||
}
|
||||
|
||||
a->Bind(&out);
|
||||
a.Bind(&out);
|
||||
{
|
||||
Node* result =
|
||||
a->SubString(context, string, var_start.value(), var_end.value());
|
||||
a->Return(result);
|
||||
a.SubString(context, string, var_start.value(), var_end.value());
|
||||
a.Return(result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1191,15 +1207,17 @@ BUILTIN(StringPrototypeStartsWith) {
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.25 String.prototype.toString ()
|
||||
void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringPrototypeToString(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* result = assembler->ToThisValue(
|
||||
Node* result = assembler.ToThisValue(
|
||||
context, receiver, PrimitiveType::kString, "String.prototype.toString");
|
||||
assembler->Return(result);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.27 String.prototype.trim ()
|
||||
@ -1224,43 +1242,47 @@ BUILTIN(StringPrototypeTrimRight) {
|
||||
}
|
||||
|
||||
// ES6 section 21.1.3.28 String.prototype.valueOf ( )
|
||||
void Builtins::Generate_StringPrototypeValueOf(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringPrototypeValueOf(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* result = assembler->ToThisValue(
|
||||
Node* result = assembler.ToThisValue(
|
||||
context, receiver, PrimitiveType::kString, "String.prototype.valueOf");
|
||||
assembler->Return(result);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_StringPrototypeIterator(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* string = assembler->ToThisString(context, receiver,
|
||||
"String.prototype[Symbol.iterator]");
|
||||
Node* string = assembler.ToThisString(context, receiver,
|
||||
"String.prototype[Symbol.iterator]");
|
||||
|
||||
Node* native_context = assembler->LoadNativeContext(context);
|
||||
Node* map = assembler->LoadFixedArrayElement(
|
||||
Node* native_context = assembler.LoadNativeContext(context);
|
||||
Node* map = assembler.LoadFixedArrayElement(
|
||||
native_context,
|
||||
assembler->IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0,
|
||||
assembler.IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0,
|
||||
CodeStubAssembler::INTPTR_PARAMETERS);
|
||||
Node* iterator = assembler->Allocate(JSStringIterator::kSize);
|
||||
assembler->StoreMapNoWriteBarrier(iterator, map);
|
||||
assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler->StoreObjectFieldNoWriteBarrier(
|
||||
Node* iterator = assembler.Allocate(JSStringIterator::kSize);
|
||||
assembler.StoreMapNoWriteBarrier(iterator, map);
|
||||
assembler.StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler.StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler.StoreObjectFieldNoWriteBarrier(
|
||||
iterator, JSStringIterator::kStringOffset, string);
|
||||
Node* index = assembler->SmiConstant(Smi::kZero);
|
||||
assembler->StoreObjectFieldNoWriteBarrier(
|
||||
Node* index = assembler.SmiConstant(Smi::kZero);
|
||||
assembler.StoreObjectFieldNoWriteBarrier(
|
||||
iterator, JSStringIterator::kNextIndexOffset, index);
|
||||
assembler->Return(iterator);
|
||||
assembler.Return(iterator);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1355,80 +1377,81 @@ compiler::Node* LoadSurrogatePairAt(CodeStubAssembler* assembler,
|
||||
} // namespace
|
||||
|
||||
void Builtins::Generate_StringIteratorPrototypeNext(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Variable var_value(assembler, MachineRepresentation::kTagged);
|
||||
Variable var_done(assembler, MachineRepresentation::kTagged);
|
||||
Variable var_value(&assembler, MachineRepresentation::kTagged);
|
||||
Variable var_done(&assembler, MachineRepresentation::kTagged);
|
||||
|
||||
var_value.Bind(assembler->UndefinedConstant());
|
||||
var_done.Bind(assembler->BooleanConstant(true));
|
||||
var_value.Bind(assembler.UndefinedConstant());
|
||||
var_done.Bind(assembler.BooleanConstant(true));
|
||||
|
||||
Label throw_bad_receiver(assembler), next_codepoint(assembler),
|
||||
return_result(assembler);
|
||||
Label throw_bad_receiver(&assembler), next_codepoint(&assembler),
|
||||
return_result(&assembler);
|
||||
|
||||
Node* iterator = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* iterator = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(iterator), &throw_bad_receiver);
|
||||
assembler->GotoUnless(
|
||||
assembler->WordEqual(assembler->LoadInstanceType(iterator),
|
||||
assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)),
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(iterator), &throw_bad_receiver);
|
||||
assembler.GotoUnless(
|
||||
assembler.WordEqual(assembler.LoadInstanceType(iterator),
|
||||
assembler.Int32Constant(JS_STRING_ITERATOR_TYPE)),
|
||||
&throw_bad_receiver);
|
||||
|
||||
Node* string =
|
||||
assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset);
|
||||
assembler.LoadObjectField(iterator, JSStringIterator::kStringOffset);
|
||||
Node* position =
|
||||
assembler->LoadObjectField(iterator, JSStringIterator::kNextIndexOffset);
|
||||
Node* length = assembler->LoadObjectField(string, String::kLengthOffset);
|
||||
assembler.LoadObjectField(iterator, JSStringIterator::kNextIndexOffset);
|
||||
Node* length = assembler.LoadObjectField(string, String::kLengthOffset);
|
||||
|
||||
assembler->Branch(assembler->SmiLessThan(position, length), &next_codepoint,
|
||||
&return_result);
|
||||
assembler.Branch(assembler.SmiLessThan(position, length), &next_codepoint,
|
||||
&return_result);
|
||||
|
||||
assembler->Bind(&next_codepoint);
|
||||
assembler.Bind(&next_codepoint);
|
||||
{
|
||||
Node* ch = LoadSurrogatePairAt(assembler, string, length, position);
|
||||
Node* value = assembler->StringFromCodePoint(ch, UnicodeEncoding::UTF16);
|
||||
Node* ch = LoadSurrogatePairAt(&assembler, string, length, position);
|
||||
Node* value = assembler.StringFromCodePoint(ch, UnicodeEncoding::UTF16);
|
||||
var_value.Bind(value);
|
||||
Node* length = assembler->LoadObjectField(value, String::kLengthOffset);
|
||||
assembler->StoreObjectFieldNoWriteBarrier(
|
||||
Node* length = assembler.LoadObjectField(value, String::kLengthOffset);
|
||||
assembler.StoreObjectFieldNoWriteBarrier(
|
||||
iterator, JSStringIterator::kNextIndexOffset,
|
||||
assembler->SmiAdd(position, length));
|
||||
var_done.Bind(assembler->BooleanConstant(false));
|
||||
assembler->Goto(&return_result);
|
||||
assembler.SmiAdd(position, length));
|
||||
var_done.Bind(assembler.BooleanConstant(false));
|
||||
assembler.Goto(&return_result);
|
||||
}
|
||||
|
||||
assembler->Bind(&return_result);
|
||||
assembler.Bind(&return_result);
|
||||
{
|
||||
Node* native_context = assembler->LoadNativeContext(context);
|
||||
Node* map = assembler->LoadFixedArrayElement(
|
||||
Node* native_context = assembler.LoadNativeContext(context);
|
||||
Node* map = assembler.LoadFixedArrayElement(
|
||||
native_context,
|
||||
assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
|
||||
assembler.IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
|
||||
CodeStubAssembler::INTPTR_PARAMETERS);
|
||||
Node* result = assembler->Allocate(JSIteratorResult::kSize);
|
||||
assembler->StoreMapNoWriteBarrier(result, map);
|
||||
assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler->StoreObjectFieldNoWriteBarrier(
|
||||
Node* result = assembler.Allocate(JSIteratorResult::kSize);
|
||||
assembler.StoreMapNoWriteBarrier(result, map);
|
||||
assembler.StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler.StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
assembler.StoreObjectFieldNoWriteBarrier(
|
||||
result, JSIteratorResult::kValueOffset, var_value.value());
|
||||
assembler->StoreObjectFieldNoWriteBarrier(
|
||||
assembler.StoreObjectFieldNoWriteBarrier(
|
||||
result, JSIteratorResult::kDoneOffset, var_done.value());
|
||||
assembler->Return(result);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
assembler->Bind(&throw_bad_receiver);
|
||||
assembler.Bind(&throw_bad_receiver);
|
||||
{
|
||||
// The {receiver} is not a valid JSGeneratorObject.
|
||||
Node* result = assembler->CallRuntime(
|
||||
Node* result = assembler.CallRuntime(
|
||||
Runtime::kThrowIncompatibleMethodReceiver, context,
|
||||
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
|
||||
assembler.HeapConstant(assembler.factory()->NewStringFromAsciiChecked(
|
||||
"String Iterator.prototype.next", TENURED)),
|
||||
iterator);
|
||||
assembler->Return(result); // Never reached.
|
||||
assembler.Return(result); // Never reached.
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,42 +34,47 @@ BUILTIN(SymbolConstructor_ConstructStub) {
|
||||
|
||||
// ES6 section 19.4.3.4 Symbol.prototype [ @@toPrimitive ] ( hint )
|
||||
void Builtins::Generate_SymbolPrototypeToPrimitive(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(4);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(4);
|
||||
|
||||
Node* result =
|
||||
assembler->ToThisValue(context, receiver, PrimitiveType::kSymbol,
|
||||
"Symbol.prototype [ @@toPrimitive ]");
|
||||
assembler->Return(result);
|
||||
assembler.ToThisValue(context, receiver, PrimitiveType::kSymbol,
|
||||
"Symbol.prototype [ @@toPrimitive ]");
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 19.4.3.2 Symbol.prototype.toString ( )
|
||||
void Builtins::Generate_SymbolPrototypeToString(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_SymbolPrototypeToString(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* value = assembler->ToThisValue(
|
||||
context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.toString");
|
||||
Node* value = assembler.ToThisValue(context, receiver, PrimitiveType::kSymbol,
|
||||
"Symbol.prototype.toString");
|
||||
Node* result =
|
||||
assembler->CallRuntime(Runtime::kSymbolDescriptiveString, context, value);
|
||||
assembler->Return(result);
|
||||
assembler.CallRuntime(Runtime::kSymbolDescriptiveString, context, value);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
// ES6 section 19.4.3.3 Symbol.prototype.valueOf ( )
|
||||
void Builtins::Generate_SymbolPrototypeValueOf(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_SymbolPrototypeValueOf(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Node* result = assembler->ToThisValue(
|
||||
Node* result = assembler.ToThisValue(
|
||||
context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.valueOf");
|
||||
assembler->Return(result);
|
||||
assembler.Return(result);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -20,48 +20,48 @@ BUILTIN(TypedArrayPrototypeBuffer) {
|
||||
|
||||
namespace {
|
||||
|
||||
void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
|
||||
void Generate_TypedArrayProtoypeGetter(compiler::CodeAssemblerState* state,
|
||||
const char* method_name,
|
||||
int object_offset) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef compiler::Node Node;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
// Check if the {receiver} is actually a JSTypedArray.
|
||||
Label if_receiverisincompatible(assembler, Label::kDeferred);
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(receiver),
|
||||
&if_receiverisincompatible);
|
||||
Node* receiver_instance_type = assembler->LoadInstanceType(receiver);
|
||||
assembler->GotoUnless(
|
||||
assembler->Word32Equal(receiver_instance_type,
|
||||
assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
|
||||
Label if_receiverisincompatible(&assembler, Label::kDeferred);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(receiver), &if_receiverisincompatible);
|
||||
Node* receiver_instance_type = assembler.LoadInstanceType(receiver);
|
||||
assembler.GotoUnless(
|
||||
assembler.Word32Equal(receiver_instance_type,
|
||||
assembler.Int32Constant(JS_TYPED_ARRAY_TYPE)),
|
||||
&if_receiverisincompatible);
|
||||
|
||||
// Check if the {receiver}'s JSArrayBuffer was neutered.
|
||||
Node* receiver_buffer =
|
||||
assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
|
||||
Label if_receiverisneutered(assembler, Label::kDeferred);
|
||||
assembler->GotoIf(assembler->IsDetachedBuffer(receiver_buffer),
|
||||
&if_receiverisneutered);
|
||||
assembler->Return(assembler->LoadObjectField(receiver, object_offset));
|
||||
assembler.LoadObjectField(receiver, JSTypedArray::kBufferOffset);
|
||||
Label if_receiverisneutered(&assembler, Label::kDeferred);
|
||||
assembler.GotoIf(assembler.IsDetachedBuffer(receiver_buffer),
|
||||
&if_receiverisneutered);
|
||||
assembler.Return(assembler.LoadObjectField(receiver, object_offset));
|
||||
|
||||
assembler->Bind(&if_receiverisneutered);
|
||||
assembler.Bind(&if_receiverisneutered);
|
||||
{
|
||||
// The {receiver}s buffer was neutered, default to zero.
|
||||
assembler->Return(assembler->SmiConstant(0));
|
||||
assembler.Return(assembler.SmiConstant(0));
|
||||
}
|
||||
|
||||
assembler->Bind(&if_receiverisincompatible);
|
||||
assembler.Bind(&if_receiverisincompatible);
|
||||
{
|
||||
// The {receiver} is not a valid JSGeneratorObject.
|
||||
Node* result = assembler->CallRuntime(
|
||||
Node* result = assembler.CallRuntime(
|
||||
Runtime::kThrowIncompatibleMethodReceiver, context,
|
||||
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
|
||||
assembler.HeapConstant(assembler.factory()->NewStringFromAsciiChecked(
|
||||
method_name, TENURED)),
|
||||
receiver);
|
||||
assembler->Return(result); // Never reached.
|
||||
assembler.Return(result); // Never reached.
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,100 +69,101 @@ void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler,
|
||||
|
||||
// ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
|
||||
void Builtins::Generate_TypedArrayPrototypeByteLength(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_TypedArrayProtoypeGetter(assembler,
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_TypedArrayProtoypeGetter(state,
|
||||
"get TypedArray.prototype.byteLength",
|
||||
JSTypedArray::kByteLengthOffset);
|
||||
}
|
||||
|
||||
// ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
|
||||
void Builtins::Generate_TypedArrayPrototypeByteOffset(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_TypedArrayProtoypeGetter(assembler,
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_TypedArrayProtoypeGetter(state,
|
||||
"get TypedArray.prototype.byteOffset",
|
||||
JSTypedArray::kByteOffsetOffset);
|
||||
}
|
||||
|
||||
// ES6 section 22.2.3.18 get %TypedArray%.prototype.length
|
||||
void Builtins::Generate_TypedArrayPrototypeLength(
|
||||
CodeStubAssembler* assembler) {
|
||||
Generate_TypedArrayProtoypeGetter(assembler,
|
||||
"get TypedArray.prototype.length",
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_TypedArrayProtoypeGetter(state, "get TypedArray.prototype.length",
|
||||
JSTypedArray::kLengthOffset);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <IterationKind kIterationKind>
|
||||
void Generate_TypedArrayPrototypeIterationMethod(CodeStubAssembler* assembler,
|
||||
const char* method_name) {
|
||||
void Generate_TypedArrayPrototypeIterationMethod(
|
||||
compiler::CodeAssemblerState* state, const char* method_name) {
|
||||
typedef compiler::Node Node;
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
CodeStubAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler->Parameter(0);
|
||||
Node* context = assembler->Parameter(3);
|
||||
Node* receiver = assembler.Parameter(0);
|
||||
Node* context = assembler.Parameter(3);
|
||||
|
||||
Label throw_bad_receiver(assembler, Label::kDeferred);
|
||||
Label throw_typeerror(assembler, Label::kDeferred);
|
||||
Label throw_bad_receiver(&assembler, Label::kDeferred);
|
||||
Label throw_typeerror(&assembler, Label::kDeferred);
|
||||
|
||||
assembler->GotoIf(assembler->TaggedIsSmi(receiver), &throw_bad_receiver);
|
||||
assembler.GotoIf(assembler.TaggedIsSmi(receiver), &throw_bad_receiver);
|
||||
|
||||
Node* map = assembler->LoadMap(receiver);
|
||||
Node* instance_type = assembler->LoadMapInstanceType(map);
|
||||
assembler->GotoIf(
|
||||
assembler->Word32NotEqual(instance_type,
|
||||
assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
|
||||
Node* map = assembler.LoadMap(receiver);
|
||||
Node* instance_type = assembler.LoadMapInstanceType(map);
|
||||
assembler.GotoIf(
|
||||
assembler.Word32NotEqual(instance_type,
|
||||
assembler.Int32Constant(JS_TYPED_ARRAY_TYPE)),
|
||||
&throw_bad_receiver);
|
||||
|
||||
// Check if the {receiver}'s JSArrayBuffer was neutered.
|
||||
Node* receiver_buffer =
|
||||
assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset);
|
||||
Label if_receiverisneutered(assembler, Label::kDeferred);
|
||||
assembler->GotoIf(assembler->IsDetachedBuffer(receiver_buffer),
|
||||
&if_receiverisneutered);
|
||||
assembler.LoadObjectField(receiver, JSTypedArray::kBufferOffset);
|
||||
Label if_receiverisneutered(&assembler, Label::kDeferred);
|
||||
assembler.GotoIf(assembler.IsDetachedBuffer(receiver_buffer),
|
||||
&if_receiverisneutered);
|
||||
|
||||
assembler->Return(assembler->CreateArrayIterator(receiver, map, instance_type,
|
||||
context, kIterationKind));
|
||||
assembler.Return(assembler.CreateArrayIterator(receiver, map, instance_type,
|
||||
context, kIterationKind));
|
||||
|
||||
Variable var_message(assembler, MachineRepresentation::kTagged);
|
||||
assembler->Bind(&throw_bad_receiver);
|
||||
Variable var_message(&assembler, MachineRepresentation::kTagged);
|
||||
assembler.Bind(&throw_bad_receiver);
|
||||
var_message.Bind(
|
||||
assembler->SmiConstant(Smi::FromInt(MessageTemplate::kNotTypedArray)));
|
||||
assembler->Goto(&throw_typeerror);
|
||||
assembler.SmiConstant(Smi::FromInt(MessageTemplate::kNotTypedArray)));
|
||||
assembler.Goto(&throw_typeerror);
|
||||
|
||||
assembler->Bind(&if_receiverisneutered);
|
||||
var_message.Bind(assembler->SmiConstant(
|
||||
Smi::FromInt(MessageTemplate::kDetachedOperation)));
|
||||
assembler->Goto(&throw_typeerror);
|
||||
assembler.Bind(&if_receiverisneutered);
|
||||
var_message.Bind(
|
||||
assembler.SmiConstant(Smi::FromInt(MessageTemplate::kDetachedOperation)));
|
||||
assembler.Goto(&throw_typeerror);
|
||||
|
||||
assembler->Bind(&throw_typeerror);
|
||||
assembler.Bind(&throw_typeerror);
|
||||
{
|
||||
Node* arg1 = assembler->HeapConstant(
|
||||
assembler->isolate()->factory()->NewStringFromAsciiChecked(method_name,
|
||||
TENURED));
|
||||
Node* result = assembler->CallRuntime(Runtime::kThrowTypeError, context,
|
||||
var_message.value(), arg1);
|
||||
assembler->Return(result);
|
||||
Node* arg1 = assembler.HeapConstant(
|
||||
assembler.isolate()->factory()->NewStringFromAsciiChecked(method_name,
|
||||
TENURED));
|
||||
Node* result = assembler.CallRuntime(Runtime::kThrowTypeError, context,
|
||||
var_message.value(), arg1);
|
||||
assembler.Return(result);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Builtins::Generate_TypedArrayPrototypeValues(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kValues>(
|
||||
assembler, "%TypedArray%.prototype.values()");
|
||||
state, "%TypedArray%.prototype.values()");
|
||||
}
|
||||
|
||||
void Builtins::Generate_TypedArrayPrototypeEntries(
|
||||
CodeStubAssembler* assembler) {
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kEntries>(
|
||||
assembler, "%TypedArray%.prototype.entries()");
|
||||
state, "%TypedArray%.prototype.entries()");
|
||||
}
|
||||
|
||||
void Builtins::Generate_TypedArrayPrototypeKeys(CodeStubAssembler* assembler) {
|
||||
void Builtins::Generate_TypedArrayPrototypeKeys(
|
||||
compiler::CodeAssemblerState* state) {
|
||||
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kKeys>(
|
||||
assembler, "%TypedArray%.prototype.keys()");
|
||||
state, "%TypedArray%.prototype.keys()");
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#include "src/builtins/builtins.h"
|
||||
#include "src/code-events.h"
|
||||
#include "src/code-stub-assembler.h"
|
||||
#include "src/compiler/code-assembler.h"
|
||||
#include "src/ic/ic-state.h"
|
||||
#include "src/interface-descriptors.h"
|
||||
#include "src/isolate.h"
|
||||
@ -42,7 +42,7 @@ void PostBuildProfileAndTracing(Isolate* isolate, Code* code,
|
||||
}
|
||||
|
||||
typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
|
||||
typedef void (*CodeAssemblerGenerator)(CodeStubAssembler*);
|
||||
typedef void (*CodeAssemblerGenerator)(compiler::CodeAssemblerState*);
|
||||
|
||||
Code* BuildWithMacroAssembler(Isolate* isolate,
|
||||
MacroAssemblerGenerator generator,
|
||||
@ -86,9 +86,10 @@ Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
|
||||
Zone zone(isolate->allocator(), ZONE_NAME);
|
||||
const int argc_with_recv =
|
||||
(argc == SharedFunctionInfo::kDontAdaptArgumentsSentinel) ? 0 : argc + 1;
|
||||
CodeStubAssembler assembler(isolate, &zone, argc_with_recv, flags, name);
|
||||
generator(&assembler);
|
||||
Handle<Code> code = assembler.GenerateCode();
|
||||
compiler::CodeAssemblerState state(isolate, &zone, argc_with_recv, flags,
|
||||
name);
|
||||
generator(&state);
|
||||
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
|
||||
PostBuildProfileAndTracing(isolate, *code, name);
|
||||
return *code;
|
||||
}
|
||||
@ -105,9 +106,9 @@ Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
|
||||
CallInterfaceDescriptor descriptor(isolate, interface_descriptor);
|
||||
// Ensure descriptor is already initialized.
|
||||
DCHECK_LE(0, descriptor.GetRegisterParameterCount());
|
||||
CodeStubAssembler assembler(isolate, &zone, descriptor, flags, name);
|
||||
generator(&assembler);
|
||||
Handle<Code> code = assembler.GenerateCode();
|
||||
compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name);
|
||||
generator(&state);
|
||||
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
|
||||
PostBuildProfileAndTracing(isolate, *code, name);
|
||||
return *code;
|
||||
}
|
||||
|
@ -716,8 +716,10 @@ namespace internal {
|
||||
IGNORE_BUILTIN, IGNORE_BUILTIN, V)
|
||||
|
||||
// Forward declarations.
|
||||
class CodeStubAssembler;
|
||||
class ObjectVisitor;
|
||||
namespace compiler {
|
||||
class CodeAssemblerState;
|
||||
}
|
||||
|
||||
class Builtins {
|
||||
public:
|
||||
@ -816,16 +818,13 @@ class Builtins {
|
||||
static void Generate_InterpreterPushArgsAndConstructImpl(
|
||||
MacroAssembler* masm, CallableType function_type);
|
||||
|
||||
static void Generate_DatePrototype_GetField(CodeStubAssembler* masm,
|
||||
int field_index);
|
||||
|
||||
enum class MathMaxMinKind { kMax, kMin };
|
||||
static void Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind);
|
||||
|
||||
#define DECLARE_ASM(Name, ...) \
|
||||
static void Generate_##Name(MacroAssembler* masm);
|
||||
#define DECLARE_TF(Name, ...) \
|
||||
static void Generate_##Name(CodeStubAssembler* csasm);
|
||||
static void Generate_##Name(compiler::CodeAssemblerState* state);
|
||||
|
||||
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, DECLARE_TF, DECLARE_TF,
|
||||
DECLARE_ASM, DECLARE_ASM, DECLARE_ASM)
|
||||
|
@ -13,18 +13,6 @@ namespace internal {
|
||||
|
||||
using compiler::Node;
|
||||
|
||||
CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
|
||||
const CallInterfaceDescriptor& descriptor,
|
||||
Code::Flags flags, const char* name,
|
||||
size_t result_size)
|
||||
: compiler::CodeAssembler(isolate, zone, descriptor, flags, name,
|
||||
result_size) {}
|
||||
|
||||
CodeStubAssembler::CodeStubAssembler(Isolate* isolate, Zone* zone,
|
||||
int parameter_count, Code::Flags flags,
|
||||
const char* name)
|
||||
: compiler::CodeAssembler(isolate, zone, parameter_count, flags, name) {}
|
||||
|
||||
void CodeStubAssembler::Assert(ConditionBody codition_body, const char* message,
|
||||
const char* file, int line) {
|
||||
#if defined(DEBUG)
|
||||
|
@ -44,17 +44,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
|
||||
// from a compiler directory OWNER).
|
||||
class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
public:
|
||||
// Create with CallStub linkage.
|
||||
// |result_size| specifies the number of results returned by the stub.
|
||||
// TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
|
||||
CodeStubAssembler(Isolate* isolate, Zone* zone,
|
||||
const CallInterfaceDescriptor& descriptor,
|
||||
Code::Flags flags, const char* name,
|
||||
size_t result_size = 1);
|
||||
|
||||
// Create with JSCall linkage.
|
||||
CodeStubAssembler(Isolate* isolate, Zone* zone, int parameter_count,
|
||||
Code::Flags flags, const char* name);
|
||||
CodeStubAssembler(compiler::CodeAssemblerState* state)
|
||||
: compiler::CodeAssembler(state) {}
|
||||
|
||||
enum AllocationFlag : uint8_t {
|
||||
kNone = 0,
|
||||
|
@ -251,8 +251,9 @@ Handle<Code> HydrogenCodeStub::GenerateRuntimeTailCall(
|
||||
const char* name = CodeStub::MajorName(MajorKey());
|
||||
Zone zone(isolate()->allocator(), ZONE_NAME);
|
||||
CallInterfaceDescriptor interface_descriptor(GetCallInterfaceDescriptor());
|
||||
CodeStubAssembler assembler(isolate(), &zone, interface_descriptor,
|
||||
GetCodeFlags(), name);
|
||||
compiler::CodeAssemblerState state(isolate(), &zone, interface_descriptor,
|
||||
GetCodeFlags(), name);
|
||||
CodeStubAssembler assembler(&state);
|
||||
int total_params = interface_descriptor.GetStackParameterCount() +
|
||||
interface_descriptor.GetRegisterParameterCount();
|
||||
switch (total_params) {
|
||||
@ -284,7 +285,7 @@ Handle<Code> HydrogenCodeStub::GenerateRuntimeTailCall(
|
||||
UNIMPLEMENTED();
|
||||
break;
|
||||
}
|
||||
return assembler.GenerateCode();
|
||||
return compiler::CodeAssembler::GenerateCode(&state);
|
||||
}
|
||||
|
||||
template <class Stub>
|
||||
|
File diff suppressed because it is too large
Load Diff
152
src/code-stubs.h
152
src/code-stubs.h
@ -370,7 +370,6 @@ class CodeStub BASE_EMBEDDED {
|
||||
public: \
|
||||
inline Major MajorKey() const override { return NAME; }; \
|
||||
\
|
||||
protected: \
|
||||
DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
|
||||
|
||||
|
||||
@ -386,59 +385,27 @@ class CodeStub BASE_EMBEDDED {
|
||||
Handle<Code> GenerateCode() override; \
|
||||
DEFINE_CODE_STUB(NAME, SUPER)
|
||||
|
||||
#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
|
||||
public: \
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override; \
|
||||
#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
|
||||
public: \
|
||||
void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
|
||||
DEFINE_CODE_STUB(NAME, SUPER)
|
||||
|
||||
#define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NAME, SUPER) \
|
||||
public: \
|
||||
static compiler::Node* Generate(CodeStubAssembler* assembler, \
|
||||
compiler::Node* left, compiler::Node* right, \
|
||||
compiler::Node* context); \
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override { \
|
||||
assembler->Return(Generate(assembler, assembler->Parameter(0), \
|
||||
assembler->Parameter(1), \
|
||||
assembler->Parameter(2))); \
|
||||
} \
|
||||
#define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
|
||||
public: \
|
||||
static compiler::Node* Generate( \
|
||||
CodeStubAssembler* assembler, compiler::Node* left, \
|
||||
compiler::Node* right, compiler::Node* slot_id, \
|
||||
compiler::Node* type_feedback_vector, compiler::Node* context); \
|
||||
void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
|
||||
DEFINE_CODE_STUB(NAME, SUPER)
|
||||
|
||||
#define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
|
||||
public: \
|
||||
static compiler::Node* Generate( \
|
||||
CodeStubAssembler* assembler, compiler::Node* left, \
|
||||
compiler::Node* right, compiler::Node* slot_id, \
|
||||
compiler::Node* type_feedback_vector, compiler::Node* context); \
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override { \
|
||||
assembler->Return( \
|
||||
Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \
|
||||
assembler->Parameter(2), assembler->Parameter(3), \
|
||||
assembler->Parameter(4))); \
|
||||
} \
|
||||
DEFINE_CODE_STUB(NAME, SUPER)
|
||||
|
||||
#define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(NAME, SUPER) \
|
||||
public: \
|
||||
static compiler::Node* Generate(CodeStubAssembler* assembler, \
|
||||
compiler::Node* value, \
|
||||
compiler::Node* context); \
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override { \
|
||||
assembler->Return(Generate(assembler, assembler->Parameter(0), \
|
||||
assembler->Parameter(1))); \
|
||||
} \
|
||||
DEFINE_CODE_STUB(NAME, SUPER)
|
||||
|
||||
#define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
|
||||
public: \
|
||||
static compiler::Node* Generate( \
|
||||
CodeStubAssembler* assembler, compiler::Node* value, \
|
||||
compiler::Node* context, compiler::Node* type_feedback_vector, \
|
||||
compiler::Node* slot_id); \
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override { \
|
||||
assembler->Return( \
|
||||
Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \
|
||||
assembler->Parameter(2), assembler->Parameter(3))); \
|
||||
} \
|
||||
#define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
|
||||
public: \
|
||||
static compiler::Node* Generate( \
|
||||
CodeStubAssembler* assembler, compiler::Node* value, \
|
||||
compiler::Node* context, compiler::Node* type_feedback_vector, \
|
||||
compiler::Node* slot_id); \
|
||||
void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
|
||||
DEFINE_CODE_STUB(NAME, SUPER)
|
||||
|
||||
#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
|
||||
@ -638,7 +605,7 @@ class TurboFanCodeStub : public CodeStub {
|
||||
protected:
|
||||
explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
|
||||
|
||||
virtual void GenerateAssembly(CodeStubAssembler* assembler) const = 0;
|
||||
virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0;
|
||||
|
||||
private:
|
||||
DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
|
||||
@ -794,13 +761,11 @@ class StoreInterceptorStub : public TurboFanCodeStub {
|
||||
public:
|
||||
explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assember) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::HANDLER; }
|
||||
ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
|
||||
DEFINE_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class LoadIndexedInterceptorStub : public TurboFanCodeStub {
|
||||
@ -1975,12 +1940,10 @@ class LoadICTrampolineStub : public TurboFanCodeStub {
|
||||
public:
|
||||
explicit LoadICTrampolineStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
|
||||
DEFINE_CODE_STUB(LoadICTrampoline, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(LoadICTrampoline, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
|
||||
@ -1991,8 +1954,6 @@ class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
|
||||
|
||||
ExtraICState GetExtraICState() const final {
|
||||
@ -2000,7 +1961,7 @@ class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
|
||||
}
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal);
|
||||
DEFINE_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub {
|
||||
@ -2008,11 +1969,9 @@ class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub {
|
||||
explicit KeyedLoadICTrampolineTFStub(Isolate* isolate)
|
||||
: LoadICTrampolineStub(isolate) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
|
||||
|
||||
DEFINE_CODE_STUB(KeyedLoadICTrampolineTF, LoadICTrampolineStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(KeyedLoadICTrampolineTF, LoadICTrampolineStub);
|
||||
};
|
||||
|
||||
class StoreICTrampolineStub : public TurboFanCodeStub {
|
||||
@ -2022,8 +1981,6 @@ class StoreICTrampolineStub : public TurboFanCodeStub {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
|
||||
|
||||
ExtraICState GetExtraICState() const final {
|
||||
@ -2034,7 +1991,7 @@ class StoreICTrampolineStub : public TurboFanCodeStub {
|
||||
StoreICState state() const { return StoreICState(GetExtraICState()); }
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
|
||||
DEFINE_CODE_STUB(StoreICTrampoline, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(StoreICTrampoline, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class KeyedStoreICTrampolineStub : public PlatformCodeStub {
|
||||
@ -2063,11 +2020,9 @@ class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub {
|
||||
KeyedStoreICTrampolineTFStub(Isolate* isolate, const StoreICState& state)
|
||||
: StoreICTrampolineStub(isolate, state) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
|
||||
|
||||
DEFINE_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub);
|
||||
};
|
||||
|
||||
class CallICTrampolineStub : public PlatformCodeStub {
|
||||
@ -2096,22 +2051,18 @@ class LoadICStub : public TurboFanCodeStub {
|
||||
public:
|
||||
explicit LoadICStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
|
||||
DEFINE_CODE_STUB(LoadIC, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(LoadIC, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class LoadICProtoArrayStub : public TurboFanCodeStub {
|
||||
public:
|
||||
explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray);
|
||||
DEFINE_CODE_STUB(LoadICProtoArray, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(LoadICProtoArray, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class LoadGlobalICStub : public TurboFanCodeStub {
|
||||
@ -2121,8 +2072,6 @@ class LoadGlobalICStub : public TurboFanCodeStub {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
|
||||
|
||||
ExtraICState GetExtraICState() const final {
|
||||
@ -2130,18 +2079,16 @@ class LoadGlobalICStub : public TurboFanCodeStub {
|
||||
}
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector);
|
||||
DEFINE_CODE_STUB(LoadGlobalIC, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(LoadGlobalIC, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class KeyedLoadICTFStub : public LoadICStub {
|
||||
public:
|
||||
explicit KeyedLoadICTFStub(Isolate* isolate) : LoadICStub(isolate) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
|
||||
|
||||
DEFINE_CODE_STUB(KeyedLoadICTF, LoadICStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(KeyedLoadICTF, LoadICStub);
|
||||
};
|
||||
|
||||
class StoreICStub : public TurboFanCodeStub {
|
||||
@ -2151,15 +2098,13 @@ class StoreICStub : public TurboFanCodeStub {
|
||||
minor_key_ = state.GetExtraICState();
|
||||
}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
|
||||
ExtraICState GetExtraICState() const final {
|
||||
return static_cast<ExtraICState>(minor_key_);
|
||||
}
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
|
||||
DEFINE_CODE_STUB(StoreIC, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(StoreIC, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
class KeyedStoreICStub : public PlatformCodeStub {
|
||||
@ -2189,11 +2134,9 @@ class KeyedStoreICTFStub : public StoreICStub {
|
||||
KeyedStoreICTFStub(Isolate* isolate, const StoreICState& state)
|
||||
: StoreICStub(isolate, state) {}
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
|
||||
|
||||
DEFINE_CODE_STUB(KeyedStoreICTF, StoreICStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(KeyedStoreICTF, StoreICStub);
|
||||
};
|
||||
|
||||
class DoubleToIStub : public PlatformCodeStub {
|
||||
@ -2398,23 +2341,22 @@ class AllocateHeapNumberStub : public TurboFanCodeStub {
|
||||
: TurboFanCodeStub(isolate) {}
|
||||
|
||||
void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override;
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
|
||||
DEFINE_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
#define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type) \
|
||||
class Allocate##Type##Stub : public TurboFanCodeStub { \
|
||||
public: \
|
||||
explicit Allocate##Type##Stub(Isolate* isolate) \
|
||||
: TurboFanCodeStub(isolate) {} \
|
||||
\
|
||||
void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override; \
|
||||
\
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type); \
|
||||
DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub); \
|
||||
#define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type) \
|
||||
class Allocate##Type##Stub : public TurboFanCodeStub { \
|
||||
public: \
|
||||
explicit Allocate##Type##Stub(Isolate* isolate) \
|
||||
: TurboFanCodeStub(isolate) {} \
|
||||
\
|
||||
void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
|
||||
void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
|
||||
\
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type); \
|
||||
DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub); \
|
||||
};
|
||||
SIMD128_TYPES(SIMD128_ALLOC_STUB)
|
||||
#undef SIMD128_ALLOC_STUB
|
||||
@ -2713,16 +2655,8 @@ class SubStringStub : public TurboFanCodeStub {
|
||||
compiler::Node* string, compiler::Node* from,
|
||||
compiler::Node* to, compiler::Node* context);
|
||||
|
||||
void GenerateAssembly(CodeStubAssembler* assembler) const override {
|
||||
assembler->Return(Generate(assembler,
|
||||
assembler->Parameter(Descriptor::kString),
|
||||
assembler->Parameter(Descriptor::kFrom),
|
||||
assembler->Parameter(Descriptor::kTo),
|
||||
assembler->Parameter(Descriptor::kContext)));
|
||||
}
|
||||
|
||||
DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString);
|
||||
DEFINE_CODE_STUB(SubString, TurboFanCodeStub);
|
||||
DEFINE_TURBOFAN_CODE_STUB(SubString, TurboFanCodeStub);
|
||||
};
|
||||
|
||||
|
||||
|
@ -26,11 +26,10 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
|
||||
const CallInterfaceDescriptor& descriptor,
|
||||
Code::Flags flags, const char* name,
|
||||
size_t result_size)
|
||||
: CodeAssembler(
|
||||
CodeAssemblerState::CodeAssemblerState(
|
||||
Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
|
||||
Code::Flags flags, const char* name, size_t result_size)
|
||||
: CodeAssemblerState(
|
||||
isolate, zone,
|
||||
Linkage::GetStubCallDescriptor(
|
||||
isolate, zone, descriptor, descriptor.GetStackParameterCount(),
|
||||
@ -38,19 +37,20 @@ CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
|
||||
MachineType::AnyTagged(), result_size),
|
||||
flags, name) {}
|
||||
|
||||
CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
|
||||
Code::Flags flags, const char* name)
|
||||
: CodeAssembler(isolate, zone,
|
||||
Linkage::GetJSCallDescriptor(
|
||||
zone, false, parameter_count,
|
||||
Code::ExtractKindFromFlags(flags) == Code::BUILTIN
|
||||
? CallDescriptor::kPushArgumentCount
|
||||
: CallDescriptor::kNoFlags),
|
||||
flags, name) {}
|
||||
CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
|
||||
int parameter_count, Code::Flags flags,
|
||||
const char* name)
|
||||
: CodeAssemblerState(isolate, zone,
|
||||
Linkage::GetJSCallDescriptor(
|
||||
zone, false, parameter_count,
|
||||
Code::ExtractKindFromFlags(flags) == Code::BUILTIN
|
||||
? CallDescriptor::kPushArgumentCount
|
||||
: CallDescriptor::kNoFlags),
|
||||
flags, name) {}
|
||||
|
||||
CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
|
||||
CallDescriptor* call_descriptor, Code::Flags flags,
|
||||
const char* name)
|
||||
CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
|
||||
CallDescriptor* call_descriptor,
|
||||
Code::Flags flags, const char* name)
|
||||
: raw_assembler_(new RawMachineAssembler(
|
||||
isolate, new (zone) Graph(zone), call_descriptor,
|
||||
MachineType::PointerRepresentation(),
|
||||
@ -61,52 +61,56 @@ CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
|
||||
code_generated_(false),
|
||||
variables_(zone) {}
|
||||
|
||||
CodeAssemblerState::~CodeAssemblerState() {}
|
||||
|
||||
CodeAssembler::~CodeAssembler() {}
|
||||
|
||||
void CodeAssembler::CallPrologue() {}
|
||||
|
||||
void CodeAssembler::CallEpilogue() {}
|
||||
|
||||
Handle<Code> CodeAssembler::GenerateCode() {
|
||||
DCHECK(!code_generated_);
|
||||
// static
|
||||
Handle<Code> CodeAssembler::GenerateCode(CodeAssemblerState* state) {
|
||||
DCHECK(!state->code_generated_);
|
||||
|
||||
Schedule* schedule = raw_assembler_->Export();
|
||||
RawMachineAssembler* rasm = state->raw_assembler_.get();
|
||||
Schedule* schedule = rasm->Export();
|
||||
Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
|
||||
isolate(), raw_assembler_->call_descriptor(), raw_assembler_->graph(),
|
||||
schedule, flags_, name_);
|
||||
rasm->isolate(), rasm->call_descriptor(), rasm->graph(), schedule,
|
||||
state->flags_, state->name_);
|
||||
|
||||
code_generated_ = true;
|
||||
state->code_generated_ = true;
|
||||
return code;
|
||||
}
|
||||
|
||||
bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); }
|
||||
bool CodeAssembler::Is64() const { return raw_assembler()->machine()->Is64(); }
|
||||
|
||||
bool CodeAssembler::IsFloat64RoundUpSupported() const {
|
||||
return raw_assembler_->machine()->Float64RoundUp().IsSupported();
|
||||
return raw_assembler()->machine()->Float64RoundUp().IsSupported();
|
||||
}
|
||||
|
||||
bool CodeAssembler::IsFloat64RoundDownSupported() const {
|
||||
return raw_assembler_->machine()->Float64RoundDown().IsSupported();
|
||||
return raw_assembler()->machine()->Float64RoundDown().IsSupported();
|
||||
}
|
||||
|
||||
bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
|
||||
return raw_assembler_->machine()->Float64RoundTruncate().IsSupported();
|
||||
return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Int32Constant(int32_t value) {
|
||||
return raw_assembler_->Int32Constant(value);
|
||||
return raw_assembler()->Int32Constant(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Int64Constant(int64_t value) {
|
||||
return raw_assembler_->Int64Constant(value);
|
||||
return raw_assembler()->Int64Constant(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::IntPtrConstant(intptr_t value) {
|
||||
return raw_assembler_->IntPtrConstant(value);
|
||||
return raw_assembler()->IntPtrConstant(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::NumberConstant(double value) {
|
||||
return raw_assembler_->NumberConstant(value);
|
||||
return raw_assembler()->NumberConstant(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::SmiConstant(Smi* value) {
|
||||
@ -118,19 +122,19 @@ Node* CodeAssembler::SmiConstant(int value) {
|
||||
}
|
||||
|
||||
Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
|
||||
return raw_assembler_->HeapConstant(object);
|
||||
return raw_assembler()->HeapConstant(object);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::BooleanConstant(bool value) {
|
||||
return raw_assembler_->BooleanConstant(value);
|
||||
return raw_assembler()->BooleanConstant(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::ExternalConstant(ExternalReference address) {
|
||||
return raw_assembler_->ExternalConstant(address);
|
||||
return raw_assembler()->ExternalConstant(address);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Float64Constant(double value) {
|
||||
return raw_assembler_->Float64Constant(value);
|
||||
return raw_assembler()->Float64Constant(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::NaNConstant() {
|
||||
@ -176,18 +180,18 @@ bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Parameter(int value) {
|
||||
return raw_assembler_->Parameter(value);
|
||||
return raw_assembler()->Parameter(value);
|
||||
}
|
||||
|
||||
void CodeAssembler::Return(Node* value) {
|
||||
return raw_assembler_->Return(value);
|
||||
return raw_assembler()->Return(value);
|
||||
}
|
||||
|
||||
void CodeAssembler::PopAndReturn(Node* pop, Node* value) {
|
||||
return raw_assembler_->PopAndReturn(pop, value);
|
||||
return raw_assembler()->PopAndReturn(pop, value);
|
||||
}
|
||||
|
||||
void CodeAssembler::DebugBreak() { raw_assembler_->DebugBreak(); }
|
||||
void CodeAssembler::DebugBreak() { raw_assembler()->DebugBreak(); }
|
||||
|
||||
void CodeAssembler::Comment(const char* format, ...) {
|
||||
if (!FLAG_code_comments) return;
|
||||
@ -206,81 +210,81 @@ void CodeAssembler::Comment(const char* format, ...) {
|
||||
MemCopy(copy + prefix_len, builder.Finalize(), length);
|
||||
copy[0] = ';';
|
||||
copy[1] = ' ';
|
||||
raw_assembler_->Comment(copy);
|
||||
raw_assembler()->Comment(copy);
|
||||
}
|
||||
|
||||
void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); }
|
||||
|
||||
Node* CodeAssembler::LoadFramePointer() {
|
||||
return raw_assembler_->LoadFramePointer();
|
||||
return raw_assembler()->LoadFramePointer();
|
||||
}
|
||||
|
||||
Node* CodeAssembler::LoadParentFramePointer() {
|
||||
return raw_assembler_->LoadParentFramePointer();
|
||||
return raw_assembler()->LoadParentFramePointer();
|
||||
}
|
||||
|
||||
Node* CodeAssembler::LoadStackPointer() {
|
||||
return raw_assembler_->LoadStackPointer();
|
||||
return raw_assembler()->LoadStackPointer();
|
||||
}
|
||||
|
||||
#define DEFINE_CODE_ASSEMBLER_BINARY_OP(name) \
|
||||
Node* CodeAssembler::name(Node* a, Node* b) { \
|
||||
return raw_assembler_->name(a, b); \
|
||||
return raw_assembler()->name(a, b); \
|
||||
}
|
||||
CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
|
||||
#undef DEFINE_CODE_ASSEMBLER_BINARY_OP
|
||||
|
||||
Node* CodeAssembler::WordShl(Node* value, int shift) {
|
||||
return (shift != 0) ? raw_assembler_->WordShl(value, IntPtrConstant(shift))
|
||||
return (shift != 0) ? raw_assembler()->WordShl(value, IntPtrConstant(shift))
|
||||
: value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::WordShr(Node* value, int shift) {
|
||||
return (shift != 0) ? raw_assembler_->WordShr(value, IntPtrConstant(shift))
|
||||
return (shift != 0) ? raw_assembler()->WordShr(value, IntPtrConstant(shift))
|
||||
: value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Word32Shr(Node* value, int shift) {
|
||||
return (shift != 0) ? raw_assembler_->Word32Shr(value, Int32Constant(shift))
|
||||
return (shift != 0) ? raw_assembler()->Word32Shr(value, Int32Constant(shift))
|
||||
: value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
|
||||
if (raw_assembler_->machine()->Is64()) {
|
||||
value = raw_assembler_->ChangeUint32ToUint64(value);
|
||||
if (raw_assembler()->machine()->Is64()) {
|
||||
value = raw_assembler()->ChangeUint32ToUint64(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
|
||||
if (raw_assembler_->machine()->Is64()) {
|
||||
value = raw_assembler_->ChangeInt32ToInt64(value);
|
||||
if (raw_assembler()->machine()->Is64()) {
|
||||
value = raw_assembler()->ChangeInt32ToInt64(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
|
||||
if (raw_assembler_->machine()->Is64()) {
|
||||
return raw_assembler_->RoundInt64ToFloat64(value);
|
||||
if (raw_assembler()->machine()->Is64()) {
|
||||
return raw_assembler()->RoundInt64ToFloat64(value);
|
||||
}
|
||||
return raw_assembler_->ChangeInt32ToFloat64(value);
|
||||
return raw_assembler()->ChangeInt32ToFloat64(value);
|
||||
}
|
||||
|
||||
#define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \
|
||||
Node* CodeAssembler::name(Node* a) { return raw_assembler_->name(a); }
|
||||
Node* CodeAssembler::name(Node* a) { return raw_assembler()->name(a); }
|
||||
CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
|
||||
#undef DEFINE_CODE_ASSEMBLER_UNARY_OP
|
||||
|
||||
Node* CodeAssembler::Load(MachineType rep, Node* base) {
|
||||
return raw_assembler_->Load(rep, base);
|
||||
return raw_assembler()->Load(rep, base);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Load(MachineType rep, Node* base, Node* index) {
|
||||
return raw_assembler_->Load(rep, base, index);
|
||||
return raw_assembler()->Load(rep, base, index);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::AtomicLoad(MachineType rep, Node* base, Node* index) {
|
||||
return raw_assembler_->AtomicLoad(rep, base, index);
|
||||
return raw_assembler()->AtomicLoad(rep, base, index);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
|
||||
@ -300,27 +304,27 @@ Node* CodeAssembler::LoadRoot(Heap::RootListIndex root_index) {
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* value) {
|
||||
return raw_assembler_->Store(rep, base, value, kFullWriteBarrier);
|
||||
return raw_assembler()->Store(rep, base, value, kFullWriteBarrier);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* index,
|
||||
Node* value) {
|
||||
return raw_assembler_->Store(rep, base, index, value, kFullWriteBarrier);
|
||||
return raw_assembler()->Store(rep, base, index, value, kFullWriteBarrier);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
|
||||
Node* value) {
|
||||
return raw_assembler_->Store(rep, base, value, kNoWriteBarrier);
|
||||
return raw_assembler()->Store(rep, base, value, kNoWriteBarrier);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
|
||||
Node* index, Node* value) {
|
||||
return raw_assembler_->Store(rep, base, index, value, kNoWriteBarrier);
|
||||
return raw_assembler()->Store(rep, base, index, value, kNoWriteBarrier);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
|
||||
Node* index, Node* value) {
|
||||
return raw_assembler_->AtomicStore(rep, base, index, value);
|
||||
return raw_assembler()->AtomicStore(rep, base, index, value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
|
||||
@ -332,11 +336,11 @@ Node* CodeAssembler::StoreRoot(Heap::RootListIndex root_index, Node* value) {
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Retain(Node* value) {
|
||||
return raw_assembler_->Retain(value);
|
||||
return raw_assembler()->Retain(value);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Projection(int index, Node* value) {
|
||||
return raw_assembler_->Projection(index, value);
|
||||
return raw_assembler()->Projection(index, value);
|
||||
}
|
||||
|
||||
void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
|
||||
@ -346,11 +350,11 @@ void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
|
||||
exception.MergeVariables();
|
||||
DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
|
||||
|
||||
raw_assembler_->Continuations(node, success.label_, exception.label_);
|
||||
raw_assembler()->Continuations(node, success.label_, exception.label_);
|
||||
|
||||
Bind(&exception);
|
||||
const Operator* op = raw_assembler_->common()->IfException();
|
||||
Node* exception_value = raw_assembler_->AddNode(op, node, node);
|
||||
const Operator* op = raw_assembler()->common()->IfException();
|
||||
Node* exception_value = raw_assembler()->AddNode(op, node, node);
|
||||
if (exception_var != nullptr) {
|
||||
exception_var->Bind(exception_value);
|
||||
}
|
||||
@ -362,20 +366,20 @@ void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
|
||||
Node* CodeAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
|
||||
Node** args) {
|
||||
CallPrologue();
|
||||
Node* return_value = raw_assembler_->CallN(descriptor, code_target, args);
|
||||
Node* return_value = raw_assembler()->CallN(descriptor, code_target, args);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target,
|
||||
Node** args) {
|
||||
return raw_assembler_->TailCallN(descriptor, code_target, args);
|
||||
return raw_assembler()->TailCallN(descriptor, code_target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context) {
|
||||
CallPrologue();
|
||||
Node* return_value = raw_assembler_->CallRuntime0(function_id, context);
|
||||
Node* return_value = raw_assembler()->CallRuntime0(function_id, context);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
@ -383,7 +387,8 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
|
||||
Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
|
||||
Node* arg1) {
|
||||
CallPrologue();
|
||||
Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context);
|
||||
Node* return_value =
|
||||
raw_assembler()->CallRuntime1(function_id, arg1, context);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
@ -392,7 +397,7 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
|
||||
Node* arg1, Node* arg2) {
|
||||
CallPrologue();
|
||||
Node* return_value =
|
||||
raw_assembler_->CallRuntime2(function_id, arg1, arg2, context);
|
||||
raw_assembler()->CallRuntime2(function_id, arg1, arg2, context);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
@ -401,7 +406,7 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
|
||||
Node* arg1, Node* arg2, Node* arg3) {
|
||||
CallPrologue();
|
||||
Node* return_value =
|
||||
raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context);
|
||||
raw_assembler()->CallRuntime3(function_id, arg1, arg2, arg3, context);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
@ -410,8 +415,8 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
|
||||
Node* arg1, Node* arg2, Node* arg3,
|
||||
Node* arg4) {
|
||||
CallPrologue();
|
||||
Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2,
|
||||
arg3, arg4, context);
|
||||
Node* return_value = raw_assembler()->CallRuntime4(function_id, arg1, arg2,
|
||||
arg3, arg4, context);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
@ -420,54 +425,54 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
|
||||
Node* arg1, Node* arg2, Node* arg3, Node* arg4,
|
||||
Node* arg5) {
|
||||
CallPrologue();
|
||||
Node* return_value = raw_assembler_->CallRuntime5(function_id, arg1, arg2,
|
||||
arg3, arg4, arg5, context);
|
||||
Node* return_value = raw_assembler()->CallRuntime5(function_id, arg1, arg2,
|
||||
arg3, arg4, arg5, context);
|
||||
CallEpilogue();
|
||||
return return_value;
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context) {
|
||||
return raw_assembler_->TailCallRuntime0(function_id, context);
|
||||
return raw_assembler()->TailCallRuntime0(function_id, context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context, Node* arg1) {
|
||||
return raw_assembler_->TailCallRuntime1(function_id, arg1, context);
|
||||
return raw_assembler()->TailCallRuntime1(function_id, arg1, context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context, Node* arg1, Node* arg2) {
|
||||
return raw_assembler_->TailCallRuntime2(function_id, arg1, arg2, context);
|
||||
return raw_assembler()->TailCallRuntime2(function_id, arg1, arg2, context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context, Node* arg1, Node* arg2,
|
||||
Node* arg3) {
|
||||
return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3,
|
||||
context);
|
||||
return raw_assembler()->TailCallRuntime3(function_id, arg1, arg2, arg3,
|
||||
context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context, Node* arg1, Node* arg2,
|
||||
Node* arg3, Node* arg4) {
|
||||
return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
|
||||
context);
|
||||
return raw_assembler()->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
|
||||
context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context, Node* arg1, Node* arg2,
|
||||
Node* arg3, Node* arg4, Node* arg5) {
|
||||
return raw_assembler_->TailCallRuntime5(function_id, arg1, arg2, arg3, arg4,
|
||||
arg5, context);
|
||||
return raw_assembler()->TailCallRuntime5(function_id, arg1, arg2, arg3, arg4,
|
||||
arg5, context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
|
||||
Node* context, Node* arg1, Node* arg2,
|
||||
Node* arg3, Node* arg4, Node* arg5,
|
||||
Node* arg6) {
|
||||
return raw_assembler_->TailCallRuntime6(function_id, arg1, arg2, arg3, arg4,
|
||||
arg5, arg6, context);
|
||||
return raw_assembler()->TailCallRuntime6(function_id, arg1, arg2, arg3, arg4,
|
||||
arg5, arg6, context);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
|
||||
@ -752,7 +757,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[0] = arg1;
|
||||
args[1] = context;
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -768,7 +773,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[1] = arg2;
|
||||
args[2] = context;
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -785,7 +790,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[2] = arg3;
|
||||
args[3] = context;
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -804,7 +809,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[3] = arg4;
|
||||
args[4] = context;
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -824,7 +829,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[4] = arg5;
|
||||
args[5] = context;
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -845,7 +850,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[5] = arg6;
|
||||
args[6] = context;
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -867,7 +872,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[kArgsCount - 1] = context;
|
||||
DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
@ -891,7 +896,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
|
||||
args[kArgsCount - 1] = context;
|
||||
DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr));
|
||||
|
||||
return raw_assembler_->TailCallN(call_descriptor, target, args);
|
||||
return raw_assembler()->TailCallN(call_descriptor, target, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::TailCallBytecodeDispatch(
|
||||
@ -900,7 +905,7 @@ Node* CodeAssembler::TailCallBytecodeDispatch(
|
||||
CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
|
||||
isolate(), zone(), interface_descriptor,
|
||||
interface_descriptor.GetStackParameterCount());
|
||||
return raw_assembler_->TailCallN(descriptor, code_target_address, args);
|
||||
return raw_assembler()->TailCallN(descriptor, code_target_address, args);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
|
||||
@ -973,13 +978,13 @@ Node* CodeAssembler::CallCFunction2(MachineType return_type,
|
||||
MachineType arg0_type,
|
||||
MachineType arg1_type, Node* function,
|
||||
Node* arg0, Node* arg1) {
|
||||
return raw_assembler_->CallCFunction2(return_type, arg0_type, arg1_type,
|
||||
function, arg0, arg1);
|
||||
return raw_assembler()->CallCFunction2(return_type, arg0_type, arg1_type,
|
||||
function, arg0, arg1);
|
||||
}
|
||||
|
||||
void CodeAssembler::Goto(CodeAssembler::Label* label) {
|
||||
label->MergeVariables();
|
||||
raw_assembler_->Goto(label->label_);
|
||||
raw_assembler()->Goto(label->label_);
|
||||
}
|
||||
|
||||
void CodeAssembler::GotoIf(Node* condition, Label* true_label) {
|
||||
@ -998,8 +1003,8 @@ void CodeAssembler::Branch(Node* condition, CodeAssembler::Label* true_label,
|
||||
CodeAssembler::Label* false_label) {
|
||||
true_label->MergeVariables();
|
||||
false_label->MergeVariables();
|
||||
return raw_assembler_->Branch(condition, true_label->label_,
|
||||
false_label->label_);
|
||||
return raw_assembler()->Branch(condition, true_label->label_,
|
||||
false_label->label_);
|
||||
}
|
||||
|
||||
void CodeAssembler::Switch(Node* index, Label* default_label,
|
||||
@ -1013,8 +1018,8 @@ void CodeAssembler::Switch(Node* index, Label* default_label,
|
||||
case_labels[i]->MergeVariables();
|
||||
default_label->MergeVariables();
|
||||
}
|
||||
return raw_assembler_->Switch(index, default_label->label_, case_values,
|
||||
labels, case_count);
|
||||
return raw_assembler()->Switch(index, default_label->label_, case_values,
|
||||
labels, case_count);
|
||||
}
|
||||
|
||||
Node* CodeAssembler::Select(Node* condition, Node* true_value,
|
||||
@ -1039,11 +1044,15 @@ Node* CodeAssembler::Select(Node* condition, Node* true_value,
|
||||
}
|
||||
|
||||
// RawMachineAssembler delegate helpers:
|
||||
Isolate* CodeAssembler::isolate() const { return raw_assembler_->isolate(); }
|
||||
Isolate* CodeAssembler::isolate() const { return raw_assembler()->isolate(); }
|
||||
|
||||
Factory* CodeAssembler::factory() const { return isolate()->factory(); }
|
||||
|
||||
Zone* CodeAssembler::zone() const { return raw_assembler_->zone(); }
|
||||
Zone* CodeAssembler::zone() const { return raw_assembler()->zone(); }
|
||||
|
||||
RawMachineAssembler* CodeAssembler::raw_assembler() const {
|
||||
return state_->raw_assembler_.get();
|
||||
}
|
||||
|
||||
// The core implementation of Variable is stored through an indirection so
|
||||
// that it can outlive the often block-scoped Variable declarations. This is
|
||||
@ -1058,11 +1067,11 @@ class CodeAssembler::Variable::Impl : public ZoneObject {
|
||||
|
||||
CodeAssembler::Variable::Variable(CodeAssembler* assembler,
|
||||
MachineRepresentation rep)
|
||||
: impl_(new (assembler->zone()) Impl(rep)), assembler_(assembler) {
|
||||
assembler->variables_.insert(impl_);
|
||||
: impl_(new (assembler->zone()) Impl(rep)), state_(assembler->state_) {
|
||||
state_->variables_.insert(impl_);
|
||||
}
|
||||
|
||||
CodeAssembler::Variable::~Variable() { assembler_->variables_.erase(impl_); }
|
||||
CodeAssembler::Variable::~Variable() { state_->variables_.erase(impl_); }
|
||||
|
||||
void CodeAssembler::Variable::Bind(Node* value) { impl_->value_ = value; }
|
||||
|
||||
@ -1081,7 +1090,10 @@ bool CodeAssembler::Variable::IsBound() const {
|
||||
|
||||
CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
|
||||
Variable** vars, CodeAssembler::Label::Type type)
|
||||
: bound_(false), merge_count_(0), assembler_(assembler), label_(nullptr) {
|
||||
: bound_(false),
|
||||
merge_count_(0),
|
||||
state_(assembler->state_),
|
||||
label_(nullptr) {
|
||||
void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
|
||||
label_ = new (buffer)
|
||||
RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
|
||||
@ -1093,7 +1105,7 @@ CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
|
||||
|
||||
void CodeAssembler::Label::MergeVariables() {
|
||||
++merge_count_;
|
||||
for (auto var : assembler_->variables_) {
|
||||
for (auto var : state_->variables_) {
|
||||
size_t count = 0;
|
||||
Node* node = var->value_;
|
||||
if (node != nullptr) {
|
||||
@ -1118,7 +1130,7 @@ void CodeAssembler::Label::MergeVariables() {
|
||||
auto phi = variable_phis_.find(var);
|
||||
if (phi != variable_phis_.end()) {
|
||||
DCHECK_NOT_NULL(phi->second);
|
||||
assembler_->raw_assembler_->AppendPhiInput(phi->second, node);
|
||||
state_->raw_assembler_->AppendPhiInput(phi->second, node);
|
||||
} else {
|
||||
auto i = variable_merges_.find(var);
|
||||
if (i != variable_merges_.end()) {
|
||||
@ -1139,11 +1151,11 @@ void CodeAssembler::Label::MergeVariables() {
|
||||
|
||||
void CodeAssembler::Label::Bind() {
|
||||
DCHECK(!bound_);
|
||||
assembler_->raw_assembler_->Bind(label_);
|
||||
state_->raw_assembler_->Bind(label_);
|
||||
|
||||
// Make sure that all variables that have changed along any path up to this
|
||||
// point are marked as merge variables.
|
||||
for (auto var : assembler_->variables_) {
|
||||
for (auto var : state_->variables_) {
|
||||
Node* shared_value = nullptr;
|
||||
auto i = variable_merges_.find(var);
|
||||
if (i != variable_merges_.end()) {
|
||||
@ -1169,14 +1181,14 @@ void CodeAssembler::Label::Bind() {
|
||||
// into the label--doesn't have a bound value along all of the paths that
|
||||
// have been merged into the label up to this point.
|
||||
DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_);
|
||||
Node* phi = assembler_->raw_assembler_->Phi(
|
||||
Node* phi = state_->raw_assembler_->Phi(
|
||||
var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
|
||||
variable_phis_[var_impl] = phi;
|
||||
}
|
||||
|
||||
// Bind all variables to a merge phi, the common value along all paths or
|
||||
// null.
|
||||
for (auto var : assembler_->variables_) {
|
||||
for (auto var : state_->variables_) {
|
||||
auto i = variable_phis_.find(var);
|
||||
if (i != variable_phis_.end()) {
|
||||
var->value_ = i->second;
|
||||
|
@ -30,6 +30,7 @@ class Zone;
|
||||
namespace compiler {
|
||||
|
||||
class CallDescriptor;
|
||||
class CodeAssemblerState;
|
||||
class Node;
|
||||
class RawMachineAssembler;
|
||||
class RawMachineLabel;
|
||||
@ -173,22 +174,17 @@ class RawMachineLabel;
|
||||
// clients, CodeAssembler also provides an abstraction for creating variables
|
||||
// and enhanced Label functionality to merge variable values along paths where
|
||||
// they have differing values, including loops.
|
||||
//
|
||||
// The CodeAssembler itself is stateless (and instances are expected to be
|
||||
// temporary-scoped and short-lived); all its state is encapsulated into
|
||||
// a CodeAssemblerState instance.
|
||||
class V8_EXPORT_PRIVATE CodeAssembler {
|
||||
public:
|
||||
// Create with CallStub linkage.
|
||||
// |result_size| specifies the number of results returned by the stub.
|
||||
// TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
|
||||
CodeAssembler(Isolate* isolate, Zone* zone,
|
||||
const CallInterfaceDescriptor& descriptor, Code::Flags flags,
|
||||
const char* name, size_t result_size = 1);
|
||||
|
||||
// Create with JSCall linkage.
|
||||
CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count,
|
||||
Code::Flags flags, const char* name);
|
||||
explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
|
||||
|
||||
virtual ~CodeAssembler();
|
||||
|
||||
Handle<Code> GenerateCode();
|
||||
static Handle<Code> GenerateCode(CodeAssemblerState* state);
|
||||
|
||||
bool Is64() const;
|
||||
bool IsFloat64RoundUpSupported() const;
|
||||
@ -207,9 +203,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
|
||||
|
||||
private:
|
||||
friend class CodeAssembler;
|
||||
friend class CodeAssemblerState;
|
||||
class Impl;
|
||||
Impl* impl_;
|
||||
CodeAssembler* assembler_;
|
||||
CodeAssemblerState* state_;
|
||||
};
|
||||
|
||||
typedef ZoneList<Variable*> VariableList;
|
||||
@ -471,17 +468,12 @@ class V8_EXPORT_PRIVATE CodeAssembler {
|
||||
virtual void CallEpilogue();
|
||||
|
||||
private:
|
||||
CodeAssembler(Isolate* isolate, Zone* zone, CallDescriptor* call_descriptor,
|
||||
Code::Flags flags, const char* name);
|
||||
|
||||
Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
|
||||
Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
|
||||
|
||||
std::unique_ptr<RawMachineAssembler> raw_assembler_;
|
||||
Code::Flags flags_;
|
||||
const char* name_;
|
||||
bool code_generated_;
|
||||
ZoneSet<Variable::Impl*> variables_;
|
||||
RawMachineAssembler* raw_assembler() const;
|
||||
|
||||
CodeAssemblerState* state_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
|
||||
};
|
||||
@ -513,7 +505,7 @@ class CodeAssembler::Label {
|
||||
|
||||
bool bound_;
|
||||
size_t merge_count_;
|
||||
CodeAssembler* assembler_;
|
||||
CodeAssemblerState* state_;
|
||||
RawMachineLabel* label_;
|
||||
// Map of variables that need to be merged to their phi nodes (or placeholders
|
||||
// for those phis).
|
||||
@ -523,6 +515,38 @@ class CodeAssembler::Label {
|
||||
std::map<Variable::Impl*, std::vector<Node*>> variable_merges_;
|
||||
};
|
||||
|
||||
class V8_EXPORT_PRIVATE CodeAssemblerState {
|
||||
public:
|
||||
// Create with CallStub linkage.
|
||||
// |result_size| specifies the number of results returned by the stub.
|
||||
// TODO(rmcilroy): move result_size to the CallInterfaceDescriptor.
|
||||
CodeAssemblerState(Isolate* isolate, Zone* zone,
|
||||
const CallInterfaceDescriptor& descriptor,
|
||||
Code::Flags flags, const char* name,
|
||||
size_t result_size = 1);
|
||||
|
||||
// Create with JSCall linkage.
|
||||
CodeAssemblerState(Isolate* isolate, Zone* zone, int parameter_count,
|
||||
Code::Flags flags, const char* name);
|
||||
|
||||
~CodeAssemblerState();
|
||||
|
||||
private:
|
||||
friend class CodeAssembler;
|
||||
|
||||
CodeAssemblerState(Isolate* isolate, Zone* zone,
|
||||
CallDescriptor* call_descriptor, Code::Flags flags,
|
||||
const char* name);
|
||||
|
||||
std::unique_ptr<RawMachineAssembler> raw_assembler_;
|
||||
Code::Flags flags_;
|
||||
const char* name_;
|
||||
bool code_generated_;
|
||||
ZoneSet<CodeAssembler::Variable::Impl*> variables_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CodeAssemblerState);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "src/handles-inl.h"
|
||||
#include "src/objects.h" // For FAA::LoadInternalField impl.
|
||||
|
||||
using v8::internal::CodeStubAssembler;
|
||||
using v8::internal::compiler::Node;
|
||||
|
||||
namespace v8 {
|
||||
@ -19,9 +18,9 @@ namespace internal {
|
||||
FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate)
|
||||
: zone_(isolate->allocator(), ZONE_NAME),
|
||||
isolate_(isolate),
|
||||
assembler_(new CodeStubAssembler(isolate, zone(), 1,
|
||||
Code::ComputeFlags(Code::STUB),
|
||||
"FastAccessorAssembler")),
|
||||
assembler_state_(isolate, zone(), 1, Code::ComputeFlags(Code::STUB),
|
||||
"FastAccessorAssembler"),
|
||||
assembler_(new CodeStubAssembler(&assembler_state_)),
|
||||
state_(kBuilding) {}
|
||||
|
||||
FastAccessorAssembler::~FastAccessorAssembler() { Clear(); }
|
||||
@ -248,7 +247,7 @@ void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id,
|
||||
|
||||
MaybeHandle<Code> FastAccessorAssembler::Build() {
|
||||
CHECK_EQ(kBuilding, state_);
|
||||
Handle<Code> code = assembler_->GenerateCode();
|
||||
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&assembler_state_);
|
||||
state_ = !code.is_null() ? kBuilt : kError;
|
||||
Clear();
|
||||
return code;
|
||||
|
@ -98,6 +98,7 @@ class FastAccessorAssembler {
|
||||
|
||||
Zone zone_;
|
||||
Isolate* isolate_;
|
||||
compiler::CodeAssemblerState assembler_state_;
|
||||
std::unique_ptr<CodeStubAssembler> assembler_;
|
||||
|
||||
// To prevent exposing the RMA internals to the outside world, we'll map
|
||||
|
@ -4,8 +4,9 @@
|
||||
|
||||
#include "src/ic/keyed-store-generic.h"
|
||||
|
||||
#include "src/compiler/code-assembler.h"
|
||||
#include "src/code-stub-assembler.h"
|
||||
#include "src/contexts.h"
|
||||
#include "src/interface-descriptors.h"
|
||||
#include "src/isolate.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -15,6 +16,9 @@ using compiler::Node;
|
||||
|
||||
class KeyedStoreGenericAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
explicit KeyedStoreGenericAssembler(compiler::CodeAssemblerState* state)
|
||||
: CodeStubAssembler(state) {}
|
||||
|
||||
void KeyedStoreGeneric(const StoreICParameters* p,
|
||||
LanguageMode language_mode);
|
||||
|
||||
@ -59,17 +63,23 @@ class KeyedStoreGenericAssembler : public CodeStubAssembler {
|
||||
Node* current_elements_kind, Node* context,
|
||||
ElementsKind packed_kind,
|
||||
ElementsKind packed_kind_2, Label* bailout);
|
||||
|
||||
// Do not add fields, so that this is safe to reinterpret_cast to CSA.
|
||||
};
|
||||
|
||||
void KeyedStoreGenericGenerator::Generate(
|
||||
CodeStubAssembler* assembler, const CodeStubAssembler::StoreICParameters* p,
|
||||
LanguageMode language_mode) {
|
||||
STATIC_ASSERT(sizeof(CodeStubAssembler) ==
|
||||
sizeof(KeyedStoreGenericAssembler));
|
||||
auto assm = reinterpret_cast<KeyedStoreGenericAssembler*>(assembler);
|
||||
assm->KeyedStoreGeneric(p, language_mode);
|
||||
void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
|
||||
LanguageMode language_mode) {
|
||||
typedef StoreWithVectorDescriptor Descriptor;
|
||||
KeyedStoreGenericAssembler assembler(state);
|
||||
|
||||
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
|
||||
Node* name = assembler.Parameter(Descriptor::kName);
|
||||
Node* value = assembler.Parameter(Descriptor::kValue);
|
||||
Node* slot = assembler.Parameter(Descriptor::kSlot);
|
||||
Node* vector = assembler.Parameter(Descriptor::kVector);
|
||||
Node* context = assembler.Parameter(Descriptor::kContext);
|
||||
|
||||
CodeStubAssembler::StoreICParameters p(context, receiver, name, value, slot,
|
||||
vector);
|
||||
assembler.KeyedStoreGeneric(&p, language_mode);
|
||||
}
|
||||
|
||||
void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
|
||||
|
@ -5,15 +5,18 @@
|
||||
#ifndef V8_SRC_IC_KEYED_STORE_GENERIC_H_
|
||||
#define V8_SRC_IC_KEYED_STORE_GENERIC_H_
|
||||
|
||||
#include "src/code-stub-assembler.h"
|
||||
#include "src/globals.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
namespace compiler {
|
||||
class CodeAssemblerState;
|
||||
}
|
||||
|
||||
class KeyedStoreGenericGenerator {
|
||||
public:
|
||||
static void Generate(CodeStubAssembler* assembler,
|
||||
const CodeStubAssembler::StoreICParameters* p,
|
||||
static void Generate(compiler::CodeAssemblerState* state,
|
||||
LanguageMode language_mode);
|
||||
};
|
||||
|
||||
|
@ -157,8 +157,7 @@ class CallDescriptors {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class CallInterfaceDescriptor {
|
||||
class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
|
||||
public:
|
||||
CallInterfaceDescriptor() : data_(NULL) {}
|
||||
virtual ~CallInterfaceDescriptor() {}
|
||||
@ -775,7 +774,8 @@ class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
|
||||
static const Register KeyRegister();
|
||||
};
|
||||
|
||||
class InterpreterDispatchDescriptor : public CallInterfaceDescriptor {
|
||||
class V8_EXPORT_PRIVATE InterpreterDispatchDescriptor
|
||||
: public CallInterfaceDescriptor {
|
||||
public:
|
||||
DEFINE_PARAMETERS(kAccumulator, kBytecodeOffset, kBytecodeArray,
|
||||
kDispatchTable)
|
||||
|
@ -20,15 +20,13 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
using compiler::CodeAssemblerState;
|
||||
using compiler::Node;
|
||||
|
||||
InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
|
||||
InterpreterAssembler::InterpreterAssembler(CodeAssemblerState* state,
|
||||
Bytecode bytecode,
|
||||
OperandScale operand_scale)
|
||||
: CodeStubAssembler(isolate, zone, InterpreterDispatchDescriptor(isolate),
|
||||
Code::ComputeFlags(Code::BYTECODE_HANDLER),
|
||||
Bytecodes::ToString(bytecode),
|
||||
Bytecodes::ReturnCount(bytecode)),
|
||||
: CodeStubAssembler(state),
|
||||
bytecode_(bytecode),
|
||||
operand_scale_(operand_scale),
|
||||
bytecode_offset_(this, MachineType::PointerRepresentation()),
|
||||
|
@ -20,7 +20,7 @@ namespace interpreter {
|
||||
|
||||
class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler {
|
||||
public:
|
||||
InterpreterAssembler(Isolate* isolate, Zone* zone, Bytecode bytecode,
|
||||
InterpreterAssembler(compiler::CodeAssemblerState* state, Bytecode bytecode,
|
||||
OperandScale operand_scale);
|
||||
virtual ~InterpreterAssembler();
|
||||
|
||||
|
@ -76,10 +76,16 @@ void Interpreter::Initialize() {
|
||||
#define GENERATE_CODE(Name, ...) \
|
||||
{ \
|
||||
if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \
|
||||
InterpreterAssembler assembler(isolate_, &zone, Bytecode::k##Name, \
|
||||
InterpreterDispatchDescriptor descriptor(isolate_); \
|
||||
compiler::CodeAssemblerState state( \
|
||||
isolate_, &zone, descriptor, \
|
||||
Code::ComputeFlags(Code::BYTECODE_HANDLER), \
|
||||
Bytecodes::ToString(Bytecode::k##Name), \
|
||||
Bytecodes::ReturnCount(Bytecode::k##Name)); \
|
||||
InterpreterAssembler assembler(&state, Bytecode::k##Name, \
|
||||
operand_scale); \
|
||||
Do##Name(&assembler); \
|
||||
Handle<Code> code = assembler.GenerateCode(); \
|
||||
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); \
|
||||
size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale); \
|
||||
dispatch_table_[index] = code->entry(); \
|
||||
TraceCodegen(code); \
|
||||
|
@ -1028,7 +1028,8 @@ class Isolate {
|
||||
// Returns true if array is the initial array prototype in any native context.
|
||||
bool IsAnyInitialArrayPrototype(Handle<JSArray> array);
|
||||
|
||||
CallInterfaceDescriptorData* call_descriptor_data(int index);
|
||||
V8_EXPORT_PRIVATE CallInterfaceDescriptorData* call_descriptor_data(
|
||||
int index);
|
||||
|
||||
AccessCompilerData* access_compiler_data() { return access_compiler_data_; }
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/compiler/code-assembler.h"
|
||||
#include "src/handles.h"
|
||||
#include "src/interface-descriptors.h"
|
||||
#include "src/isolate.h"
|
||||
@ -11,51 +12,43 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
class ZoneHolder {
|
||||
class CodeAssemblerTester {
|
||||
public:
|
||||
explicit ZoneHolder(Isolate* isolate)
|
||||
: held_zone_(isolate->allocator(), ZONE_NAME) {}
|
||||
Zone* held_zone() { return &held_zone_; }
|
||||
|
||||
private:
|
||||
Zone held_zone_;
|
||||
};
|
||||
|
||||
// Inherit from ZoneHolder in order to create a zone that can be passed to
|
||||
// CodeAssembler base class constructor.
|
||||
template <typename CodeAssemblerT>
|
||||
class CodeAssemblerTesterImpl : private ZoneHolder, public CodeAssemblerT {
|
||||
public:
|
||||
// Test generating code for a stub.
|
||||
CodeAssemblerTesterImpl(Isolate* isolate,
|
||||
const CallInterfaceDescriptor& descriptor)
|
||||
: ZoneHolder(isolate),
|
||||
CodeAssemblerT(isolate, ZoneHolder::held_zone(), descriptor,
|
||||
Code::ComputeFlags(Code::STUB), "test"),
|
||||
scope_(isolate) {}
|
||||
// Test generating code for a stub. Assumes VoidDescriptor call interface.
|
||||
explicit CodeAssemblerTester(Isolate* isolate)
|
||||
: zone_(isolate->allocator(), ZONE_NAME),
|
||||
scope_(isolate),
|
||||
state_(isolate, &zone_, VoidDescriptor(isolate),
|
||||
Code::ComputeFlags(Code::STUB), "test") {}
|
||||
|
||||
// Test generating code for a JS function (e.g. builtins).
|
||||
CodeAssemblerTesterImpl(Isolate* isolate, int parameter_count,
|
||||
Code::Kind kind = Code::BUILTIN)
|
||||
: ZoneHolder(isolate),
|
||||
CodeAssemblerT(isolate, ZoneHolder::held_zone(), parameter_count,
|
||||
Code::ComputeFlags(kind), "test"),
|
||||
scope_(isolate) {}
|
||||
CodeAssemblerTester(Isolate* isolate, int parameter_count,
|
||||
Code::Kind kind = Code::BUILTIN)
|
||||
: zone_(isolate->allocator(), ZONE_NAME),
|
||||
scope_(isolate),
|
||||
state_(isolate, &zone_, parameter_count, Code::ComputeFlags(kind),
|
||||
"test") {}
|
||||
|
||||
// This constructor is intended to be used for creating code objects with
|
||||
// specific flags.
|
||||
CodeAssemblerTesterImpl(Isolate* isolate, Code::Flags flags)
|
||||
: ZoneHolder(isolate),
|
||||
CodeAssemblerT(isolate, ZoneHolder::held_zone(), 0, flags, "test"),
|
||||
scope_(isolate) {}
|
||||
CodeAssemblerTester(Isolate* isolate, Code::Flags flags)
|
||||
: zone_(isolate->allocator(), ZONE_NAME),
|
||||
scope_(isolate),
|
||||
state_(isolate, &zone_, 0, flags, "test") {}
|
||||
|
||||
CodeAssemblerState* state() { return &state_; }
|
||||
|
||||
Handle<Code> GenerateCode() { return CodeAssembler::GenerateCode(&state_); }
|
||||
|
||||
Handle<Code> GenerateCodeCloseAndEscape() {
|
||||
return scope_.CloseAndEscape(CodeAssemblerT::GenerateCode());
|
||||
return scope_.CloseAndEscape(CodeAssembler::GenerateCode(&state_));
|
||||
}
|
||||
|
||||
private:
|
||||
Zone zone_;
|
||||
HandleScope scope_;
|
||||
LocalContext context_;
|
||||
CodeAssemblerState state_;
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -46,9 +46,7 @@ FunctionTester::FunctionTester(Handle<Code> code, int param_count)
|
||||
function->ReplaceCode(*code);
|
||||
}
|
||||
|
||||
FunctionTester::FunctionTester(const CallInterfaceDescriptor& descriptor,
|
||||
Handle<Code> code)
|
||||
: FunctionTester(code, descriptor.GetParameterCount()) {}
|
||||
FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {}
|
||||
|
||||
MaybeHandle<Object> FunctionTester::Call() {
|
||||
return Execution::Call(isolate, function, undefined(), 0, nullptr);
|
||||
|
@ -26,7 +26,8 @@ class FunctionTester : public InitializedHandleScope {
|
||||
|
||||
FunctionTester(Handle<Code> code, int param_count);
|
||||
|
||||
FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code);
|
||||
// Assumes VoidDescriptor call interface.
|
||||
explicit FunctionTester(Handle<Code> code);
|
||||
|
||||
Isolate* isolate;
|
||||
Handle<JSFunction> function;
|
||||
|
@ -12,11 +12,9 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
typedef CodeAssemblerTesterImpl<CodeAssembler> CodeAssemblerTester;
|
||||
|
||||
namespace {
|
||||
|
||||
Node* SmiTag(CodeAssemblerTester& m, Node* value) {
|
||||
Node* SmiTag(CodeAssembler& m, Node* value) {
|
||||
int32_t constant_value;
|
||||
if (m.ToInt32Constant(value, constant_value) &&
|
||||
Smi::IsValid(constant_value)) {
|
||||
@ -25,11 +23,11 @@ Node* SmiTag(CodeAssemblerTester& m, Node* value) {
|
||||
return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize));
|
||||
}
|
||||
|
||||
Node* UndefinedConstant(CodeAssemblerTester& m) {
|
||||
Node* UndefinedConstant(CodeAssembler& m) {
|
||||
return m.LoadRoot(Heap::kUndefinedValueRootIndex);
|
||||
}
|
||||
|
||||
Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset,
|
||||
Node* LoadObjectField(CodeAssembler& m, Node* object, int offset,
|
||||
MachineType rep = MachineType::AnyTagged()) {
|
||||
return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag));
|
||||
}
|
||||
@ -38,23 +36,23 @@ Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset,
|
||||
|
||||
TEST(SimpleSmiReturn) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
m.Return(SmiTag(m, m.Int32Constant(37)));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(SimpleIntPtrReturn) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
int test;
|
||||
m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(reinterpret_cast<intptr_t>(&test),
|
||||
reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
|
||||
@ -62,65 +60,65 @@ TEST(SimpleIntPtrReturn) {
|
||||
|
||||
TEST(SimpleDoubleReturn) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
m.Return(m.NumberConstant(0.5));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(SimpleCallRuntime1Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
|
||||
Node* b = SmiTag(m, m.Int32Constant(0));
|
||||
m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(SimpleTailCallRuntime1Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
|
||||
Node* b = SmiTag(m, m.Int32Constant(0));
|
||||
m.TailCallRuntime(Runtime::kNumberToSmi, context, b);
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(SimpleCallRuntime2Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
|
||||
Node* a = SmiTag(m, m.Int32Constant(2));
|
||||
Node* b = SmiTag(m, m.Int32Constant(4));
|
||||
m.Return(m.CallRuntime(Runtime::kAdd, context, a, b));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(SimpleTailCallRuntime2Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
|
||||
Node* a = SmiTag(m, m.Int32Constant(2));
|
||||
Node* b = SmiTag(m, m.Int32Constant(4));
|
||||
m.TailCallRuntime(Runtime::kAdd, context, a, b);
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
@ -144,7 +142,8 @@ Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) {
|
||||
TEST(SimpleCallJSFunction0Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 1;
|
||||
CodeAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeAssembler m(data.state());
|
||||
{
|
||||
Node* function = m.Parameter(0);
|
||||
Node* context = m.Parameter(kNumParams + 2);
|
||||
@ -155,7 +154,7 @@ TEST(SimpleCallJSFunction0Arg) {
|
||||
Node* result = m.CallJS(callable, context, function, receiver);
|
||||
m.Return(result);
|
||||
}
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
|
||||
@ -166,7 +165,8 @@ TEST(SimpleCallJSFunction0Arg) {
|
||||
TEST(SimpleCallJSFunction1Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeAssembler m(data.state());
|
||||
{
|
||||
Node* function = m.Parameter(0);
|
||||
Node* context = m.Parameter(1);
|
||||
@ -178,7 +178,7 @@ TEST(SimpleCallJSFunction1Arg) {
|
||||
Node* result = m.CallJS(callable, context, function, receiver, a);
|
||||
m.Return(result);
|
||||
}
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
|
||||
@ -189,7 +189,8 @@ TEST(SimpleCallJSFunction1Arg) {
|
||||
TEST(SimpleCallJSFunction2Arg) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeAssembler m(data.state());
|
||||
{
|
||||
Node* function = m.Parameter(0);
|
||||
Node* context = m.Parameter(1);
|
||||
@ -202,7 +203,7 @@ TEST(SimpleCallJSFunction2Arg) {
|
||||
Node* result = m.CallJS(callable, context, function, receiver, a, b);
|
||||
m.Return(result);
|
||||
}
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
|
||||
@ -212,8 +213,8 @@ TEST(SimpleCallJSFunction2Arg) {
|
||||
|
||||
TEST(VariableMerge1) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
|
||||
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
|
||||
Node* temp = m.Int32Constant(0);
|
||||
@ -231,8 +232,8 @@ TEST(VariableMerge1) {
|
||||
|
||||
TEST(VariableMerge2) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
|
||||
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
|
||||
Node* temp = m.Int32Constant(0);
|
||||
@ -252,8 +253,8 @@ TEST(VariableMerge2) {
|
||||
|
||||
TEST(VariableMerge3) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
|
||||
CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
|
||||
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
|
||||
@ -277,8 +278,8 @@ TEST(VariableMerge3) {
|
||||
|
||||
TEST(VariableMergeBindFirst) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
|
||||
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
|
||||
Node* temp = m.Int32Constant(0);
|
||||
@ -303,8 +304,8 @@ TEST(VariableMergeBindFirst) {
|
||||
|
||||
TEST(VariableMergeSwitch) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
|
||||
CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
|
||||
CodeStubAssembler::Label* labels[] = {&l1, &l2};
|
||||
@ -325,20 +326,20 @@ TEST(VariableMergeSwitch) {
|
||||
|
||||
TEST(SplitEdgeBranchMerge) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Label l1(&m), merge(&m);
|
||||
m.Branch(m.Int32Constant(1), &l1, &merge);
|
||||
m.Bind(&l1);
|
||||
m.Goto(&merge);
|
||||
m.Bind(&merge);
|
||||
USE(m.GenerateCode());
|
||||
USE(data.GenerateCode());
|
||||
}
|
||||
|
||||
TEST(SplitEdgeSwitchMerge) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m);
|
||||
CodeStubAssembler::Label* labels[] = {&l1, &l2};
|
||||
int32_t values[] = {1, 2};
|
||||
@ -350,13 +351,13 @@ TEST(SplitEdgeSwitchMerge) {
|
||||
m.Bind(&l2);
|
||||
m.Goto(&default_label);
|
||||
m.Bind(&default_label);
|
||||
USE(m.GenerateCode());
|
||||
USE(data.GenerateCode());
|
||||
}
|
||||
|
||||
TEST(TestToConstant) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
int32_t value32;
|
||||
int64_t value64;
|
||||
Node* a = m.Int32Constant(5);
|
||||
@ -385,8 +386,8 @@ TEST(DeferredCodePhiHints) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
Label block1(&m, Label::kDeferred);
|
||||
m.Goto(&block1);
|
||||
m.Bind(&block1);
|
||||
@ -402,15 +403,15 @@ TEST(DeferredCodePhiHints) {
|
||||
m.Goto(&loop);
|
||||
}
|
||||
}
|
||||
CHECK(!m.GenerateCode().is_null());
|
||||
CHECK(!data.GenerateCode().is_null());
|
||||
}
|
||||
|
||||
TEST(TestOutOfScopeVariable) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeAssembler m(data.state());
|
||||
Label block1(&m);
|
||||
Label block2(&m);
|
||||
Label block3(&m);
|
||||
@ -431,7 +432,7 @@ TEST(TestOutOfScopeVariable) {
|
||||
m.Goto(&block1);
|
||||
}
|
||||
m.Bind(&block1);
|
||||
CHECK(!m.GenerateCode().is_null());
|
||||
CHECK(!data.GenerateCode().is_null());
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -14,48 +14,46 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
using compiler::CodeAssemblerTester;
|
||||
using compiler::FunctionTester;
|
||||
using compiler::Node;
|
||||
|
||||
typedef compiler::CodeAssemblerTesterImpl<CodeStubAssembler>
|
||||
CodeStubAssemblerTester;
|
||||
|
||||
TEST(FixedArrayAccessSmiIndex) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeStubAssembler m(data.state());
|
||||
Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
|
||||
array->set(4, Smi::FromInt(733));
|
||||
m.Return(m.LoadFixedArrayElement(m.HeapConstant(array),
|
||||
m.SmiTag(m.Int32Constant(4)), 0,
|
||||
CodeStubAssembler::SMI_PARAMETERS));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(LoadHeapNumberValue) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeStubAssembler m(data.state());
|
||||
Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
|
||||
m.Return(m.SmiTag(
|
||||
m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number)))));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
}
|
||||
|
||||
TEST(LoadInstanceType) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeStubAssembler m(data.state());
|
||||
Handle<HeapObject> undefined = isolate->factory()->undefined_value();
|
||||
m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined))));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
CHECK_EQ(InstanceType::ODDBALL_TYPE,
|
||||
Handle<Smi>::cast(result.ToHandleChecked())->value());
|
||||
@ -63,14 +61,14 @@ TEST(LoadInstanceType) {
|
||||
|
||||
TEST(DecodeWordFromWord32) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
class TestBitField : public BitField<unsigned, 3, 3> {};
|
||||
m.Return(
|
||||
m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2f))));
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
FunctionTester ft(descriptor, code);
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code);
|
||||
MaybeHandle<Object> result = ft.Call();
|
||||
// value = 00101111
|
||||
// mask = 00111000
|
||||
@ -81,11 +79,12 @@ TEST(DecodeWordFromWord32) {
|
||||
TEST(JSFunction) {
|
||||
const int kNumParams = 3; // Receiver, left, right.
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
m.Return(m.SmiFromWord32(m.Int32Add(m.SmiToWord32(m.Parameter(1)),
|
||||
m.SmiToWord32(m.Parameter(2)))));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(),
|
||||
@ -97,11 +96,12 @@ TEST(JSFunction) {
|
||||
TEST(ComputeIntegerHash) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 2;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
m.Return(m.SmiFromWord32(m.ComputeIntegerHash(
|
||||
m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1)))));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Smi> hash_seed = isolate->factory()->hash_seed();
|
||||
@ -123,10 +123,11 @@ TEST(ComputeIntegerHash) {
|
||||
TEST(ToString) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 1;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
m.Return(m.ToString(m.Parameter(kNumParams + 2), m.Parameter(0)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<FixedArray> test_cases = isolate->factory()->NewFixedArray(5);
|
||||
@ -179,10 +180,11 @@ TEST(ToString) {
|
||||
TEST(FlattenString) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 1;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
m.Return(m.FlattenString(m.Parameter(0)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<FixedArray> test_cases(isolate->factory()->NewFixedArray(4));
|
||||
@ -222,7 +224,8 @@ TEST(TryToName) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 3;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
enum Result { kKeyIsIndex, kKeyIsUnique, kBailout };
|
||||
{
|
||||
@ -261,7 +264,7 @@ TEST(TryToName) {
|
||||
m.Return(m.BooleanConstant(false));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate);
|
||||
@ -352,14 +355,15 @@ void TestEntryToIndex() {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 1;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
{
|
||||
Node* entry = m.SmiUntag(m.Parameter(0));
|
||||
Node* result = m.EntryToIndex<Dictionary>(entry);
|
||||
m.Return(m.SmiTag(result));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
// Test a wide range of entries but staying linear in the first 100 entries.
|
||||
@ -385,7 +389,8 @@ void TestNameDictionaryLookup() {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
enum Result { kFound, kNotFound };
|
||||
{
|
||||
@ -419,7 +424,7 @@ void TestNameDictionaryLookup() {
|
||||
m.Return(m.BooleanConstant(false));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
|
||||
@ -491,7 +496,8 @@ void TestNumberDictionaryLookup() {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
enum Result { kFound, kNotFound };
|
||||
{
|
||||
@ -525,7 +531,7 @@ void TestNumberDictionaryLookup() {
|
||||
m.Return(m.BooleanConstant(false));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
|
||||
@ -628,7 +634,8 @@ TEST(TryHasOwnProperty) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
enum Result { kFound, kNotFound, kBailout };
|
||||
{
|
||||
@ -666,7 +673,7 @@ TEST(TryHasOwnProperty) {
|
||||
m.Return(m.BooleanConstant(false));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
|
||||
@ -814,7 +821,8 @@ TEST(TryGetOwnProperty) {
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
const int kNumParams = 2;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
Handle<Symbol> not_found_symbol = factory->NewSymbol();
|
||||
Handle<Symbol> bailout_symbol = factory->NewSymbol();
|
||||
@ -843,7 +851,7 @@ TEST(TryGetOwnProperty) {
|
||||
m.Return(m.HeapConstant(bailout_symbol));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Name> deleted_property_name =
|
||||
@ -1030,7 +1038,8 @@ TEST(TryLookupElement) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 3;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
enum Result { kFound, kNotFound, kBailout };
|
||||
{
|
||||
@ -1068,7 +1077,7 @@ TEST(TryLookupElement) {
|
||||
m.Return(m.BooleanConstant(false));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
@ -1216,8 +1225,8 @@ TEST(DeferredCodePhiHints) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeStubAssembler m(data.state());
|
||||
Label block1(&m, Label::kDeferred);
|
||||
m.Goto(&block1);
|
||||
m.Bind(&block1);
|
||||
@ -1233,15 +1242,15 @@ TEST(DeferredCodePhiHints) {
|
||||
m.Goto(&loop);
|
||||
}
|
||||
}
|
||||
CHECK(!m.GenerateCode().is_null());
|
||||
CHECK(!data.GenerateCode().is_null());
|
||||
}
|
||||
|
||||
TEST(TestOutOfScopeVariable) {
|
||||
typedef CodeStubAssembler::Label Label;
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
VoidDescriptor descriptor(isolate);
|
||||
CodeStubAssemblerTester m(isolate, descriptor);
|
||||
CodeAssemblerTester data(isolate);
|
||||
CodeStubAssembler m(data.state());
|
||||
Label block1(&m);
|
||||
Label block2(&m);
|
||||
Label block3(&m);
|
||||
@ -1262,7 +1271,7 @@ TEST(TestOutOfScopeVariable) {
|
||||
m.Goto(&block1);
|
||||
}
|
||||
m.Bind(&block1);
|
||||
CHECK(!m.GenerateCode().is_null());
|
||||
CHECK(!data.GenerateCode().is_null());
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -1270,7 +1279,8 @@ namespace {
|
||||
void TestStubCacheOffsetCalculation(StubCache::Table table) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 2;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
{
|
||||
Node* name = m.Parameter(0);
|
||||
@ -1286,7 +1296,7 @@ void TestStubCacheOffsetCalculation(StubCache::Table table) {
|
||||
m.Return(m.SmiFromWord32(result));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Factory* factory = isolate->factory();
|
||||
@ -1354,9 +1364,10 @@ namespace {
|
||||
|
||||
Handle<Code> CreateCodeWithFlags(Code::Flags flags) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
CodeStubAssemblerTester m(isolate, flags);
|
||||
CodeAssemblerTester data(isolate, flags);
|
||||
CodeStubAssembler m(data.state());
|
||||
m.Return(m.UndefinedConstant());
|
||||
return m.GenerateCodeCloseAndEscape();
|
||||
return data.GenerateCodeCloseAndEscape();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -1366,7 +1377,8 @@ TEST(TryProbeStubCache) {
|
||||
typedef CodeStubAssembler::Variable Variable;
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 3;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
Code::Kind ic_kind = Code::LOAD_IC;
|
||||
StubCache stub_cache(isolate, ic_kind);
|
||||
@ -1399,7 +1411,7 @@ TEST(TryProbeStubCache) {
|
||||
m.Return(m.BooleanConstant(false));
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
std::vector<Handle<Name>> names;
|
||||
@ -1510,8 +1522,8 @@ TEST(GotoIfException) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 1;
|
||||
// Emulate TFJ builtin
|
||||
CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
|
||||
Node* to_string_tag =
|
||||
@ -1527,13 +1539,13 @@ TEST(GotoIfException) {
|
||||
m.Bind(&exception_handler);
|
||||
m.Return(exception.value());
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
FunctionTester ft(code, kNumParams);
|
||||
Handle<Object> result = ft.Call().ToHandleChecked();
|
||||
|
||||
// Should be a TypeError
|
||||
// Should be a TypeError.
|
||||
CHECK(result->IsJSObject());
|
||||
|
||||
Handle<Object> constructor =
|
||||
@ -1549,8 +1561,8 @@ TEST(GotoIfExceptionMultiple) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4; // receiver, first, second, third
|
||||
// Emulate TFJ builtin
|
||||
CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
|
||||
Node* first_value = m.Parameter(0);
|
||||
@ -1592,25 +1604,25 @@ TEST(GotoIfExceptionMultiple) {
|
||||
m.Bind(&exception_handler3);
|
||||
m.Return(error.value());
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Object> result;
|
||||
// First handler does not throw, returns result of first value
|
||||
// First handler does not throw, returns result of first value.
|
||||
result = ft.Call(isolate->factory()->undefined_value(),
|
||||
isolate->factory()->to_string_tag_symbol())
|
||||
.ToHandleChecked();
|
||||
CHECK(String::cast(*result)->IsOneByteEqualTo(OneByteVector("undefined")));
|
||||
|
||||
// First handler returns a number
|
||||
// First handler returns a number.
|
||||
result = ft.Call(isolate->factory()->to_string_tag_symbol(),
|
||||
isolate->factory()->undefined_value())
|
||||
.ToHandleChecked();
|
||||
CHECK_EQ(7, Smi::cast(*result)->value());
|
||||
|
||||
// First handler throws, second handler returns a number
|
||||
// First handler throws, second handler returns a number.
|
||||
result = ft.Call(isolate->factory()->to_string_tag_symbol(),
|
||||
isolate->factory()->to_primitive_symbol())
|
||||
.ToHandleChecked();
|
||||
@ -1623,7 +1635,7 @@ TEST(GotoIfExceptionMultiple) {
|
||||
isolate->factory()->unscopables_symbol())
|
||||
.ToHandleChecked();
|
||||
|
||||
// Should be a TypeError
|
||||
// Should be a TypeError.
|
||||
CHECK(result->IsJSObject());
|
||||
|
||||
Handle<Object> constructor =
|
||||
@ -1638,7 +1650,8 @@ TEST(AllocateJSObjectFromMap) {
|
||||
Factory* factory = isolate->factory();
|
||||
|
||||
const int kNumParams = 3;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
{
|
||||
Node* map = m.Parameter(0);
|
||||
@ -1650,7 +1663,7 @@ TEST(AllocateJSObjectFromMap) {
|
||||
m.Return(result);
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
Handle<Map> maps[] = {
|
||||
@ -1701,7 +1714,8 @@ TEST(AllocateNameDictionary) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 1;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
{
|
||||
Node* capacity = m.Parameter(0);
|
||||
@ -1709,7 +1723,7 @@ TEST(AllocateNameDictionary) {
|
||||
m.Return(result);
|
||||
}
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
||||
{
|
||||
@ -1729,16 +1743,17 @@ TEST(PopAndReturnConstant) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
const int kNumProgramaticParams = 2;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams);
|
||||
const int kNumProgrammaticParams = 2;
|
||||
CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
// Call a function that return |kNumProgramaticParams| parameters in addition
|
||||
// to those specified by the static descriptor. |kNumProgramaticParams| is
|
||||
// specified as a constant.
|
||||
m.PopAndReturn(m.Int32Constant(kNumProgramaticParams),
|
||||
m.PopAndReturn(m.Int32Constant(kNumProgrammaticParams),
|
||||
m.SmiConstant(Smi::FromInt(1234)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
FunctionTester ft(code, kNumParams);
|
||||
@ -1757,8 +1772,9 @@ TEST(PopAndReturnVariable) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
const int kNumProgramaticParams = 2;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams);
|
||||
const int kNumProgrammaticParams = 2;
|
||||
CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
// Call a function that return |kNumProgramaticParams| parameters in addition
|
||||
// to those specified by the static descriptor. |kNumProgramaticParams| is
|
||||
@ -1766,7 +1782,7 @@ TEST(PopAndReturnVariable) {
|
||||
// a constant.
|
||||
m.PopAndReturn(m.SmiUntag(m.Parameter(1)), m.SmiConstant(Smi::FromInt(1234)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
FunctionTester ft(code, kNumParams);
|
||||
@ -1775,7 +1791,7 @@ TEST(PopAndReturnVariable) {
|
||||
result = ft.Call(isolate->factory()->undefined_value(),
|
||||
Handle<Smi>(Smi::FromInt(1234), isolate),
|
||||
isolate->factory()->undefined_value(),
|
||||
Handle<Smi>(Smi::FromInt(kNumProgramaticParams), isolate))
|
||||
Handle<Smi>(Smi::FromInt(kNumProgrammaticParams), isolate))
|
||||
.ToHandleChecked();
|
||||
CHECK_EQ(1234, Handle<Smi>::cast(result)->value());
|
||||
}
|
||||
@ -1784,7 +1800,9 @@ TEST(PopAndReturnVariable) {
|
||||
TEST(OneToTwoByteStringCopy) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
CodeStubAssemblerTester m(isolate, 2);
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
m.CopyStringCharacters(
|
||||
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
|
||||
@ -1793,7 +1811,7 @@ TEST(OneToTwoByteStringCopy) {
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
m.Return(m.SmiConstant(Smi::FromInt(0)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
|
||||
@ -1818,7 +1836,9 @@ TEST(OneToTwoByteStringCopy) {
|
||||
TEST(OneToOneByteStringCopy) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
CodeStubAssemblerTester m(isolate, 2);
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
m.CopyStringCharacters(
|
||||
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
|
||||
@ -1827,7 +1847,7 @@ TEST(OneToOneByteStringCopy) {
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
m.Return(m.SmiConstant(Smi::FromInt(0)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
|
||||
@ -1852,7 +1872,9 @@ TEST(OneToOneByteStringCopy) {
|
||||
TEST(OneToOneByteStringCopyNonZeroStart) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
CodeStubAssemblerTester m(isolate, 2);
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
m.CopyStringCharacters(
|
||||
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
|
||||
@ -1861,7 +1883,7 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
m.Return(m.SmiConstant(Smi::FromInt(0)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
|
||||
@ -1883,7 +1905,9 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
|
||||
TEST(TwoToTwoByteStringCopy) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
CodeStubAssemblerTester m(isolate, 2);
|
||||
const int kNumParams = 2;
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
m.CopyStringCharacters(
|
||||
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
|
||||
@ -1892,7 +1916,7 @@ TEST(TwoToTwoByteStringCopy) {
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
m.Return(m.SmiConstant(Smi::FromInt(0)));
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
uc16 array1[] = {2000, 2001, 2002, 2003, 2004};
|
||||
@ -1921,7 +1945,8 @@ TEST(Arguments) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
CodeStubArguments arguments(&m, m.IntPtrConstant(3));
|
||||
|
||||
@ -1934,7 +1959,7 @@ TEST(Arguments) {
|
||||
|
||||
m.Return(arguments.GetReceiver());
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
FunctionTester ft(code, kNumParams);
|
||||
@ -1950,13 +1975,13 @@ TEST(ArgumentsForEach) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 4;
|
||||
CodeStubAssemblerTester m(isolate, kNumParams);
|
||||
CodeAssemblerTester data(isolate, kNumParams);
|
||||
CodeStubAssembler m(data.state());
|
||||
|
||||
CodeStubArguments arguments(&m, m.IntPtrConstant(3));
|
||||
|
||||
CodeStubAssemblerTester::Variable sum(&m,
|
||||
MachineType::PointerRepresentation());
|
||||
CodeStubAssemblerTester::VariableList list({&sum}, m.zone());
|
||||
CodeStubAssembler::Variable sum(&m, MachineType::PointerRepresentation());
|
||||
CodeStubAssembler::VariableList list({&sum}, m.zone());
|
||||
|
||||
sum.Bind(m.IntPtrConstant(0));
|
||||
|
||||
@ -1966,7 +1991,7 @@ TEST(ArgumentsForEach) {
|
||||
|
||||
m.Return(sum.value());
|
||||
|
||||
Handle<Code> code = m.GenerateCode();
|
||||
Handle<Code> code = data.GenerateCode();
|
||||
CHECK(!code.is_null());
|
||||
|
||||
FunctionTester ft(code, kNumParams);
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "test/unittests/interpreter/interpreter-assembler-unittest.h"
|
||||
|
||||
#include "src/code-factory.h"
|
||||
#include "src/compiler/graph.h"
|
||||
#include "src/compiler/node.h"
|
||||
#include "src/interface-descriptors.h"
|
||||
#include "src/isolate.h"
|
||||
@ -21,6 +20,14 @@ using namespace compiler;
|
||||
|
||||
namespace interpreter {
|
||||
|
||||
InterpreterAssemblerTestState::InterpreterAssemblerTestState(
|
||||
InterpreterAssemblerTest* test, Bytecode bytecode)
|
||||
: compiler::CodeAssemblerState(
|
||||
test->isolate(), test->zone(),
|
||||
InterpreterDispatchDescriptor(test->isolate()),
|
||||
Code::ComputeFlags(Code::BYTECODE_HANDLER),
|
||||
Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode)) {}
|
||||
|
||||
const interpreter::Bytecode kBytecodes[] = {
|
||||
#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
|
||||
BYTECODE_LIST(DEFINE_BYTECODE)
|
||||
@ -298,7 +305,8 @@ InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedOperand(
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* tail_call_node = m.Dispatch();
|
||||
|
||||
OperandScale operand_scale = OperandScale::kSingle;
|
||||
@ -364,7 +372,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
if (!interpreter::Bytecodes::IsJump(bytecode)) return;
|
||||
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
|
||||
|
||||
Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
|
||||
@ -398,7 +407,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
|
||||
OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
TRACED_FOREACH(interpreter::OperandScale, operand_scale, kOperandScales) {
|
||||
InterpreterAssemblerForTest m(this, bytecode, operand_scale);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode, operand_scale);
|
||||
int number_of_operands =
|
||||
interpreter::Bytecodes::NumberOfOperands(bytecode);
|
||||
for (int i = 0; i < number_of_operands; i++) {
|
||||
@ -463,7 +473,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
|
||||
continue;
|
||||
}
|
||||
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
// Should be incoming accumulator if not set.
|
||||
EXPECT_THAT(m.GetAccumulator(),
|
||||
IsParameter(InterpreterDispatchDescriptor::kAccumulator));
|
||||
@ -485,7 +496,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
EXPECT_THAT(
|
||||
m.GetContext(),
|
||||
m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
|
||||
@ -496,7 +508,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* reg_index_node = m.IntPtrConstant(44);
|
||||
Node* reg_location_node = m.RegisterLocation(reg_index_node);
|
||||
EXPECT_THAT(reg_location_node,
|
||||
@ -508,7 +521,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* reg_index_node = m.IntPtrConstant(44);
|
||||
Node* load_reg_node = m.LoadRegister(reg_index_node);
|
||||
EXPECT_THAT(load_reg_node,
|
||||
@ -520,7 +534,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* store_value = m.Int32Constant(0xdeadbeef);
|
||||
Node* reg_index_node = m.IntPtrConstant(44);
|
||||
Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
|
||||
@ -536,7 +551,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* value = m.Int32Constant(44);
|
||||
EXPECT_THAT(m.SmiTag(value), IsBitcastWordToTaggedSigned(IsIntPtrConstant(
|
||||
static_cast<intptr_t>(44)
|
||||
@ -549,7 +565,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* a = m.Int32Constant(0);
|
||||
Node* b = m.Int32Constant(1);
|
||||
Node* add = m.IntPtrAdd(a, b);
|
||||
@ -559,7 +576,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* a = m.Int32Constant(0);
|
||||
Node* b = m.Int32Constant(1);
|
||||
Node* add = m.IntPtrSub(a, b);
|
||||
@ -569,7 +587,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* a = m.IntPtrConstant(0);
|
||||
Node* add = m.WordShl(a, 10);
|
||||
EXPECT_THAT(add, IsWordShl(a, IsIntPtrConstant(10)));
|
||||
@ -578,7 +597,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* index = m.IntPtrConstant(2);
|
||||
Node* load_constant = m.LoadConstantPoolEntry(index);
|
||||
Matcher<Node*> constant_pool_matcher = m.IsLoad(
|
||||
@ -596,7 +616,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* object = m.IntPtrConstant(0xdeadbeef);
|
||||
int offset = 16;
|
||||
Node* load_field = m.LoadObjectField(object, offset);
|
||||
@ -608,7 +629,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* arg1 = m.Int32Constant(2);
|
||||
Node* arg2 = m.Int32Constant(3);
|
||||
Node* context = m.Int32Constant(4);
|
||||
@ -622,7 +644,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
|
||||
const int kResultSizes[] = {1, 2};
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
TRACED_FOREACH(int, result_size, kResultSizes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
|
||||
|
||||
Node* function_id = m.Int32Constant(0);
|
||||
@ -653,7 +676,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
|
||||
TailCallMode::kAllow};
|
||||
TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Callable builtin =
|
||||
CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
|
||||
Node* function = m.Int32Constant(0);
|
||||
@ -670,7 +694,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
|
||||
|
||||
TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
|
||||
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
|
||||
InterpreterAssemblerForTest m(this, bytecode);
|
||||
InterpreterAssemblerTestState state(this, bytecode);
|
||||
InterpreterAssemblerForTest m(&state, bytecode);
|
||||
Node* feedback_vector = m.LoadTypeFeedbackVector();
|
||||
|
||||
Matcher<Node*> load_function_matcher =
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
|
||||
#define V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
|
||||
|
||||
#include "src/compiler/code-assembler.h"
|
||||
#include "src/compiler/machine-operator.h"
|
||||
#include "src/interpreter/interpreter-assembler.h"
|
||||
#include "test/unittests/test-utils.h"
|
||||
@ -16,6 +17,14 @@ namespace interpreter {
|
||||
|
||||
using ::testing::Matcher;
|
||||
|
||||
class InterpreterAssemblerTest;
|
||||
|
||||
class InterpreterAssemblerTestState : public compiler::CodeAssemblerState {
|
||||
public:
|
||||
InterpreterAssemblerTestState(InterpreterAssemblerTest* test,
|
||||
Bytecode bytecode);
|
||||
};
|
||||
|
||||
class InterpreterAssemblerTest : public TestWithIsolateAndZone {
|
||||
public:
|
||||
InterpreterAssemblerTest() {}
|
||||
@ -24,10 +33,9 @@ class InterpreterAssemblerTest : public TestWithIsolateAndZone {
|
||||
class InterpreterAssemblerForTest final : public InterpreterAssembler {
|
||||
public:
|
||||
InterpreterAssemblerForTest(
|
||||
InterpreterAssemblerTest* test, Bytecode bytecode,
|
||||
InterpreterAssemblerTestState* state, Bytecode bytecode,
|
||||
OperandScale operand_scale = OperandScale::kSingle)
|
||||
: InterpreterAssembler(test->isolate(), test->zone(), bytecode,
|
||||
operand_scale) {}
|
||||
: InterpreterAssembler(state, bytecode, operand_scale) {}
|
||||
~InterpreterAssemblerForTest() override;
|
||||
|
||||
Matcher<compiler::Node*> IsLoad(
|
||||
|
Loading…
Reference in New Issue
Block a user