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:
jkummerow 2016-11-16 03:48:07 -08:00 committed by Commit bot
parent c93bdaaff1
commit 87a65911b9
43 changed files with 4129 additions and 3856 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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),
&not_string);
assembler->Return(input);
Label not_string(&assembler);
assembler.GotoUnless(assembler.IsStringInstanceType(input_instance_type),
&not_string);
assembler.Return(input);
Label not_heap_number(assembler);
Label not_heap_number(&assembler);
assembler->Bind(&not_string);
assembler.Bind(&not_string);
{
assembler->GotoUnless(
assembler->WordEqual(input_map, assembler->HeapNumberMapConstant()),
assembler.GotoUnless(
assembler.WordEqual(input_map, assembler.HeapNumberMapConstant()),
&not_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(&not_heap_number);
assembler.Bind(&not_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

View File

@ -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

View File

@ -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

View File

@ -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");
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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.
}
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -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,

View File

@ -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

View File

@ -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);
};

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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(

View File

@ -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);
};

View File

@ -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)

View File

@ -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()),

View File

@ -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();

View File

@ -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); \

View File

@ -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_; }

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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 =

View File

@ -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(