[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

Review-Url: https://codereview.chromium.org/2498073002
Cr-Commit-Position: refs/heads/master@{#41015}
This commit is contained in:
jkummerow 2016-11-15 14:57:08 -08:00 committed by Commit bot
parent 879f6599ee
commit 913da29ea2
42 changed files with 4127 additions and 3855 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 ( ) // 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* value = assembler->ToThisValue( Node* value = assembler.ToThisValue(
context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.toString"); context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.toString");
Node* result = assembler->LoadObjectField(value, Oddball::kToStringOffset); Node* result = assembler.LoadObjectField(value, Oddball::kToStringOffset);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 19.3.3.3 Boolean.prototype.valueOf ( ) // 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* result = assembler->ToThisValue( Node* result = assembler.ToThisValue(
context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.valueOf"); context, receiver, PrimitiveType::kBoolean, "Boolean.prototype.valueOf");
assembler->Return(result); assembler.Return(result);
} }
} // namespace internal } // namespace internal

View File

@ -95,110 +95,117 @@ void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler,
} // anonymous namespace } // anonymous namespace
void Builtins::Generate_NonPrimitiveToPrimitive_Default( void Builtins::Generate_NonPrimitiveToPrimitive_Default(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kDefault); CodeStubAssembler assembler(state);
Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kDefault);
} }
void Builtins::Generate_NonPrimitiveToPrimitive_Number( void Builtins::Generate_NonPrimitiveToPrimitive_Number(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kNumber); CodeStubAssembler assembler(state);
Generate_NonPrimitiveToPrimitive(&assembler, ToPrimitiveHint::kNumber);
} }
void Builtins::Generate_NonPrimitiveToPrimitive_String( void Builtins::Generate_NonPrimitiveToPrimitive_String(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString); 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 compiler::Node Node;
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* input = assembler->Parameter(Descriptor::kArgument); Node* input = assembler.Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext); 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 compiler::Node Node;
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* input = assembler->Parameter(Descriptor::kArgument); Node* input = assembler.Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->Return(assembler->ToName(context, input)); assembler.Return(assembler.ToName(context, input));
} }
// static // static
void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { void Builtins::Generate_NonNumberToNumber(compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* input = assembler->Parameter(Descriptor::kArgument); Node* input = assembler.Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext); 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 ) // 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 compiler::Node Node;
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* input = assembler->Parameter(Descriptor::kArgument); Node* input = assembler.Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext); 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* input = assembler->Parameter(Descriptor::kArgument); Node* input = assembler.Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
Label is_number(assembler); Label is_number(&assembler);
Label runtime(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_map = assembler.LoadMap(input);
Node* input_instance_type = assembler->LoadMapInstanceType(input_map); Node* input_instance_type = assembler.LoadMapInstanceType(input_map);
Label not_string(assembler); Label not_string(&assembler);
assembler->GotoUnless(assembler->IsStringInstanceType(input_instance_type), assembler.GotoUnless(assembler.IsStringInstanceType(input_instance_type),
&not_string); &not_string);
assembler->Return(input); assembler.Return(input);
Label not_heap_number(assembler); Label not_heap_number(&assembler);
assembler->Bind(&not_string); assembler.Bind(&not_string);
{ {
assembler->GotoUnless( assembler.GotoUnless(
assembler->WordEqual(input_map, assembler->HeapNumberMapConstant()), assembler.WordEqual(input_map, assembler.HeapNumberMapConstant()),
&not_heap_number); &not_heap_number);
assembler->Goto(&is_number); assembler.Goto(&is_number);
} }
assembler->Bind(&is_number); assembler.Bind(&is_number);
{ assembler->Return(assembler->NumberToString(context, input)); } { assembler.Return(assembler.NumberToString(context, input)); }
assembler->Bind(&not_heap_number); assembler.Bind(&not_heap_number);
{ {
assembler->GotoIf( assembler.GotoIf(
assembler->Word32NotEqual(input_instance_type, assembler.Word32NotEqual(input_instance_type,
assembler->Int32Constant(ODDBALL_TYPE)), assembler.Int32Constant(ODDBALL_TYPE)),
&runtime); &runtime);
assembler->Return( assembler.Return(
assembler->LoadObjectField(input, Oddball::kToStringOffset)); assembler.LoadObjectField(input, Oddball::kToStringOffset));
} }
assembler->Bind(&runtime); assembler.Bind(&runtime);
{ {
assembler->Return( assembler.Return(assembler.CallRuntime(Runtime::kToString, context, input));
assembler->CallRuntime(Runtime::kToString, context, input));
} }
} }
@ -283,194 +290,201 @@ void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler,
} // anonymous namespace } // anonymous namespace
void Builtins::Generate_OrdinaryToPrimitive_Number( void Builtins::Generate_OrdinaryToPrimitive_Number(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kNumber); CodeStubAssembler assembler(state);
Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kNumber);
} }
void Builtins::Generate_OrdinaryToPrimitive_String( void Builtins::Generate_OrdinaryToPrimitive_String(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kString); CodeStubAssembler assembler(state);
Generate_OrdinaryToPrimitive(&assembler, OrdinaryToPrimitiveHint::kString);
} }
// ES6 section 7.1.2 ToBoolean ( argument ) // 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 compiler::Node Node;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef TypeConversionDescriptor Descriptor; 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); Label return_true(&assembler), return_false(&assembler);
assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false); assembler.BranchIfToBooleanIsTrue(value, &return_true, &return_false);
assembler->Bind(&return_true); assembler.Bind(&return_true);
assembler->Return(assembler->BooleanConstant(true)); assembler.Return(assembler.BooleanConstant(true));
assembler->Bind(&return_false); assembler.Bind(&return_false);
assembler->Return(assembler->BooleanConstant(false)); assembler.Return(assembler.BooleanConstant(false));
} }
void Builtins::Generate_ToLength(CodeStubAssembler* assembler) { void Builtins::Generate_ToLength(compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; 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. // We might need to loop once for ToNumber conversion.
Variable var_len(assembler, MachineRepresentation::kTagged); Variable var_len(&assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_len); Label loop(&assembler, &var_len);
var_len.Bind(assembler->Parameter(0)); var_len.Bind(assembler.Parameter(0));
assembler->Goto(&loop); assembler.Goto(&loop);
assembler->Bind(&loop); assembler.Bind(&loop);
{ {
// Shared entry points. // Shared entry points.
Label return_len(assembler), Label return_len(&assembler),
return_two53minus1(assembler, Label::kDeferred), return_two53minus1(&assembler, Label::kDeferred),
return_zero(assembler, Label::kDeferred); return_zero(&assembler, Label::kDeferred);
// Load the current {len} value. // Load the current {len} value.
Node* len = var_len.value(); Node* len = var_len.value();
// Check if {len} is a positive Smi. // 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. // 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. // Check if {len} is a HeapNumber.
Label if_lenisheapnumber(assembler), Label if_lenisheapnumber(&assembler),
if_lenisnotheapnumber(assembler, Label::kDeferred); if_lenisnotheapnumber(&assembler, Label::kDeferred);
assembler->Branch(assembler->IsHeapNumberMap(assembler->LoadMap(len)), assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(len)),
&if_lenisheapnumber, &if_lenisnotheapnumber); &if_lenisheapnumber, &if_lenisnotheapnumber);
assembler->Bind(&if_lenisheapnumber); assembler.Bind(&if_lenisheapnumber);
{ {
// Load the floating-point value of {len}. // 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. // Check if {len} is not greater than zero.
assembler->GotoUnless(assembler->Float64GreaterThan( assembler.GotoUnless(assembler.Float64GreaterThan(
len_value, assembler->Float64Constant(0.0)), len_value, assembler.Float64Constant(0.0)),
&return_zero); &return_zero);
// Check if {len} is greater than or equal to 2^53-1. // Check if {len} is greater than or equal to 2^53-1.
assembler->GotoIf( assembler.GotoIf(
assembler->Float64GreaterThanOrEqual( assembler.Float64GreaterThanOrEqual(
len_value, assembler->Float64Constant(kMaxSafeInteger)), len_value, assembler.Float64Constant(kMaxSafeInteger)),
&return_two53minus1); &return_two53minus1);
// Round the {len} towards -Infinity. // Round the {len} towards -Infinity.
Node* value = assembler->Float64Floor(len_value); Node* value = assembler.Float64Floor(len_value);
Node* result = assembler->ChangeFloat64ToTagged(value); Node* result = assembler.ChangeFloat64ToTagged(value);
assembler->Return(result); assembler.Return(result);
} }
assembler->Bind(&if_lenisnotheapnumber); assembler.Bind(&if_lenisnotheapnumber);
{ {
// Need to convert {len} to a Number first. // Need to convert {len} to a Number first.
Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate()); Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
var_len.Bind(assembler->CallStub(callable, context, len)); var_len.Bind(assembler.CallStub(callable, context, len));
assembler->Goto(&loop); assembler.Goto(&loop);
} }
assembler->Bind(&return_len); assembler.Bind(&return_len);
assembler->Return(var_len.value()); assembler.Return(var_len.value());
assembler->Bind(&return_two53minus1); assembler.Bind(&return_two53minus1);
assembler->Return(assembler->NumberConstant(kMaxSafeInteger)); assembler.Return(assembler.NumberConstant(kMaxSafeInteger));
assembler->Bind(&return_zero); assembler.Bind(&return_zero);
assembler->Return(assembler->SmiConstant(Smi::kZero)); assembler.Return(assembler.SmiConstant(Smi::kZero));
} }
} }
void Builtins::Generate_ToInteger(CodeStubAssembler* assembler) { void Builtins::Generate_ToInteger(compiler::CodeAssemblerState* state) {
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
compiler::Node* input = assembler->Parameter(Descriptor::kArgument); compiler::Node* input = assembler.Parameter(Descriptor::kArgument);
compiler::Node* context = assembler->Parameter(Descriptor::kContext); 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) // 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 compiler::Node Node;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
typedef TypeConversionDescriptor Descriptor; typedef TypeConversionDescriptor Descriptor;
CodeStubAssembler assembler(state);
Label if_number(assembler, Label::kDeferred), if_notsmi(assembler), Label if_number(&assembler, Label::kDeferred), if_notsmi(&assembler),
if_jsreceiver(assembler), if_noconstructor(assembler, Label::kDeferred), if_jsreceiver(&assembler), if_noconstructor(&assembler, Label::kDeferred),
if_wrapjsvalue(assembler); if_wrapjsvalue(&assembler);
Node* object = assembler->Parameter(Descriptor::kArgument); Node* object = assembler.Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
Variable constructor_function_index_var(assembler, Variable constructor_function_index_var(&assembler,
MachineType::PointerRepresentation()); MachineType::PointerRepresentation());
assembler->Branch(assembler->TaggedIsSmi(object), &if_number, &if_notsmi); assembler.Branch(assembler.TaggedIsSmi(object), &if_number, &if_notsmi);
assembler->Bind(&if_notsmi); assembler.Bind(&if_notsmi);
Node* map = assembler->LoadMap(object); 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); Node* instance_type = assembler.LoadMapInstanceType(map);
assembler->GotoIf(assembler->IsJSReceiverInstanceType(instance_type), assembler.GotoIf(assembler.IsJSReceiverInstanceType(instance_type),
&if_jsreceiver); &if_jsreceiver);
Node* constructor_function_index = Node* constructor_function_index =
assembler->LoadMapConstructorFunctionIndex(map); assembler.LoadMapConstructorFunctionIndex(map);
assembler->GotoIf(assembler->WordEqual(constructor_function_index, assembler.GotoIf(assembler.WordEqual(constructor_function_index,
assembler->IntPtrConstant( assembler.IntPtrConstant(
Map::kNoConstructorFunctionIndex)), Map::kNoConstructorFunctionIndex)),
&if_noconstructor); &if_noconstructor);
constructor_function_index_var.Bind(constructor_function_index); 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( constructor_function_index_var.Bind(
assembler->IntPtrConstant(Context::NUMBER_FUNCTION_INDEX)); assembler.IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
assembler->Goto(&if_wrapjsvalue); assembler.Goto(&if_wrapjsvalue);
assembler->Bind(&if_wrapjsvalue); assembler.Bind(&if_wrapjsvalue);
Node* native_context = assembler->LoadNativeContext(context); Node* native_context = assembler.LoadNativeContext(context);
Node* constructor = assembler->LoadFixedArrayElement( Node* constructor = assembler.LoadFixedArrayElement(
native_context, constructor_function_index_var.value(), 0, native_context, constructor_function_index_var.value(), 0,
CodeStubAssembler::INTPTR_PARAMETERS); CodeStubAssembler::INTPTR_PARAMETERS);
Node* initial_map = assembler->LoadObjectField( Node* initial_map = assembler.LoadObjectField(
constructor, JSFunction::kPrototypeOrInitialMapOffset); constructor, JSFunction::kPrototypeOrInitialMapOffset);
Node* js_value = assembler->Allocate(JSValue::kSize); Node* js_value = assembler.Allocate(JSValue::kSize);
assembler->StoreMapNoWriteBarrier(js_value, initial_map); assembler.StoreMapNoWriteBarrier(js_value, initial_map);
assembler->StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset, assembler.StoreObjectFieldRoot(js_value, JSValue::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex); Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldRoot(js_value, JSObject::kElementsOffset, assembler.StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex); Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectField(js_value, JSValue::kValueOffset, object); assembler.StoreObjectField(js_value, JSValue::kValueOffset, object);
assembler->Return(js_value); assembler.Return(js_value);
assembler->Bind(&if_noconstructor); assembler.Bind(&if_noconstructor);
assembler->TailCallRuntime( assembler.TailCallRuntime(
Runtime::kThrowUndefinedOrNullToObject, context, Runtime::kThrowUndefinedOrNullToObject, context,
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( assembler.HeapConstant(
"ToObject", TENURED))); assembler.factory()->NewStringFromAsciiChecked("ToObject", TENURED)));
assembler->Bind(&if_jsreceiver); assembler.Bind(&if_jsreceiver);
assembler->Return(object); assembler.Return(object);
} }
// ES6 section 12.5.5 typeof operator // 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 compiler::Node Node;
typedef TypeofDescriptor Descriptor; typedef TypeofDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler.Parameter(Descriptor::kObject);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->Return(assembler->Typeof(object, context)); assembler.Return(assembler.Typeof(object, context));
} }
} // namespace internal } // namespace internal

View File

@ -908,9 +908,10 @@ BUILTIN(DatePrototypeToJson) {
} }
} }
// static namespace {
void Builtins::Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
int field_index) { void Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
int field_index) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
@ -965,100 +966,132 @@ void Builtins::Generate_DatePrototype_GetField(CodeStubAssembler* assembler,
} }
} }
} // namespace
// static // static
void Builtins::Generate_DatePrototypeGetDate(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetDate(
Generate_DatePrototype_GetField(assembler, JSDate::kDay); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kDay);
} }
// static // static
void Builtins::Generate_DatePrototypeGetDay(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetDay(
Generate_DatePrototype_GetField(assembler, JSDate::kWeekday); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kWeekday);
} }
// static // static
void Builtins::Generate_DatePrototypeGetFullYear(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetFullYear(
Generate_DatePrototype_GetField(assembler, JSDate::kYear); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kYear);
} }
// static // static
void Builtins::Generate_DatePrototypeGetHours(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetHours(
Generate_DatePrototype_GetField(assembler, JSDate::kHour); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kHour);
} }
// static // static
void Builtins::Generate_DatePrototypeGetMilliseconds( void Builtins::Generate_DatePrototypeGetMilliseconds(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_DatePrototype_GetField(assembler, JSDate::kMillisecond); CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecond);
} }
// static // static
void Builtins::Generate_DatePrototypeGetMinutes(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetMinutes(
Generate_DatePrototype_GetField(assembler, JSDate::kMinute); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kMinute);
} }
// static // static
void Builtins::Generate_DatePrototypeGetMonth(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetMonth(
Generate_DatePrototype_GetField(assembler, JSDate::kMonth); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kMonth);
} }
// static // static
void Builtins::Generate_DatePrototypeGetSeconds(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetSeconds(
Generate_DatePrototype_GetField(assembler, JSDate::kSecond); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kSecond);
} }
// static // static
void Builtins::Generate_DatePrototypeGetTime(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetTime(
Generate_DatePrototype_GetField(assembler, JSDate::kDateValue); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kDateValue);
} }
// static // static
void Builtins::Generate_DatePrototypeGetTimezoneOffset( void Builtins::Generate_DatePrototypeGetTimezoneOffset(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_DatePrototype_GetField(assembler, JSDate::kTimezoneOffset); CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kTimezoneOffset);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCDate(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetUTCDate(
Generate_DatePrototype_GetField(assembler, JSDate::kDayUTC); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kDayUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCDay(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetUTCDay(
Generate_DatePrototype_GetField(assembler, JSDate::kWeekdayUTC); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kWeekdayUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCFullYear( void Builtins::Generate_DatePrototypeGetUTCFullYear(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_DatePrototype_GetField(assembler, JSDate::kYearUTC); CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kYearUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCHours(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetUTCHours(
Generate_DatePrototype_GetField(assembler, JSDate::kHourUTC); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kHourUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCMilliseconds( void Builtins::Generate_DatePrototypeGetUTCMilliseconds(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_DatePrototype_GetField(assembler, JSDate::kMillisecondUTC); CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecondUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCMinutes( void Builtins::Generate_DatePrototypeGetUTCMinutes(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_DatePrototype_GetField(assembler, JSDate::kMinuteUTC); CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kMinuteUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCMonth(CodeStubAssembler* assembler) { void Builtins::Generate_DatePrototypeGetUTCMonth(
Generate_DatePrototype_GetField(assembler, JSDate::kMonthUTC); compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kMonthUTC);
} }
// static // static
void Builtins::Generate_DatePrototypeGetUTCSeconds( void Builtins::Generate_DatePrototypeGetUTCSeconds(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_DatePrototype_GetField(assembler, JSDate::kSecondUTC); CodeStubAssembler assembler(state);
Generate_DatePrototype_GetField(&assembler, JSDate::kSecondUTC);
} }
} // namespace internal } // namespace internal

View File

@ -283,14 +283,15 @@ BUILTIN(FunctionPrototypeToString) {
// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V ) // ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
void Builtins::Generate_FunctionPrototypeHasInstance( void Builtins::Generate_FunctionPrototypeHasInstance(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
using compiler::Node; using compiler::Node;
CodeStubAssembler assembler(state);
Node* f = assembler->Parameter(0); Node* f = assembler.Parameter(0);
Node* v = assembler->Parameter(1); Node* v = assembler.Parameter(1);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
Node* result = assembler->OrdinaryHasInstance(context, f, v); Node* result = assembler.OrdinaryHasInstance(context, f, v);
assembler->Return(result); assembler.Return(result);
} }
} // namespace internal } // namespace internal

View File

@ -96,20 +96,26 @@ void Generate_GeneratorPrototypeResume(
} // anonymous namespace } // anonymous namespace
// ES6 section 25.3.1.2 Generator.prototype.next ( value ) // ES6 section 25.3.1.2 Generator.prototype.next ( value )
void Builtins::Generate_GeneratorPrototypeNext(CodeStubAssembler* assembler) { void Builtins::Generate_GeneratorPrototypeNext(
Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kNext, compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kNext,
"[Generator].prototype.next"); "[Generator].prototype.next");
} }
// ES6 section 25.3.1.3 Generator.prototype.return ( value ) // ES6 section 25.3.1.3 Generator.prototype.return ( value )
void Builtins::Generate_GeneratorPrototypeReturn(CodeStubAssembler* assembler) { void Builtins::Generate_GeneratorPrototypeReturn(
Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kReturn, compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kReturn,
"[Generator].prototype.return"); "[Generator].prototype.return");
} }
// ES6 section 25.3.1.4 Generator.prototype.throw ( exception ) // ES6 section 25.3.1.4 Generator.prototype.throw ( exception )
void Builtins::Generate_GeneratorPrototypeThrow(CodeStubAssembler* assembler) { void Builtins::Generate_GeneratorPrototypeThrow(
Generate_GeneratorPrototypeResume(assembler, JSGeneratorObject::kThrow, compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
Generate_GeneratorPrototypeResume(&assembler, JSGeneratorObject::kThrow,
"[Generator].prototype.throw"); "[Generator].prototype.throw");
} }

View File

@ -101,111 +101,112 @@ BUILTIN(GlobalEval) {
} }
// ES6 section 18.2.2 isFinite ( number ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; 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. // We might need to loop once for ToNumber conversion.
Variable var_num(assembler, MachineRepresentation::kTagged); Variable var_num(&assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_num); Label loop(&assembler, &var_num);
var_num.Bind(assembler->Parameter(1)); var_num.Bind(assembler.Parameter(1));
assembler->Goto(&loop); assembler.Goto(&loop);
assembler->Bind(&loop); assembler.Bind(&loop);
{ {
// Load the current {num} value. // Load the current {num} value.
Node* num = var_num.value(); Node* num = var_num.value();
// Check if {num} is a Smi or a HeapObject. // 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. // Check if {num} is a HeapNumber.
Label if_numisheapnumber(assembler), Label if_numisheapnumber(&assembler),
if_numisnotheapnumber(assembler, Label::kDeferred); if_numisnotheapnumber(&assembler, Label::kDeferred);
assembler->Branch(assembler->WordEqual(assembler->LoadMap(num), assembler.Branch(assembler.WordEqual(assembler.LoadMap(num),
assembler->HeapNumberMapConstant()), assembler.HeapNumberMapConstant()),
&if_numisheapnumber, &if_numisnotheapnumber); &if_numisheapnumber, &if_numisnotheapnumber);
assembler->Bind(&if_numisheapnumber); assembler.Bind(&if_numisheapnumber);
{ {
// Check if {num} contains a finite, non-NaN value. // Check if {num} contains a finite, non-NaN value.
Node* num_value = assembler->LoadHeapNumberValue(num); Node* num_value = assembler.LoadHeapNumberValue(num);
assembler->BranchIfFloat64IsNaN( assembler.BranchIfFloat64IsNaN(assembler.Float64Sub(num_value, num_value),
assembler->Float64Sub(num_value, num_value), &return_false, &return_false, &return_true);
&return_true);
} }
assembler->Bind(&if_numisnotheapnumber); assembler.Bind(&if_numisnotheapnumber);
{ {
// Need to convert {num} to a Number first. // Need to convert {num} to a Number first.
Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate()); Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
var_num.Bind(assembler->CallStub(callable, context, num)); var_num.Bind(assembler.CallStub(callable, context, num));
assembler->Goto(&loop); assembler.Goto(&loop);
} }
} }
assembler->Bind(&return_true); assembler.Bind(&return_true);
assembler->Return(assembler->BooleanConstant(true)); assembler.Return(assembler.BooleanConstant(true));
assembler->Bind(&return_false); assembler.Bind(&return_false);
assembler->Return(assembler->BooleanConstant(false)); assembler.Return(assembler.BooleanConstant(false));
} }
// ES6 section 18.2.3 isNaN ( number ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; 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. // We might need to loop once for ToNumber conversion.
Variable var_num(assembler, MachineRepresentation::kTagged); Variable var_num(&assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_num); Label loop(&assembler, &var_num);
var_num.Bind(assembler->Parameter(1)); var_num.Bind(assembler.Parameter(1));
assembler->Goto(&loop); assembler.Goto(&loop);
assembler->Bind(&loop); assembler.Bind(&loop);
{ {
// Load the current {num} value. // Load the current {num} value.
Node* num = var_num.value(); Node* num = var_num.value();
// Check if {num} is a Smi or a HeapObject. // 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. // Check if {num} is a HeapNumber.
Label if_numisheapnumber(assembler), Label if_numisheapnumber(&assembler),
if_numisnotheapnumber(assembler, Label::kDeferred); if_numisnotheapnumber(&assembler, Label::kDeferred);
assembler->Branch(assembler->WordEqual(assembler->LoadMap(num), assembler.Branch(assembler.WordEqual(assembler.LoadMap(num),
assembler->HeapNumberMapConstant()), assembler.HeapNumberMapConstant()),
&if_numisheapnumber, &if_numisnotheapnumber); &if_numisheapnumber, &if_numisnotheapnumber);
assembler->Bind(&if_numisheapnumber); assembler.Bind(&if_numisheapnumber);
{ {
// Check if {num} contains a NaN. // Check if {num} contains a NaN.
Node* num_value = assembler->LoadHeapNumberValue(num); Node* num_value = assembler.LoadHeapNumberValue(num);
assembler->BranchIfFloat64IsNaN(num_value, &return_true, &return_false); assembler.BranchIfFloat64IsNaN(num_value, &return_true, &return_false);
} }
assembler->Bind(&if_numisnotheapnumber); assembler.Bind(&if_numisnotheapnumber);
{ {
// Need to convert {num} to a Number first. // Need to convert {num} to a Number first.
Callable callable = CodeFactory::NonNumberToNumber(assembler->isolate()); Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
var_num.Bind(assembler->CallStub(callable, context, num)); var_num.Bind(assembler.CallStub(callable, context, num));
assembler->Goto(&loop); assembler.Goto(&loop);
} }
} }
assembler->Bind(&return_true); assembler.Bind(&return_true);
assembler->Return(assembler->BooleanConstant(true)); assembler.Return(assembler.BooleanConstant(true));
assembler->Bind(&return_false); assembler.Bind(&return_false);
assembler->Return(assembler->BooleanConstant(false)); assembler.Return(assembler.BooleanConstant(false));
} }
} // namespace internal } // namespace internal

View File

@ -12,18 +12,19 @@ namespace v8 {
namespace internal { namespace internal {
void Builtins::Generate_KeyedLoadIC_Megamorphic_TF( void Builtins::Generate_KeyedLoadIC_Megamorphic_TF(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef LoadWithVectorDescriptor Descriptor; typedef LoadWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(Descriptor::kReceiver); Node* receiver = assembler.Parameter(Descriptor::kReceiver);
Node* name = assembler->Parameter(Descriptor::kName); Node* name = assembler.Parameter(Descriptor::kName);
Node* slot = assembler->Parameter(Descriptor::kSlot); Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler->Parameter(Descriptor::kVector); Node* vector = assembler.Parameter(Descriptor::kVector);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
CodeStubAssembler::LoadICParameters p(context, receiver, name, slot, vector); CodeStubAssembler::LoadICParameters p(context, receiver, name, slot, vector);
assembler->KeyedLoadICGeneric(&p); assembler.KeyedLoadICGeneric(&p);
} }
void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) { void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
@ -41,30 +42,14 @@ void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
KeyedStoreIC::GenerateMegamorphic(masm, STRICT); 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( void Builtins::Generate_KeyedStoreIC_Megamorphic_TF(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
KeyedStoreICMegamorphic(assembler, SLOPPY); KeyedStoreGenericGenerator::Generate(state, SLOPPY);
} }
void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict_TF( void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict_TF(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
KeyedStoreICMegamorphic(assembler, STRICT); KeyedStoreGenericGenerator::Generate(state, STRICT);
} }
void Builtins::Generate_KeyedStoreIC_Miss(MacroAssembler* masm) { void Builtins::Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
@ -75,76 +60,79 @@ void Builtins::Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
KeyedStoreIC::GenerateSlow(masm); KeyedStoreIC::GenerateSlow(masm);
} }
void Builtins::Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) { void Builtins::Generate_LoadGlobalIC_Miss(compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef LoadGlobalWithVectorDescriptor Descriptor; typedef LoadGlobalWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* slot = assembler->Parameter(Descriptor::kSlot); Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler->Parameter(Descriptor::kVector); Node* vector = assembler.Parameter(Descriptor::kVector);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot, assembler.TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot, vector);
vector);
} }
void Builtins::Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler) { void Builtins::Generate_LoadGlobalIC_Slow(compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef LoadGlobalWithVectorDescriptor Descriptor; typedef LoadGlobalWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* slot = assembler->Parameter(Descriptor::kSlot); Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler->Parameter(Descriptor::kVector); Node* vector = assembler.Parameter(Descriptor::kVector);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot, assembler.TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, slot, vector);
vector);
} }
void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) { void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm); NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
} }
void Builtins::Generate_LoadIC_Miss(CodeStubAssembler* assembler) { void Builtins::Generate_LoadIC_Miss(compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef LoadWithVectorDescriptor Descriptor; typedef LoadWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(Descriptor::kReceiver); Node* receiver = assembler.Parameter(Descriptor::kReceiver);
Node* name = assembler->Parameter(Descriptor::kName); Node* name = assembler.Parameter(Descriptor::kName);
Node* slot = assembler->Parameter(Descriptor::kSlot); Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler->Parameter(Descriptor::kVector); Node* vector = assembler.Parameter(Descriptor::kVector);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, assembler.TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name,
slot, vector); slot, vector);
} }
void Builtins::Generate_LoadIC_Normal(MacroAssembler* masm) { void Builtins::Generate_LoadIC_Normal(MacroAssembler* masm) {
LoadIC::GenerateNormal(masm); LoadIC::GenerateNormal(masm);
} }
void Builtins::Generate_LoadIC_Slow(CodeStubAssembler* assembler) { void Builtins::Generate_LoadIC_Slow(compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef LoadWithVectorDescriptor Descriptor; typedef LoadWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(Descriptor::kReceiver); Node* receiver = assembler.Parameter(Descriptor::kReceiver);
Node* name = assembler->Parameter(Descriptor::kName); Node* name = assembler.Parameter(Descriptor::kName);
Node* context = assembler->Parameter(Descriptor::kContext); 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 compiler::Node Node;
typedef StoreWithVectorDescriptor Descriptor; typedef StoreWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(Descriptor::kReceiver); Node* receiver = assembler.Parameter(Descriptor::kReceiver);
Node* name = assembler->Parameter(Descriptor::kName); Node* name = assembler.Parameter(Descriptor::kName);
Node* value = assembler->Parameter(Descriptor::kValue); Node* value = assembler.Parameter(Descriptor::kValue);
Node* slot = assembler->Parameter(Descriptor::kSlot); Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler->Parameter(Descriptor::kVector); Node* vector = assembler.Parameter(Descriptor::kVector);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, assembler.TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot,
vector, receiver, name); vector, receiver, name);
} }
void Builtins::Generate_StoreIC_Normal(MacroAssembler* masm) { void Builtins::Generate_StoreIC_Normal(MacroAssembler* masm) {
@ -156,30 +144,33 @@ void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
} }
namespace { namespace {
void Generate_StoreIC_Slow(CodeStubAssembler* assembler, void Generate_StoreIC_Slow(compiler::CodeAssemblerState* state,
LanguageMode language_mode) { LanguageMode language_mode) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef StoreWithVectorDescriptor Descriptor; typedef StoreWithVectorDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(Descriptor::kReceiver); Node* receiver = assembler.Parameter(Descriptor::kReceiver);
Node* name = assembler->Parameter(Descriptor::kName); Node* name = assembler.Parameter(Descriptor::kName);
Node* value = assembler->Parameter(Descriptor::kValue); Node* value = assembler.Parameter(Descriptor::kValue);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
Node* lang_mode = assembler->SmiConstant(Smi::FromInt(language_mode)); Node* lang_mode = assembler.SmiConstant(Smi::FromInt(language_mode));
// The slow case calls into the runtime to complete the store without causing // 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. // an IC miss that would otherwise cause a transition to the generic stub.
assembler->TailCallRuntime(Runtime::kSetProperty, context, receiver, name, assembler.TailCallRuntime(Runtime::kSetProperty, context, receiver, name,
value, lang_mode); value, lang_mode);
} }
} // anonymous namespace } // anonymous namespace
void Builtins::Generate_StoreIC_SlowSloppy(CodeStubAssembler* assembler) { void Builtins::Generate_StoreIC_SlowSloppy(
Generate_StoreIC_Slow(assembler, SLOPPY); compiler::CodeAssemblerState* state) {
Generate_StoreIC_Slow(state, SLOPPY);
} }
void Builtins::Generate_StoreIC_SlowStrict(CodeStubAssembler* assembler) { void Builtins::Generate_StoreIC_SlowStrict(
Generate_StoreIC_Slow(assembler, STRICT); compiler::CodeAssemblerState* state) {
Generate_StoreIC_Slow(state, STRICT);
} }
} // namespace internal } // namespace internal

View File

@ -54,86 +54,90 @@ void Builtins::Generate_StackCheck(MacroAssembler* masm) {
// TurboFan support builtins. // TurboFan support builtins.
void Builtins::Generate_CopyFastSmiOrObjectElements( void Builtins::Generate_CopyFastSmiOrObjectElements(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CopyFastSmiOrObjectElementsDescriptor Descriptor; typedef CopyFastSmiOrObjectElementsDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler.Parameter(Descriptor::kObject);
// Load the {object}s elements. // Load the {object}s elements.
Node* source = assembler->LoadObjectField(object, JSObject::kElementsOffset); Node* source = assembler.LoadObjectField(object, JSObject::kElementsOffset);
CodeStubAssembler::ParameterMode mode = assembler->OptimalParameterMode(); CodeStubAssembler::ParameterMode mode = assembler.OptimalParameterMode();
Node* length = assembler->UntagParameter( Node* length = assembler.UntagParameter(
assembler->LoadFixedArrayBaseLength(source), mode); assembler.LoadFixedArrayBaseLength(source), mode);
// Check if we can allocate in new space. // Check if we can allocate in new space.
ElementsKind kind = FAST_ELEMENTS; ElementsKind kind = FAST_ELEMENTS;
int max_elements = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind); int max_elements = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(kind);
Label if_newspace(assembler), if_oldspace(assembler); Label if_newspace(&assembler), if_oldspace(&assembler);
assembler->Branch( assembler.Branch(
assembler->UintPtrLessThan( assembler.UintPtrLessThan(
length, assembler->IntPtrOrSmiConstant(max_elements, mode)), length, assembler.IntPtrOrSmiConstant(max_elements, mode)),
&if_newspace, &if_oldspace); &if_newspace, &if_oldspace);
assembler->Bind(&if_newspace); assembler.Bind(&if_newspace);
{ {
Node* target = assembler->AllocateFixedArray(kind, length, mode); Node* target = assembler.AllocateFixedArray(kind, length, mode);
assembler->CopyFixedArrayElements(kind, source, target, length, assembler.CopyFixedArrayElements(kind, source, target, length,
SKIP_WRITE_BARRIER, mode); SKIP_WRITE_BARRIER, mode);
assembler->StoreObjectField(object, JSObject::kElementsOffset, target); assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
assembler->Return(target); assembler.Return(target);
} }
assembler->Bind(&if_oldspace); assembler.Bind(&if_oldspace);
{ {
Node* target = assembler->AllocateFixedArray( Node* target = assembler.AllocateFixedArray(kind, length, mode,
kind, length, mode, CodeStubAssembler::kPretenured); CodeStubAssembler::kPretenured);
assembler->CopyFixedArrayElements(kind, source, target, length, assembler.CopyFixedArrayElements(kind, source, target, length,
UPDATE_WRITE_BARRIER, mode); UPDATE_WRITE_BARRIER, mode);
assembler->StoreObjectField(object, JSObject::kElementsOffset, target); assembler.StoreObjectField(object, JSObject::kElementsOffset, target);
assembler->Return(target); assembler.Return(target);
} }
} }
void Builtins::Generate_GrowFastDoubleElements(CodeStubAssembler* assembler) { void Builtins::Generate_GrowFastDoubleElements(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef GrowArrayElementsDescriptor Descriptor; typedef GrowArrayElementsDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler.Parameter(Descriptor::kObject);
Node* key = assembler->Parameter(Descriptor::kKey); Node* key = assembler.Parameter(Descriptor::kKey);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
Label runtime(assembler, CodeStubAssembler::Label::kDeferred); Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
Node* elements = assembler->LoadElements(object); Node* elements = assembler.LoadElements(object);
elements = assembler->TryGrowElementsCapacity( elements = assembler.TryGrowElementsCapacity(
object, elements, FAST_DOUBLE_ELEMENTS, key, &runtime); object, elements, FAST_DOUBLE_ELEMENTS, key, &runtime);
assembler->Return(elements); assembler.Return(elements);
assembler->Bind(&runtime); assembler.Bind(&runtime);
assembler->TailCallRuntime(Runtime::kGrowArrayElements, context, object, key); assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
} }
void Builtins::Generate_GrowFastSmiOrObjectElements( void Builtins::Generate_GrowFastSmiOrObjectElements(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef GrowArrayElementsDescriptor Descriptor; typedef GrowArrayElementsDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler.Parameter(Descriptor::kObject);
Node* key = assembler->Parameter(Descriptor::kKey); Node* key = assembler.Parameter(Descriptor::kKey);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
Label runtime(assembler, CodeStubAssembler::Label::kDeferred); Label runtime(&assembler, CodeStubAssembler::Label::kDeferred);
Node* elements = assembler->LoadElements(object); Node* elements = assembler.LoadElements(object);
elements = assembler->TryGrowElementsCapacity(object, elements, FAST_ELEMENTS, elements = assembler.TryGrowElementsCapacity(object, elements, FAST_ELEMENTS,
key, &runtime); key, &runtime);
assembler->Return(elements); assembler.Return(elements);
assembler->Bind(&runtime); assembler.Bind(&runtime);
assembler->TailCallRuntime(Runtime::kGrowArrayElements, context, object, key); assembler.TailCallRuntime(Runtime::kGrowArrayElements, context, object, key);
} }
} // namespace internal } // namespace internal

View File

@ -10,8 +10,9 @@ namespace v8 {
namespace internal { namespace internal {
void Builtins::Generate_IteratorPrototypeIterator( void Builtins::Generate_IteratorPrototypeIterator(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
assembler->Return(assembler->Parameter(0)); CodeStubAssembler assembler(state);
assembler.Return(assembler.Parameter(0));
} }
BUILTIN(ModuleNamespaceIterator) { 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 Function Properties of the Math Object
// ES6 section - 20.2.2.1 Math.abs ( x ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; 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. // We might need to loop once for ToNumber conversion.
Variable var_x(assembler, MachineRepresentation::kTagged); Variable var_x(&assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_x); Label loop(&assembler, &var_x);
var_x.Bind(assembler->Parameter(1)); var_x.Bind(assembler.Parameter(1));
assembler->Goto(&loop); assembler.Goto(&loop);
assembler->Bind(&loop); assembler.Bind(&loop);
{ {
// Load the current {x} value. // Load the current {x} value.
Node* x = var_x.value(); Node* x = var_x.value();
// Check if {x} is a Smi or a HeapObject. // Check if {x} is a Smi or a HeapObject.
Label if_xissmi(assembler), if_xisnotsmi(assembler); Label if_xissmi(&assembler), if_xisnotsmi(&assembler);
assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi); assembler.Branch(assembler.TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
assembler->Bind(&if_xissmi); assembler.Bind(&if_xissmi);
{ {
// Check if {x} is already positive. // Check if {x} is already positive.
Label if_xispositive(assembler), if_xisnotpositive(assembler); Label if_xispositive(&assembler), if_xisnotpositive(&assembler);
assembler->BranchIfSmiLessThanOrEqual( assembler.BranchIfSmiLessThanOrEqual(
assembler->SmiConstant(Smi::FromInt(0)), x, &if_xispositive, assembler.SmiConstant(Smi::FromInt(0)), x, &if_xispositive,
&if_xisnotpositive); &if_xisnotpositive);
assembler->Bind(&if_xispositive); assembler.Bind(&if_xispositive);
{ {
// Just return the input {x}. // 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. // Try to negate the {x} value.
Node* pair = assembler->IntPtrSubWithOverflow( Node* pair = assembler.IntPtrSubWithOverflow(
assembler->IntPtrConstant(0), assembler->BitcastTaggedToWord(x)); assembler.IntPtrConstant(0), assembler.BitcastTaggedToWord(x));
Node* overflow = assembler->Projection(1, pair); Node* overflow = assembler.Projection(1, pair);
Label if_overflow(assembler, Label::kDeferred), Label if_overflow(&assembler, Label::kDeferred),
if_notoverflow(assembler); if_notoverflow(&assembler);
assembler->Branch(overflow, &if_overflow, &if_notoverflow); assembler.Branch(overflow, &if_overflow, &if_notoverflow);
assembler->Bind(&if_notoverflow); assembler.Bind(&if_notoverflow);
{ {
// There is a Smi representation for negated {x}. // There is a Smi representation for negated {x}.
Node* result = assembler->Projection(0, pair); Node* result = assembler.Projection(0, pair);
result = assembler->BitcastWordToTagged(result); result = assembler.BitcastWordToTagged(result);
assembler->Return(result); assembler.Return(result);
} }
assembler->Bind(&if_overflow); assembler.Bind(&if_overflow);
{ {
Node* result = assembler->NumberConstant(0.0 - Smi::kMinValue); Node* result = assembler.NumberConstant(0.0 - Smi::kMinValue);
assembler->Return(result); assembler.Return(result);
} }
} }
} }
assembler->Bind(&if_xisnotsmi); assembler.Bind(&if_xisnotsmi);
{ {
// Check if {x} is a HeapNumber. // Check if {x} is a HeapNumber.
Label if_xisheapnumber(assembler), Label if_xisheapnumber(&assembler),
if_xisnotheapnumber(assembler, Label::kDeferred); if_xisnotheapnumber(&assembler, Label::kDeferred);
assembler->Branch( assembler.Branch(assembler.WordEqual(assembler.LoadMap(x),
assembler->WordEqual(assembler->LoadMap(x), assembler.HeapNumberMapConstant()),
assembler->HeapNumberMapConstant()), &if_xisheapnumber, &if_xisnotheapnumber);
&if_xisheapnumber, &if_xisnotheapnumber);
assembler->Bind(&if_xisheapnumber); assembler.Bind(&if_xisheapnumber);
{ {
Node* x_value = assembler->LoadHeapNumberValue(x); Node* x_value = assembler.LoadHeapNumberValue(x);
Node* value = assembler->Float64Abs(x_value); Node* value = assembler.Float64Abs(x_value);
Node* result = assembler->AllocateHeapNumberWithValue(value); Node* result = assembler.AllocateHeapNumberWithValue(value);
assembler->Return(result); assembler.Return(result);
} }
assembler->Bind(&if_xisnotheapnumber); assembler.Bind(&if_xisnotheapnumber);
{ {
// Need to convert {x} to a Number first. // Need to convert {x} to a Number first.
Callable callable = Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
CodeFactory::NonNumberToNumber(assembler->isolate()); var_x.Bind(assembler.CallStub(callable, context, x));
var_x.Bind(assembler->CallStub(callable, context, x)); assembler.Goto(&loop);
assembler->Goto(&loop);
} }
} }
} }
@ -182,163 +181,177 @@ void Generate_MathUnaryOperation(
} // namespace } // namespace
// ES6 section 20.2.2.2 Math.acos ( x ) // ES6 section 20.2.2.2 Math.acos ( x )
void Builtins::Generate_MathAcos(CodeStubAssembler* assembler) { void Builtins::Generate_MathAcos(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Acos); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Acos);
} }
// ES6 section 20.2.2.3 Math.acosh ( x ) // ES6 section 20.2.2.3 Math.acosh ( x )
void Builtins::Generate_MathAcosh(CodeStubAssembler* assembler) { void Builtins::Generate_MathAcosh(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Acosh); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Acosh);
} }
// ES6 section 20.2.2.4 Math.asin ( x ) // ES6 section 20.2.2.4 Math.asin ( x )
void Builtins::Generate_MathAsin(CodeStubAssembler* assembler) { void Builtins::Generate_MathAsin(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Asin); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Asin);
} }
// ES6 section 20.2.2.5 Math.asinh ( x ) // ES6 section 20.2.2.5 Math.asinh ( x )
void Builtins::Generate_MathAsinh(CodeStubAssembler* assembler) { void Builtins::Generate_MathAsinh(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Asinh); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Asinh);
} }
// ES6 section 20.2.2.6 Math.atan ( x ) // ES6 section 20.2.2.6 Math.atan ( x )
void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) { void Builtins::Generate_MathAtan(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Atan); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Atan);
} }
// ES6 section 20.2.2.7 Math.atanh ( x ) // ES6 section 20.2.2.7 Math.atanh ( x )
void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) { void Builtins::Generate_MathAtanh(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Atanh); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Atanh);
} }
// ES6 section 20.2.2.8 Math.atan2 ( y, x ) // 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; using compiler::Node;
CodeStubAssembler assembler(state);
Node* y = assembler->Parameter(1); Node* y = assembler.Parameter(1);
Node* x = assembler->Parameter(2); Node* x = assembler.Parameter(2);
Node* context = assembler->Parameter(5); Node* context = assembler.Parameter(5);
Node* y_value = assembler->TruncateTaggedToFloat64(context, y); Node* y_value = assembler.TruncateTaggedToFloat64(context, y);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x); Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
Node* value = assembler->Float64Atan2(y_value, x_value); Node* value = assembler.Float64Atan2(y_value, x_value);
Node* result = assembler->AllocateHeapNumberWithValue(value); Node* result = assembler.AllocateHeapNumberWithValue(value);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 20.2.2.10 Math.ceil ( x ) // ES6 section 20.2.2.10 Math.ceil ( x )
void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) { void Builtins::Generate_MathCeil(compiler::CodeAssemblerState* state) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil); CodeStubAssembler assembler(state);
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Ceil);
} }
// ES6 section 20.2.2.9 Math.cbrt ( x ) // ES6 section 20.2.2.9 Math.cbrt ( x )
void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) { void Builtins::Generate_MathCbrt(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cbrt); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Cbrt);
} }
// ES6 section 20.2.2.11 Math.clz32 ( x ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler assembler(state);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
// Shared entry point for the clz32 operation. // Shared entry point for the clz32 operation.
Variable var_clz32_x(assembler, MachineRepresentation::kWord32); Variable var_clz32_x(&assembler, MachineRepresentation::kWord32);
Label do_clz32(assembler); Label do_clz32(&assembler);
// We might need to loop once for ToNumber conversion. // We might need to loop once for ToNumber conversion.
Variable var_x(assembler, MachineRepresentation::kTagged); Variable var_x(&assembler, MachineRepresentation::kTagged);
Label loop(assembler, &var_x); Label loop(&assembler, &var_x);
var_x.Bind(assembler->Parameter(1)); var_x.Bind(assembler.Parameter(1));
assembler->Goto(&loop); assembler.Goto(&loop);
assembler->Bind(&loop); assembler.Bind(&loop);
{ {
// Load the current {x} value. // Load the current {x} value.
Node* x = var_x.value(); Node* x = var_x.value();
// Check if {x} is a Smi or a HeapObject. // Check if {x} is a Smi or a HeapObject.
Label if_xissmi(assembler), if_xisnotsmi(assembler); Label if_xissmi(&assembler), if_xisnotsmi(&assembler);
assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi); assembler.Branch(assembler.TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
assembler->Bind(&if_xissmi); assembler.Bind(&if_xissmi);
{ {
var_clz32_x.Bind(assembler->SmiToWord32(x)); var_clz32_x.Bind(assembler.SmiToWord32(x));
assembler->Goto(&do_clz32); assembler.Goto(&do_clz32);
} }
assembler->Bind(&if_xisnotsmi); assembler.Bind(&if_xisnotsmi);
{ {
// Check if {x} is a HeapNumber. // Check if {x} is a HeapNumber.
Label if_xisheapnumber(assembler), Label if_xisheapnumber(&assembler),
if_xisnotheapnumber(assembler, Label::kDeferred); if_xisnotheapnumber(&assembler, Label::kDeferred);
assembler->Branch( assembler.Branch(assembler.WordEqual(assembler.LoadMap(x),
assembler->WordEqual(assembler->LoadMap(x), assembler.HeapNumberMapConstant()),
assembler->HeapNumberMapConstant()), &if_xisheapnumber, &if_xisnotheapnumber);
&if_xisheapnumber, &if_xisnotheapnumber);
assembler->Bind(&if_xisheapnumber); assembler.Bind(&if_xisheapnumber);
{ {
var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x)); var_clz32_x.Bind(assembler.TruncateHeapNumberValueToWord32(x));
assembler->Goto(&do_clz32); assembler.Goto(&do_clz32);
} }
assembler->Bind(&if_xisnotheapnumber); assembler.Bind(&if_xisnotheapnumber);
{ {
// Need to convert {x} to a Number first. // Need to convert {x} to a Number first.
Callable callable = Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate());
CodeFactory::NonNumberToNumber(assembler->isolate()); var_x.Bind(assembler.CallStub(callable, context, x));
var_x.Bind(assembler->CallStub(callable, context, x)); assembler.Goto(&loop);
assembler->Goto(&loop);
} }
} }
} }
assembler->Bind(&do_clz32); assembler.Bind(&do_clz32);
{ {
Node* x_value = var_clz32_x.value(); Node* x_value = var_clz32_x.value();
Node* value = assembler->Word32Clz(x_value); Node* value = assembler.Word32Clz(x_value);
Node* result = assembler->ChangeInt32ToTagged(value); Node* result = assembler.ChangeInt32ToTagged(value);
assembler->Return(result); assembler.Return(result);
} }
} }
// ES6 section 20.2.2.12 Math.cos ( x ) // ES6 section 20.2.2.12 Math.cos ( x )
void Builtins::Generate_MathCos(CodeStubAssembler* assembler) { void Builtins::Generate_MathCos(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cos); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Cos);
} }
// ES6 section 20.2.2.13 Math.cosh ( x ) // ES6 section 20.2.2.13 Math.cosh ( x )
void Builtins::Generate_MathCosh(CodeStubAssembler* assembler) { void Builtins::Generate_MathCosh(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cosh); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Cosh);
} }
// ES6 section 20.2.2.14 Math.exp ( x ) // ES6 section 20.2.2.14 Math.exp ( x )
void Builtins::Generate_MathExp(CodeStubAssembler* assembler) { void Builtins::Generate_MathExp(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Exp); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Exp);
} }
// ES6 section 20.2.2.15 Math.expm1 ( x ) // ES6 section 20.2.2.15 Math.expm1 ( x )
void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) { void Builtins::Generate_MathExpm1(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Expm1); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Expm1);
} }
// ES6 section 20.2.2.16 Math.floor ( x ) // ES6 section 20.2.2.16 Math.floor ( x )
void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) { void Builtins::Generate_MathFloor(compiler::CodeAssemblerState* state) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor); CodeStubAssembler assembler(state);
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Floor);
} }
// ES6 section 20.2.2.17 Math.fround ( x ) // 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; using compiler::Node;
CodeStubAssembler assembler(state);
Node* x = assembler->Parameter(1); Node* x = assembler.Parameter(1);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x); Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
Node* value32 = assembler->TruncateFloat64ToFloat32(x_value); Node* value32 = assembler.TruncateFloat64ToFloat32(x_value);
Node* value = assembler->ChangeFloat32ToFloat64(value32); Node* value = assembler.ChangeFloat32ToFloat64(value32);
Node* result = assembler->AllocateHeapNumberWithValue(value); Node* result = assembler.AllocateHeapNumberWithValue(value);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values ) // 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 ) // 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; using compiler::Node;
CodeStubAssembler assembler(state);
Node* x = assembler->Parameter(1); Node* x = assembler.Parameter(1);
Node* y = assembler->Parameter(2); Node* y = assembler.Parameter(2);
Node* context = assembler->Parameter(5); Node* context = assembler.Parameter(5);
Node* x_value = assembler->TruncateTaggedToWord32(context, x); Node* x_value = assembler.TruncateTaggedToWord32(context, x);
Node* y_value = assembler->TruncateTaggedToWord32(context, y); Node* y_value = assembler.TruncateTaggedToWord32(context, y);
Node* value = assembler->Int32Mul(x_value, y_value); Node* value = assembler.Int32Mul(x_value, y_value);
Node* result = assembler->ChangeInt32ToTagged(value); Node* result = assembler.ChangeInt32ToTagged(value);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 20.2.2.20 Math.log ( x ) // ES6 section 20.2.2.20 Math.log ( x )
void Builtins::Generate_MathLog(CodeStubAssembler* assembler) { void Builtins::Generate_MathLog(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log);
} }
// ES6 section 20.2.2.21 Math.log1p ( x ) // ES6 section 20.2.2.21 Math.log1p ( x )
void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) { void Builtins::Generate_MathLog1p(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log1p); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log1p);
} }
// ES6 section 20.2.2.22 Math.log10 ( x ) // ES6 section 20.2.2.22 Math.log10 ( x )
void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) { void Builtins::Generate_MathLog10(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log10); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log10);
} }
// ES6 section 20.2.2.23 Math.log2 ( x ) // ES6 section 20.2.2.23 Math.log2 ( x )
void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) { void Builtins::Generate_MathLog2(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log2); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Log2);
} }
// ES6 section 20.2.2.26 Math.pow ( x, y ) // 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; using compiler::Node;
CodeStubAssembler assembler(state);
Node* x = assembler->Parameter(1); Node* x = assembler.Parameter(1);
Node* y = assembler->Parameter(2); Node* y = assembler.Parameter(2);
Node* context = assembler->Parameter(5); Node* context = assembler.Parameter(5);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x); Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
Node* y_value = assembler->TruncateTaggedToFloat64(context, y); Node* y_value = assembler.TruncateTaggedToFloat64(context, y);
Node* value = assembler->Float64Pow(x_value, y_value); Node* value = assembler.Float64Pow(x_value, y_value);
Node* result = assembler->ChangeFloat64ToTagged(value); Node* result = assembler.ChangeFloat64ToTagged(value);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 20.2.2.27 Math.random ( ) // ES6 section 20.2.2.27 Math.random ( )
void Builtins::Generate_MathRandom(CodeStubAssembler* assembler) { void Builtins::Generate_MathRandom(compiler::CodeAssemblerState* state) {
using compiler::Node; using compiler::Node;
CodeStubAssembler assembler(state);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* native_context = assembler->LoadNativeContext(context); Node* native_context = assembler.LoadNativeContext(context);
// Load cache index. // Load cache index.
CodeStubAssembler::Variable smi_index(assembler, CodeStubAssembler::Variable smi_index(&assembler,
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
smi_index.Bind(assembler->LoadContextElement( smi_index.Bind(assembler.LoadContextElement(
native_context, Context::MATH_RANDOM_INDEX_INDEX)); native_context, Context::MATH_RANDOM_INDEX_INDEX));
// Cached random numbers are exhausted if index is 0. Go to slow path. // Cached random numbers are exhausted if index is 0. Go to slow path.
CodeStubAssembler::Label if_cached(assembler); CodeStubAssembler::Label if_cached(&assembler);
assembler->GotoIf(assembler->SmiAbove(smi_index.value(), assembler.GotoIf(
assembler->SmiConstant(Smi::kZero)), assembler.SmiAbove(smi_index.value(), assembler.SmiConstant(Smi::kZero)),
&if_cached); &if_cached);
// Cache exhausted, populate the cache. Return value is the new index. // Cache exhausted, populate the cache. Return value is the new index.
smi_index.Bind( smi_index.Bind(
assembler->CallRuntime(Runtime::kGenerateRandomNumbers, context)); assembler.CallRuntime(Runtime::kGenerateRandomNumbers, context));
assembler->Goto(&if_cached); assembler.Goto(&if_cached);
// Compute next index by decrement. // Compute next index by decrement.
assembler->Bind(&if_cached); assembler.Bind(&if_cached);
Node* new_smi_index = assembler->SmiSub( Node* new_smi_index = assembler.SmiSub(
smi_index.value(), assembler->SmiConstant(Smi::FromInt(1))); smi_index.value(), assembler.SmiConstant(Smi::FromInt(1)));
assembler->StoreContextElement( assembler.StoreContextElement(
native_context, Context::MATH_RANDOM_INDEX_INDEX, new_smi_index); native_context, Context::MATH_RANDOM_INDEX_INDEX, new_smi_index);
// Load and return next cached random number. // Load and return next cached random number.
Node* array = assembler->LoadContextElement(native_context, Node* array = assembler.LoadContextElement(native_context,
Context::MATH_RANDOM_CACHE_INDEX); Context::MATH_RANDOM_CACHE_INDEX);
Node* random = assembler->LoadFixedDoubleArrayElement( Node* random = assembler.LoadFixedDoubleArrayElement(
array, new_smi_index, MachineType::Float64(), 0, array, new_smi_index, MachineType::Float64(), 0,
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
assembler->Return(assembler->AllocateHeapNumberWithValue(random)); assembler.Return(assembler.AllocateHeapNumberWithValue(random));
} }
// ES6 section 20.2.2.28 Math.round ( x ) // ES6 section 20.2.2.28 Math.round ( x )
void Builtins::Generate_MathRound(CodeStubAssembler* assembler) { void Builtins::Generate_MathRound(compiler::CodeAssemblerState* state) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round); CodeStubAssembler assembler(state);
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Round);
} }
// ES6 section 20.2.2.29 Math.sign ( x ) // 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; typedef CodeStubAssembler::Label Label;
using compiler::Node; using compiler::Node;
CodeStubAssembler assembler(state);
// Convert the {x} value to a Number. // Convert the {x} value to a Number.
Node* x = assembler->Parameter(1); Node* x = assembler.Parameter(1);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
Node* x_value = assembler->TruncateTaggedToFloat64(context, x); Node* x_value = assembler.TruncateTaggedToFloat64(context, x);
// Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself. // Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself.
Label if_xisnegative(assembler), if_xispositive(assembler); Label if_xisnegative(&assembler), if_xispositive(&assembler);
assembler->GotoIf( assembler.GotoIf(
assembler->Float64LessThan(x_value, assembler->Float64Constant(0.0)), assembler.Float64LessThan(x_value, assembler.Float64Constant(0.0)),
&if_xisnegative); &if_xisnegative);
assembler->GotoIf( assembler.GotoIf(
assembler->Float64LessThan(assembler->Float64Constant(0.0), x_value), assembler.Float64LessThan(assembler.Float64Constant(0.0), x_value),
&if_xispositive); &if_xispositive);
assembler->Return(assembler->ChangeFloat64ToTagged(x_value)); assembler.Return(assembler.ChangeFloat64ToTagged(x_value));
assembler->Bind(&if_xisnegative); assembler.Bind(&if_xisnegative);
assembler->Return(assembler->SmiConstant(Smi::FromInt(-1))); assembler.Return(assembler.SmiConstant(Smi::FromInt(-1)));
assembler->Bind(&if_xispositive); assembler.Bind(&if_xispositive);
assembler->Return(assembler->SmiConstant(Smi::FromInt(1))); assembler.Return(assembler.SmiConstant(Smi::FromInt(1)));
} }
// ES6 section 20.2.2.30 Math.sin ( x ) // ES6 section 20.2.2.30 Math.sin ( x )
void Builtins::Generate_MathSin(CodeStubAssembler* assembler) { void Builtins::Generate_MathSin(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sin); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Sin);
} }
// ES6 section 20.2.2.31 Math.sinh ( x ) // ES6 section 20.2.2.31 Math.sinh ( x )
void Builtins::Generate_MathSinh(CodeStubAssembler* assembler) { void Builtins::Generate_MathSinh(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sinh); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Sinh);
} }
// ES6 section 20.2.2.32 Math.sqrt ( x ) // ES6 section 20.2.2.32 Math.sqrt ( x )
void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) { void Builtins::Generate_MathSqrt(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sqrt); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Sqrt);
} }
// ES6 section 20.2.2.33 Math.tan ( x ) // ES6 section 20.2.2.33 Math.tan ( x )
void Builtins::Generate_MathTan(CodeStubAssembler* assembler) { void Builtins::Generate_MathTan(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Tan); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Tan);
} }
// ES6 section 20.2.2.34 Math.tanh ( x ) // ES6 section 20.2.2.34 Math.tanh ( x )
void Builtins::Generate_MathTanh(CodeStubAssembler* assembler) { void Builtins::Generate_MathTanh(compiler::CodeAssemblerState* state) {
Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Tanh); CodeStubAssembler assembler(state);
Generate_MathUnaryOperation(&assembler, &CodeStubAssembler::Float64Tanh);
} }
// ES6 section 20.2.2.35 Math.trunc ( x ) // ES6 section 20.2.2.35 Math.trunc ( x )
void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) { void Builtins::Generate_MathTrunc(compiler::CodeAssemblerState* state) {
Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc); CodeStubAssembler assembler(state);
Generate_MathRoundingOperation(&assembler, &CodeStubAssembler::Float64Trunc);
} }
void Builtins::Generate_MathMax(MacroAssembler* masm) { 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 // ES6 section 19.1 Object Objects
void Builtins::Generate_ObjectHasOwnProperty(CodeStubAssembler* assembler) { void Builtins::Generate_ObjectHasOwnProperty(
compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler assembler(state);
Node* object = assembler->Parameter(0); Node* object = assembler.Parameter(0);
Node* key = assembler->Parameter(1); Node* key = assembler.Parameter(1);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
Label call_runtime(assembler), return_true(assembler), Label call_runtime(&assembler), return_true(&assembler),
return_false(assembler); return_false(&assembler);
// Smi receivers do not have own properties. // Smi receivers do not have own properties.
Label if_objectisnotsmi(assembler); Label if_objectisnotsmi(&assembler);
assembler->Branch(assembler->TaggedIsSmi(object), &return_false, assembler.Branch(assembler.TaggedIsSmi(object), &return_false,
&if_objectisnotsmi); &if_objectisnotsmi);
assembler->Bind(&if_objectisnotsmi); assembler.Bind(&if_objectisnotsmi);
Node* map = assembler->LoadMap(object); Node* map = assembler.LoadMap(object);
Node* instance_type = assembler->LoadMapInstanceType(map); Node* instance_type = assembler.LoadMapInstanceType(map);
Variable var_index(assembler, MachineType::PointerRepresentation()); Variable var_index(&assembler, MachineType::PointerRepresentation());
Label keyisindex(assembler), if_iskeyunique(assembler); Label keyisindex(&assembler), if_iskeyunique(&assembler);
assembler->TryToName(key, &keyisindex, &var_index, &if_iskeyunique, assembler.TryToName(key, &keyisindex, &var_index, &if_iskeyunique,
&call_runtime); &call_runtime);
assembler->Bind(&if_iskeyunique); assembler.Bind(&if_iskeyunique);
assembler->TryHasOwnProperty(object, map, instance_type, key, &return_true, assembler.TryHasOwnProperty(object, map, instance_type, key, &return_true,
&return_false, &call_runtime); &return_false, &call_runtime);
assembler->Bind(&keyisindex); assembler.Bind(&keyisindex);
assembler->TryLookupElement(object, map, instance_type, var_index.value(), assembler.TryLookupElement(object, map, instance_type, var_index.value(),
&return_true, &return_false, &call_runtime); &return_true, &return_false, &call_runtime);
assembler->Bind(&return_true); assembler.Bind(&return_true);
assembler->Return(assembler->BooleanConstant(true)); assembler.Return(assembler.BooleanConstant(true));
assembler->Bind(&return_false); assembler.Bind(&return_false);
assembler->Return(assembler->BooleanConstant(false)); assembler.Return(assembler.BooleanConstant(false));
assembler->Bind(&call_runtime); assembler.Bind(&call_runtime);
assembler->Return(assembler->CallRuntime(Runtime::kObjectHasOwnProperty, assembler.Return(assembler.CallRuntime(Runtime::kObjectHasOwnProperty,
context, object, key)); context, object, key));
} }
namespace { namespace {
@ -273,76 +275,78 @@ void ReturnIfPrimitive(CodeStubAssembler* assembler,
} // namespace } // namespace
// ES6 section 19.1.3.6 Object.prototype.toString // 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 compiler::Node Node;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler assembler(state);
Label return_undefined(assembler, Label::kDeferred), Label return_undefined(&assembler, Label::kDeferred),
return_null(assembler, Label::kDeferred), return_null(&assembler, Label::kDeferred),
return_arguments(assembler, Label::kDeferred), return_array(assembler), return_arguments(&assembler, Label::kDeferred), return_array(&assembler),
return_api(assembler, Label::kDeferred), return_object(assembler), return_api(&assembler, Label::kDeferred), return_object(&assembler),
return_regexp(assembler), return_function(assembler), return_regexp(&assembler), return_function(&assembler),
return_error(assembler), return_date(assembler), return_string(assembler), return_error(&assembler), return_date(&assembler),
return_boolean(assembler), return_jsvalue(assembler), return_string(&assembler), return_boolean(&assembler),
return_jsproxy(assembler, Label::kDeferred), return_number(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 checkstringtag(&assembler);
Label if_tostringtag(assembler), if_notostringtag(assembler); Label if_tostringtag(&assembler), if_notostringtag(&assembler);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
assembler->GotoIf( assembler.GotoIf(assembler.WordEqual(receiver, assembler.UndefinedConstant()),
assembler->WordEqual(receiver, assembler->UndefinedConstant()), &return_undefined);
&return_undefined);
assembler->GotoIf(assembler->WordEqual(receiver, assembler->NullConstant()), assembler.GotoIf(assembler.WordEqual(receiver, assembler.NullConstant()),
&return_null); &return_null);
assembler->GotoIf(assembler->TaggedIsSmi(receiver), &return_number); assembler.GotoIf(assembler.TaggedIsSmi(receiver), &return_number);
Node* receiver_instance_type = assembler->LoadInstanceType(receiver); Node* receiver_instance_type = assembler.LoadInstanceType(receiver);
ReturnIfPrimitive(assembler, receiver_instance_type, &return_string, ReturnIfPrimitive(&assembler, receiver_instance_type, &return_string,
&return_boolean, &return_number); &return_boolean, &return_number);
// for proxies, check IsArray before getting @@toStringTag // for proxies, check IsArray before getting @@toStringTag
Variable var_proxy_is_array(assembler, MachineRepresentation::kTagged); Variable var_proxy_is_array(&assembler, MachineRepresentation::kTagged);
var_proxy_is_array.Bind(assembler->BooleanConstant(false)); var_proxy_is_array.Bind(assembler.BooleanConstant(false));
assembler->Branch( assembler.Branch(
assembler->Word32Equal(receiver_instance_type, assembler.Word32Equal(receiver_instance_type,
assembler->Int32Constant(JS_PROXY_TYPE)), assembler.Int32Constant(JS_PROXY_TYPE)),
&if_isproxy, &checkstringtag); &if_isproxy, &checkstringtag);
assembler->Bind(&if_isproxy); assembler.Bind(&if_isproxy);
{ {
// This can throw // This can throw
var_proxy_is_array.Bind( var_proxy_is_array.Bind(
assembler->CallRuntime(Runtime::kArrayIsArray, context, receiver)); assembler.CallRuntime(Runtime::kArrayIsArray, context, receiver));
assembler->Goto(&checkstringtag); assembler.Goto(&checkstringtag);
} }
assembler->Bind(&checkstringtag); assembler.Bind(&checkstringtag);
{ {
Node* to_string_tag_symbol = assembler->HeapConstant( Node* to_string_tag_symbol = assembler.HeapConstant(
assembler->isolate()->factory()->to_string_tag_symbol()); assembler.isolate()->factory()->to_string_tag_symbol());
GetPropertyStub stub(assembler->isolate()); GetPropertyStub stub(assembler.isolate());
Callable get_property = Callable get_property =
Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor()); 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); 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); &if_notostringtag);
assembler->Bind(&if_tostringtag); assembler.Bind(&if_tostringtag);
ReturnToStringFormat(assembler, context, to_string_tag_value); ReturnToStringFormat(&assembler, context, to_string_tag_value);
} }
assembler->Bind(&if_notostringtag); assembler.Bind(&if_notostringtag);
{ {
size_t const kNumCases = 11; size_t const kNumCases = 11;
Label* case_labels[kNumCases]; Label* case_labels[kNumCases];
@ -370,178 +374,179 @@ void Builtins::Generate_ObjectProtoToString(CodeStubAssembler* assembler) {
case_labels[10] = &return_jsproxy; case_labels[10] = &return_jsproxy;
case_values[10] = JS_PROXY_TYPE; case_values[10] = JS_PROXY_TYPE;
assembler->Switch(receiver_instance_type, &return_object, case_values, assembler.Switch(receiver_instance_type, &return_object, case_values,
case_labels, arraysize(case_values)); case_labels, arraysize(case_values));
assembler->Bind(&return_undefined); assembler.Bind(&return_undefined);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->undefined_to_string())); assembler.isolate()->factory()->undefined_to_string()));
assembler->Bind(&return_null); assembler.Bind(&return_null);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->null_to_string())); assembler.isolate()->factory()->null_to_string()));
assembler->Bind(&return_number); assembler.Bind(&return_number);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->number_to_string())); assembler.isolate()->factory()->number_to_string()));
assembler->Bind(&return_string); assembler.Bind(&return_string);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->string_to_string())); assembler.isolate()->factory()->string_to_string()));
assembler->Bind(&return_boolean); assembler.Bind(&return_boolean);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->boolean_to_string())); assembler.isolate()->factory()->boolean_to_string()));
assembler->Bind(&return_arguments); assembler.Bind(&return_arguments);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->arguments_to_string())); assembler.isolate()->factory()->arguments_to_string()));
assembler->Bind(&return_array); assembler.Bind(&return_array);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->array_to_string())); assembler.isolate()->factory()->array_to_string()));
assembler->Bind(&return_function); assembler.Bind(&return_function);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->function_to_string())); assembler.isolate()->factory()->function_to_string()));
assembler->Bind(&return_error); assembler.Bind(&return_error);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->error_to_string())); assembler.isolate()->factory()->error_to_string()));
assembler->Bind(&return_date); assembler.Bind(&return_date);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->date_to_string())); assembler.isolate()->factory()->date_to_string()));
assembler->Bind(&return_regexp); assembler.Bind(&return_regexp);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->regexp_to_string())); assembler.isolate()->factory()->regexp_to_string()));
assembler->Bind(&return_api); assembler.Bind(&return_api);
{ {
Node* class_name = Node* class_name =
assembler->CallRuntime(Runtime::kClassOf, context, receiver); assembler.CallRuntime(Runtime::kClassOf, context, receiver);
ReturnToStringFormat(assembler, context, class_name); ReturnToStringFormat(&assembler, context, class_name);
} }
assembler->Bind(&return_jsvalue); assembler.Bind(&return_jsvalue);
{ {
Node* value = assembler->LoadJSValueValue(receiver); Node* value = assembler.LoadJSValueValue(receiver);
assembler->GotoIf(assembler->TaggedIsSmi(value), &return_number); assembler.GotoIf(assembler.TaggedIsSmi(value), &return_number);
ReturnIfPrimitive(assembler, assembler->LoadInstanceType(value), ReturnIfPrimitive(&assembler, assembler.LoadInstanceType(value),
&return_string, &return_boolean, &return_number); &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.GotoIf(assembler.WordEqual(var_proxy_is_array.value(),
assembler->BooleanConstant(true)), assembler.BooleanConstant(true)),
&return_array); &return_array);
Node* map = assembler->LoadMap(receiver); Node* map = assembler.LoadMap(receiver);
// Return object if the proxy {receiver} is not callable. // Return object if the proxy {receiver} is not callable.
assembler->Branch(assembler->IsCallableMap(map), &return_function, assembler.Branch(assembler.IsCallableMap(map), &return_function,
&return_object); &return_object);
} }
// Default // Default
assembler->Bind(&return_object); assembler.Bind(&return_object);
assembler->Return(assembler->HeapConstant( assembler.Return(assembler.HeapConstant(
assembler->isolate()->factory()->object_to_string())); assembler.isolate()->factory()->object_to_string()));
} }
} }
void Builtins::Generate_ObjectCreate(CodeStubAssembler* a) { void Builtins::Generate_ObjectCreate(compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler a(state);
Node* prototype = a->Parameter(1); Node* prototype = a.Parameter(1);
Node* properties = a->Parameter(2); Node* properties = a.Parameter(2);
Node* context = a->Parameter(3 + 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.Comment("Argument 1 check: prototype");
a->GotoIf(a->WordEqual(prototype, a->NullConstant()), &prototype_valid); a.GotoIf(a.WordEqual(prototype, a.NullConstant()), &prototype_valid);
a->BranchIfJSReceiver(prototype, &prototype_valid, &call_runtime); 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 // 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. // Undefined implies no properties.
a->GotoIf(a->WordEqual(properties, a->UndefinedConstant()), &no_properties); a.GotoIf(a.WordEqual(properties, a.UndefinedConstant()), &no_properties);
Node* properties_map = a->LoadMap(properties); Node* properties_map = a.LoadMap(properties);
a->GotoIf(a->IsSpecialReceiverMap(properties_map), &call_runtime); a.GotoIf(a.IsSpecialReceiverMap(properties_map), &call_runtime);
// Stay on the fast path only if there are no elements. // Stay on the fast path only if there are no elements.
a->GotoUnless(a->WordEqual(a->LoadElements(properties), a.GotoUnless(a.WordEqual(a.LoadElements(properties),
a->LoadRoot(Heap::kEmptyFixedArrayRootIndex)), a.LoadRoot(Heap::kEmptyFixedArrayRootIndex)),
&call_runtime); &call_runtime);
// Handle dictionary objects or fast objects with properties in runtime. // Handle dictionary objects or fast objects with properties in runtime.
Node* bit_field3 = a->LoadMapBitField3(properties_map); Node* bit_field3 = a.LoadMapBitField3(properties_map);
a->GotoIf(a->IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime); a.GotoIf(a.IsSetWord32<Map::DictionaryMap>(bit_field3), &call_runtime);
a->Branch(a->IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3), a.Branch(a.IsSetWord32<Map::NumberOfOwnDescriptorsBits>(bit_field3),
&call_runtime, &no_properties); &call_runtime, &no_properties);
} }
// Create a new object with the given prototype. // Create a new object with the given prototype.
a->Bind(&no_properties); a.Bind(&no_properties);
{ {
Variable map(a, MachineRepresentation::kTagged); Variable map(&a, MachineRepresentation::kTagged);
Variable properties(a, MachineRepresentation::kTagged); Variable properties(&a, MachineRepresentation::kTagged);
Label non_null_proto(a), instantiate_map(a), good(a); Label non_null_proto(&a), instantiate_map(&a), good(&a);
a->Branch(a->WordEqual(prototype, a->NullConstant()), &good, a.Branch(a.WordEqual(prototype, a.NullConstant()), &good, &non_null_proto);
&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)); context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP));
properties.Bind( properties.Bind(
a->AllocateNameDictionary(NameDictionary::kInitialCapacity)); a.AllocateNameDictionary(NameDictionary::kInitialCapacity));
a->Goto(&instantiate_map); 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 = Node* object_function =
a->LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX); a.LoadContextElement(context, Context::OBJECT_FUNCTION_INDEX);
Node* object_function_map = a->LoadObjectField( Node* object_function_map = a.LoadObjectField(
object_function, JSFunction::kPrototypeOrInitialMapOffset); object_function, JSFunction::kPrototypeOrInitialMapOffset);
map.Bind(object_function_map); map.Bind(object_function_map);
a->GotoIf(a->WordEqual(prototype, a->LoadMapPrototype(map.value())), a.GotoIf(a.WordEqual(prototype, a.LoadMapPrototype(map.value())),
&instantiate_map); &instantiate_map);
// Try loading the prototype info. // Try loading the prototype info.
Node* prototype_info = Node* prototype_info =
a->LoadMapPrototypeInfo(a->LoadMap(prototype), &call_runtime); a.LoadMapPrototypeInfo(a.LoadMap(prototype), &call_runtime);
a->Comment("Load ObjectCreateMap from PrototypeInfo"); a.Comment("Load ObjectCreateMap from PrototypeInfo");
Node* weak_cell = Node* weak_cell =
a->LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap); a.LoadObjectField(prototype_info, PrototypeInfo::kObjectCreateMap);
a->GotoIf(a->WordEqual(weak_cell, a->UndefinedConstant()), &call_runtime); a.GotoIf(a.WordEqual(weak_cell, a.UndefinedConstant()), &call_runtime);
map.Bind(a->LoadWeakCellValue(weak_cell, &call_runtime)); map.Bind(a.LoadWeakCellValue(weak_cell, &call_runtime));
a->Goto(&instantiate_map); a.Goto(&instantiate_map);
} }
a->Bind(&instantiate_map); a.Bind(&instantiate_map);
{ {
Node* instance = Node* instance =
a->AllocateJSObjectFromMap(map.value(), properties.value()); a.AllocateJSObjectFromMap(map.value(), properties.value());
a->Return(instance); a.Return(instance);
} }
} }
a->Bind(&call_runtime); a.Bind(&call_runtime);
{ {
a->Return( a.Return(
a->CallRuntime(Runtime::kObjectCreate, context, prototype, properties)); a.CallRuntime(Runtime::kObjectCreate, context, prototype, properties));
} }
} }
@ -1018,37 +1023,41 @@ BUILTIN(ObjectSeal) {
return *object; return *object;
} }
void Builtins::Generate_HasProperty(CodeStubAssembler* assembler) { void Builtins::Generate_HasProperty(compiler::CodeAssemblerState* state) {
typedef HasPropertyDescriptor Descriptor; typedef HasPropertyDescriptor Descriptor;
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* key = assembler->Parameter(Descriptor::kKey); Node* key = assembler.Parameter(Descriptor::kKey);
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler.Parameter(Descriptor::kObject);
Node* context = assembler->Parameter(Descriptor::kContext); Node* context = assembler.Parameter(Descriptor::kContext);
assembler->Return( assembler.Return(
assembler->HasProperty(object, key, context, Runtime::kHasProperty)); 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 compiler::Node Node;
typedef ForInFilterDescriptor Descriptor; typedef ForInFilterDescriptor Descriptor;
CodeStubAssembler assembler(state);
Node* key = assembler->Parameter(Descriptor::kKey); Node* key = assembler.Parameter(Descriptor::kKey);
Node* object = assembler->Parameter(Descriptor::kObject); Node* object = assembler.Parameter(Descriptor::kObject);
Node* context = assembler->Parameter(Descriptor::kContext); 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 compiler::Node Node;
typedef CompareDescriptor Descriptor; typedef CompareDescriptor Descriptor;
Node* object = assembler->Parameter(Descriptor::kLeft); CodeStubAssembler assembler(state);
Node* callable = assembler->Parameter(Descriptor::kRight);
Node* context = assembler->Parameter(Descriptor::kContext);
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 } // namespace internal

View File

@ -481,16 +481,18 @@ compiler::Node* RegExpPrototypeExecInternal(CodeStubAssembler* a,
// ES#sec-regexp.prototype.exec // ES#sec-regexp.prototype.exec
// RegExp.prototype.exec ( string ) // RegExp.prototype.exec ( string )
void Builtins::Generate_RegExpPrototypeExec(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeExec(
compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler a(state);
Node* const maybe_receiver = a->Parameter(0); Node* const maybe_receiver = a.Parameter(0);
Node* const maybe_string = a->Parameter(1); Node* const maybe_string = a.Parameter(1);
Node* const context = a->Parameter(4); Node* const context = a.Parameter(4);
Node* const result = Node* const result =
RegExpPrototypeExecInternal(a, context, maybe_receiver, maybe_string); RegExpPrototypeExecInternal(&a, context, maybe_receiver, maybe_string);
a->Return(result); a.Return(result);
} }
namespace { namespace {
@ -585,58 +587,59 @@ void BranchIfFastPath(CodeStubAssembler* a, compiler::Node* context,
} // namespace } // namespace
void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeFlagsGetter(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler a(state);
Node* const receiver = a->Parameter(0); Node* const receiver = a.Parameter(0);
Node* const context = a->Parameter(3); Node* const context = a.Parameter(3);
Isolate* isolate = a->isolate(); Isolate* isolate = a.isolate();
Node* const int_zero = a->IntPtrConstant(0); Node* const int_zero = a.IntPtrConstant(0);
Node* const int_one = a->IntPtrConstant(1); 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, MessageTemplate::kRegExpNonObject,
"RegExp.prototype.flags"); "RegExp.prototype.flags");
Variable var_length(a, MachineType::PointerRepresentation()); Variable var_length(&a, MachineType::PointerRepresentation());
Variable var_flags(a, MachineType::PointerRepresentation()); Variable var_flags(&a, MachineType::PointerRepresentation());
// First, count the number of characters we will need and check which flags // First, count the number of characters we will need and check which flags
// are set. // are set.
var_length.Bind(int_zero); var_length.Bind(int_zero);
Label if_isunmodifiedjsregexp(a), Label if_isunmodifiedjsregexp(&a),
if_isnotunmodifiedjsregexp(a, Label::kDeferred); if_isnotunmodifiedjsregexp(&a, Label::kDeferred);
a->Branch(IsInitialRegExpMap(a, context, map), &if_isunmodifiedjsregexp, a.Branch(IsInitialRegExpMap(&a, context, map), &if_isunmodifiedjsregexp,
&if_isnotunmodifiedjsregexp); &if_isnotunmodifiedjsregexp);
Label construct_string(a); Label construct_string(&a);
a->Bind(&if_isunmodifiedjsregexp); a.Bind(&if_isunmodifiedjsregexp);
{ {
// Refer to JSRegExp's flag property on the fast-path. // Refer to JSRegExp's flag property on the fast-path.
Node* const flags_smi = Node* const flags_smi = a.LoadObjectField(receiver, JSRegExp::kFlagsOffset);
a->LoadObjectField(receiver, JSRegExp::kFlagsOffset); Node* const flags_intptr = a.SmiUntag(flags_smi);
Node* const flags_intptr = a->SmiUntag(flags_smi);
var_flags.Bind(flags_intptr); var_flags.Bind(flags_intptr);
Label label_global(a), label_ignorecase(a), label_multiline(a), Label label_global(&a), label_ignorecase(&a), label_multiline(&a),
label_unicode(a), label_sticky(a); label_unicode(&a), label_sticky(&a);
#define CASE_FOR_FLAG(FLAG, LABEL, NEXT_LABEL) \ #define CASE_FOR_FLAG(FLAG, LABEL, NEXT_LABEL) \
do { \ do { \
a->Bind(&LABEL); \ a.Bind(&LABEL); \
Node* const mask = a->IntPtrConstant(FLAG); \ Node* const mask = a.IntPtrConstant(FLAG); \
a->GotoIf(a->WordEqual(a->WordAnd(flags_intptr, mask), int_zero), \ a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \
&NEXT_LABEL); \ &NEXT_LABEL); \
var_length.Bind(a->IntPtrAdd(var_length.value(), int_one)); \ var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \
a->Goto(&NEXT_LABEL); \ a.Goto(&NEXT_LABEL); \
} while (false) } while (false)
a->Goto(&label_global); a.Goto(&label_global);
CASE_FOR_FLAG(JSRegExp::kGlobal, label_global, label_ignorecase); CASE_FOR_FLAG(JSRegExp::kGlobal, label_global, label_ignorecase);
CASE_FOR_FLAG(JSRegExp::kIgnoreCase, label_ignorecase, label_multiline); CASE_FOR_FLAG(JSRegExp::kIgnoreCase, label_ignorecase, label_multiline);
CASE_FOR_FLAG(JSRegExp::kMultiline, label_multiline, label_unicode); CASE_FOR_FLAG(JSRegExp::kMultiline, label_multiline, label_unicode);
@ -645,31 +648,31 @@ void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) {
#undef CASE_FOR_FLAG #undef CASE_FOR_FLAG
} }
a->Bind(&if_isnotunmodifiedjsregexp); a.Bind(&if_isnotunmodifiedjsregexp);
{ {
// Fall back to GetProperty stub on the slow-path. // Fall back to GetProperty stub on the slow-path.
var_flags.Bind(int_zero); var_flags.Bind(int_zero);
Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); Callable getproperty_callable = CodeFactory::GetProperty(a.isolate());
Label label_global(a), label_ignorecase(a), label_multiline(a), Label label_global(&a), label_ignorecase(&a), label_multiline(&a),
label_unicode(a), label_sticky(a); label_unicode(&a), label_sticky(&a);
#define CASE_FOR_FLAG(NAME, FLAG, LABEL, NEXT_LABEL) \ #define CASE_FOR_FLAG(NAME, FLAG, LABEL, NEXT_LABEL) \
do { \ do { \
a->Bind(&LABEL); \ a.Bind(&LABEL); \
Node* const name = \ Node* const name = \
a->HeapConstant(isolate->factory()->NewStringFromAsciiChecked(NAME)); \ a.HeapConstant(isolate->factory()->NewStringFromAsciiChecked(NAME)); \
Node* const flag = \ Node* const flag = \
a->CallStub(getproperty_callable, context, receiver, name); \ a.CallStub(getproperty_callable, context, receiver, name); \
Label if_isflagset(a); \ Label if_isflagset(&a); \
a->BranchIfToBooleanIsTrue(flag, &if_isflagset, &NEXT_LABEL); \ a.BranchIfToBooleanIsTrue(flag, &if_isflagset, &NEXT_LABEL); \
a->Bind(&if_isflagset); \ a.Bind(&if_isflagset); \
var_length.Bind(a->IntPtrAdd(var_length.value(), int_one)); \ var_length.Bind(a.IntPtrAdd(var_length.value(), int_one)); \
var_flags.Bind(a->WordOr(var_flags.value(), a->IntPtrConstant(FLAG))); \ var_flags.Bind(a.WordOr(var_flags.value(), a.IntPtrConstant(FLAG))); \
a->Goto(&NEXT_LABEL); \ a.Goto(&NEXT_LABEL); \
} while (false) } while (false)
a->Goto(&label_global); a.Goto(&label_global);
CASE_FOR_FLAG("global", JSRegExp::kGlobal, label_global, label_ignorecase); CASE_FOR_FLAG("global", JSRegExp::kGlobal, label_global, label_ignorecase);
CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase, label_ignorecase, CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase, label_ignorecase,
label_multiline); 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 // Allocate a string of the required length and fill it with the corresponding
// char for each set flag. // char for each set flag.
a->Bind(&construct_string); a.Bind(&construct_string);
{ {
Node* const result = Node* const result =
a->AllocateSeqOneByteString(context, var_length.value()); a.AllocateSeqOneByteString(context, var_length.value());
Node* const flags_intptr = var_flags.value(); Node* const flags_intptr = var_flags.value();
Variable var_offset(a, MachineType::PointerRepresentation()); Variable var_offset(&a, MachineType::PointerRepresentation());
var_offset.Bind( var_offset.Bind(
a->IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag)); a.IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
Label label_global(a), label_ignorecase(a), label_multiline(a), Label label_global(&a), label_ignorecase(&a), label_multiline(&a),
label_unicode(a), label_sticky(a), out(a); label_unicode(&a), label_sticky(&a), out(&a);
#define CASE_FOR_FLAG(FLAG, CHAR, LABEL, NEXT_LABEL) \ #define CASE_FOR_FLAG(FLAG, CHAR, LABEL, NEXT_LABEL) \
do { \ do { \
a->Bind(&LABEL); \ a.Bind(&LABEL); \
Node* const mask = a->IntPtrConstant(FLAG); \ Node* const mask = a.IntPtrConstant(FLAG); \
a->GotoIf(a->WordEqual(a->WordAnd(flags_intptr, mask), int_zero), \ a.GotoIf(a.WordEqual(a.WordAnd(flags_intptr, mask), int_zero), \
&NEXT_LABEL); \ &NEXT_LABEL); \
Node* const value = a->IntPtrConstant(CHAR); \ Node* const value = a.IntPtrConstant(CHAR); \
a->StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ a.StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
var_offset.value(), value); \ var_offset.value(), value); \
var_offset.Bind(a->IntPtrAdd(var_offset.value(), int_one)); \ var_offset.Bind(a.IntPtrAdd(var_offset.value(), int_one)); \
a->Goto(&NEXT_LABEL); \ a.Goto(&NEXT_LABEL); \
} while (false) } while (false)
a->Goto(&label_global); a.Goto(&label_global);
CASE_FOR_FLAG(JSRegExp::kGlobal, 'g', label_global, label_ignorecase); CASE_FOR_FLAG(JSRegExp::kGlobal, 'g', label_global, label_ignorecase);
CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i', label_ignorecase, CASE_FOR_FLAG(JSRegExp::kIgnoreCase, 'i', label_ignorecase,
label_multiline); label_multiline);
@ -718,8 +721,8 @@ void Builtins::Generate_RegExpPrototypeFlagsGetter(CodeStubAssembler* a) {
CASE_FOR_FLAG(JSRegExp::kSticky, 'y', label_sticky, out); CASE_FOR_FLAG(JSRegExp::kSticky, 'y', label_sticky, out);
#undef CASE_FOR_FLAG #undef CASE_FOR_FLAG
a->Bind(&out); a.Bind(&out);
a->Return(result); a.Return(result);
} }
} }
@ -869,36 +872,46 @@ void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
} // namespace } // namespace
// ES6 21.2.5.4. // ES6 21.2.5.4.
void Builtins::Generate_RegExpPrototypeGlobalGetter(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeGlobalGetter(
Generate_FlagGetter(a, JSRegExp::kGlobal, compiler::CodeAssemblerState* state) {
CodeStubAssembler a(state);
Generate_FlagGetter(&a, JSRegExp::kGlobal,
v8::Isolate::kRegExpPrototypeOldFlagGetter, v8::Isolate::kRegExpPrototypeOldFlagGetter,
"RegExp.prototype.global"); "RegExp.prototype.global");
} }
// ES6 21.2.5.5. // ES6 21.2.5.5.
void Builtins::Generate_RegExpPrototypeIgnoreCaseGetter(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeIgnoreCaseGetter(
Generate_FlagGetter(a, JSRegExp::kIgnoreCase, compiler::CodeAssemblerState* state) {
CodeStubAssembler a(state);
Generate_FlagGetter(&a, JSRegExp::kIgnoreCase,
v8::Isolate::kRegExpPrototypeOldFlagGetter, v8::Isolate::kRegExpPrototypeOldFlagGetter,
"RegExp.prototype.ignoreCase"); "RegExp.prototype.ignoreCase");
} }
// ES6 21.2.5.7. // ES6 21.2.5.7.
void Builtins::Generate_RegExpPrototypeMultilineGetter(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeMultilineGetter(
Generate_FlagGetter(a, JSRegExp::kMultiline, compiler::CodeAssemblerState* state) {
CodeStubAssembler a(state);
Generate_FlagGetter(&a, JSRegExp::kMultiline,
v8::Isolate::kRegExpPrototypeOldFlagGetter, v8::Isolate::kRegExpPrototypeOldFlagGetter,
"RegExp.prototype.multiline"); "RegExp.prototype.multiline");
} }
// ES6 21.2.5.12. // ES6 21.2.5.12.
void Builtins::Generate_RegExpPrototypeStickyGetter(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeStickyGetter(
Generate_FlagGetter(a, JSRegExp::kSticky, compiler::CodeAssemblerState* state) {
CodeStubAssembler a(state);
Generate_FlagGetter(&a, JSRegExp::kSticky,
v8::Isolate::kRegExpPrototypeStickyGetter, v8::Isolate::kRegExpPrototypeStickyGetter,
"RegExp.prototype.sticky"); "RegExp.prototype.sticky");
} }
// ES6 21.2.5.15. // ES6 21.2.5.15.
void Builtins::Generate_RegExpPrototypeUnicodeGetter(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeUnicodeGetter(
Generate_FlagGetter(a, JSRegExp::kUnicode, compiler::CodeAssemblerState* state) {
CodeStubAssembler a(state);
Generate_FlagGetter(&a, JSRegExp::kUnicode,
v8::Isolate::kRegExpPrototypeUnicodeGetter, v8::Isolate::kRegExpPrototypeUnicodeGetter,
"RegExp.prototype.unicode"); "RegExp.prototype.unicode");
} }
@ -1061,31 +1074,33 @@ compiler::Node* RegExpExec(CodeStubAssembler* a, compiler::Node* context,
// ES#sec-regexp.prototype.test // ES#sec-regexp.prototype.test
// RegExp.prototype.test ( S ) // RegExp.prototype.test ( S )
void Builtins::Generate_RegExpPrototypeTest(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeTest(
compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; 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_receiver = a.Parameter(0);
Node* const maybe_string = a->Parameter(1); Node* const maybe_string = a.Parameter(1);
Node* const context = a->Parameter(4); Node* const context = a.Parameter(4);
// Ensure {maybe_receiver} is a JSReceiver. // Ensure {maybe_receiver} is a JSReceiver.
ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver, ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
MessageTemplate::kIncompatibleMethodReceiver, MessageTemplate::kIncompatibleMethodReceiver,
"RegExp.prototype.test"); "RegExp.prototype.test");
Node* const receiver = maybe_receiver; Node* const receiver = maybe_receiver;
// Convert {maybe_string} to a String. // Convert {maybe_string} to a String.
Node* const string = a->ToString(context, maybe_string); Node* const string = a.ToString(context, maybe_string);
// Call exec. // 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. // Return true iff exec matched successfully.
Node* const result = a->Select(a->WordEqual(match_indices, a->NullConstant()), Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()),
a->FalseConstant(), a->TrueConstant()); a.FalseConstant(), a.TrueConstant());
a->Return(result); a.Return(result);
} }
// ES#sec-regexp.prototype-@@match // ES#sec-regexp.prototype-@@match
@ -1253,34 +1268,36 @@ void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
// ES#sec-regexp.prototype-@@search // ES#sec-regexp.prototype-@@search
// RegExp.prototype [ @@search ] ( string ) // RegExp.prototype [ @@search ] ( string )
void Builtins::Generate_RegExpPrototypeSearch(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeSearch(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; 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_receiver = a.Parameter(0);
Node* const maybe_string = a->Parameter(1); Node* const maybe_string = a.Parameter(1);
Node* const context = a->Parameter(4); Node* const context = a.Parameter(4);
// Ensure {maybe_receiver} is a JSReceiver. // Ensure {maybe_receiver} is a JSReceiver.
Node* const map = Node* const map =
ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver, ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
MessageTemplate::kIncompatibleMethodReceiver, MessageTemplate::kIncompatibleMethodReceiver,
"RegExp.prototype.@@search"); "RegExp.prototype.@@search");
Node* const receiver = maybe_receiver; Node* const receiver = maybe_receiver;
// Convert {maybe_string} to a String. // 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); Label fast_path(&a), slow_path(&a);
BranchIfFastPath(a, context, map, &fast_path, &slow_path); BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
a->Bind(&fast_path); a.Bind(&fast_path);
Generate_RegExpPrototypeSearchBody(a, receiver, string, context, true); Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true);
a->Bind(&slow_path); a.Bind(&slow_path);
Generate_RegExpPrototypeSearchBody(a, receiver, string, context, false); Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false);
} }
namespace { namespace {
@ -1974,130 +1991,134 @@ compiler::Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a,
// ES#sec-regexp.prototype-@@replace // ES#sec-regexp.prototype-@@replace
// RegExp.prototype [ @@replace ] ( string, replaceValue ) // RegExp.prototype [ @@replace ] ( string, replaceValue )
void Builtins::Generate_RegExpPrototypeReplace(CodeStubAssembler* a) { void Builtins::Generate_RegExpPrototypeReplace(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; 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_receiver = a.Parameter(0);
Node* const maybe_string = a->Parameter(1); Node* const maybe_string = a.Parameter(1);
Node* const replace_value = a->Parameter(2); Node* const replace_value = a.Parameter(2);
Node* const context = a->Parameter(5); 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. // Ensure {maybe_receiver} is a JSReceiver.
Node* const map = Node* const map =
ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver, ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
MessageTemplate::kIncompatibleMethodReceiver, MessageTemplate::kIncompatibleMethodReceiver,
"RegExp.prototype.@@replace"); "RegExp.prototype.@@replace");
Node* const receiver = maybe_receiver; Node* const receiver = maybe_receiver;
// Convert {maybe_string} to a String. // Convert {maybe_string} to a String.
Callable tostring_callable = CodeFactory::ToString(isolate); 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? // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance?
Label checkreplacecallable(a), runtime(a, Label::kDeferred), fastpath(a); Label checkreplacecallable(&a), runtime(&a, Label::kDeferred), fastpath(&a);
BranchIfFastPath(a, context, map, &checkreplacecallable, &runtime); BranchIfFastPath(&a, context, map, &checkreplacecallable, &runtime);
a->Bind(&checkreplacecallable); a.Bind(&checkreplacecallable);
Node* const regexp = receiver; Node* const regexp = receiver;
// 2. Is {replace_value} callable? // 2. Is {replace_value} callable?
Label checkreplacestring(a), if_iscallable(a); Label checkreplacestring(&a), if_iscallable(&a);
a->GotoIf(a->TaggedIsSmi(replace_value), &checkreplacestring); a.GotoIf(a.TaggedIsSmi(replace_value), &checkreplacestring);
Node* const replace_value_map = a->LoadMap(replace_value); Node* const replace_value_map = a.LoadMap(replace_value);
a->Branch(a->IsCallableMap(replace_value_map), &if_iscallable, a.Branch(a.IsCallableMap(replace_value_map), &if_iscallable,
&checkreplacestring); &checkreplacestring);
// 3. Does ToString({replace_value}) contain '$'? // 3. Does ToString({replace_value}) contain '$'?
a->Bind(&checkreplacestring); a.Bind(&checkreplacestring);
{ {
Node* const replace_string = 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 dollar_char = a.IntPtrConstant('$');
Node* const smi_minusone = a->SmiConstant(Smi::FromInt(-1)); Node* const smi_minusone = a.SmiConstant(Smi::FromInt(-1));
a->GotoUnless(a->SmiEqual(a->StringIndexOfChar(context, replace_string, a.GotoUnless(a.SmiEqual(a.StringIndexOfChar(context, replace_string,
dollar_char, int_zero), dollar_char, int_zero),
smi_minusone), smi_minusone),
&runtime); &runtime);
a->Return(ReplaceSimpleStringFastPath(a, context, regexp, string, a.Return(ReplaceSimpleStringFastPath(&a, context, regexp, string,
replace_string)); replace_string));
} }
// {regexp} is unmodified and {replace_value} is callable. // {regexp} is unmodified and {replace_value} is callable.
a->Bind(&if_iscallable); a.Bind(&if_iscallable);
{ {
Node* const replace_callable = replace_value; Node* const replace_callable = replace_value;
// Check if the {regexp} is global. // Check if the {regexp} is global.
Label if_isglobal(a), if_isnotglobal(a); Label if_isglobal(&a), if_isnotglobal(&a);
Node* const is_global = FastFlagGetter(a, regexp, JSRegExp::kGlobal); Node* const is_global = FastFlagGetter(&a, regexp, JSRegExp::kGlobal);
a->Branch(is_global, &if_isglobal, &if_isnotglobal); a.Branch(is_global, &if_isglobal, &if_isnotglobal);
a->Bind(&if_isglobal); a.Bind(&if_isglobal);
{ {
Node* const result = ReplaceGlobalCallableFastPath( Node* const result = ReplaceGlobalCallableFastPath(
a, context, regexp, string, replace_callable); &a, context, regexp, string, replace_callable);
a->Return(result); a.Return(result);
} }
a->Bind(&if_isnotglobal); a.Bind(&if_isnotglobal);
{ {
Node* const result = Node* const result =
a->CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction, a.CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction,
context, string, regexp, replace_callable); context, string, regexp, replace_callable);
a->Return(result); a.Return(result);
} }
} }
a->Bind(&runtime); a.Bind(&runtime);
{ {
Node* const result = a->CallRuntime(Runtime::kRegExpReplace, context, Node* const result = a.CallRuntime(Runtime::kRegExpReplace, context,
receiver, string, replace_value); receiver, string, replace_value);
a->Return(result); a.Return(result);
} }
} }
// Simple string matching functionality for internal use which does not modify // Simple string matching functionality for internal use which does not modify
// the last match info. // the last match info.
void Builtins::Generate_RegExpInternalMatch(CodeStubAssembler* a) { void Builtins::Generate_RegExpInternalMatch(
compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; 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 regexp = a.Parameter(1);
Node* const string = a->Parameter(2); Node* const string = a.Parameter(2);
Node* const context = a->Parameter(5); Node* const context = a.Parameter(5);
Node* const null = a->NullConstant(); Node* const null = a.NullConstant();
Node* const smi_zero = a->SmiConstant(Smi::FromInt(0)); Node* const smi_zero = a.SmiConstant(Smi::FromInt(0));
Node* const native_context = a->LoadNativeContext(context); Node* const native_context = a.LoadNativeContext(context);
Node* const internal_match_info = a->LoadContextElement( Node* const internal_match_info = a.LoadContextElement(
native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
Callable exec_callable = CodeFactory::RegExpExec(isolate); Callable exec_callable = CodeFactory::RegExpExec(isolate);
Node* const match_indices = a->CallStub( Node* const match_indices = a.CallStub(exec_callable, context, regexp, string,
exec_callable, context, regexp, string, smi_zero, internal_match_info); smi_zero, internal_match_info);
Label if_matched(a), if_didnotmatch(a); Label if_matched(&a), if_didnotmatch(&a);
a->Branch(a->WordEqual(match_indices, null), &if_didnotmatch, &if_matched); a.Branch(a.WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
a->Bind(&if_didnotmatch); a.Bind(&if_didnotmatch);
a->Return(null); 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); 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* context,
compiler::Node** out_instance_type, compiler::Node** out_instance_type,
compiler::Node** out_backing_store) { compiler::Node** out_backing_store) {
using namespace compiler; using compiler::Node;
CodeStubAssembler::Label is_smi(a), not_smi(a), is_typed_array(a), 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_typed_array(a), is_shared(a), not_shared(a), is_float_or_clamped(a),
not_float_or_clamped(a), invalid(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* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
compiler::Node* tagged, compiler::Node* tagged,
compiler::Node* context) { compiler::Node* context) {
using namespace compiler; using compiler::Node;
CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32); CodeStubAssembler::Variable var_result(a, MachineRepresentation::kWord32);
Callable to_number = CodeFactory::ToNumber(a->isolate()); Callable to_number = CodeFactory::ToNumber(a->isolate());
@ -139,7 +139,7 @@ compiler::Node* ConvertTaggedAtomicIndexToWord32(CodeStubAssembler* a,
void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word, void ValidateAtomicIndex(CodeStubAssembler* a, compiler::Node* index_word,
compiler::Node* array_length_word, compiler::Node* array_length_word,
compiler::Node* context) { compiler::Node* context) {
using namespace compiler; using compiler::Node;
// Check if the index is in bounds. If not, throw RangeError. // Check if the index is in bounds. If not, throw RangeError.
CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a); CodeStubAssembler::Label if_inbounds(a), if_notinbounds(a);
// TODO(jkummerow): Use unsigned comparison instead of "i<0 || i>length". // 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 } // anonymous namespace
void Builtins::Generate_AtomicsLoad(CodeStubAssembler* a) { void Builtins::Generate_AtomicsLoad(compiler::CodeAssemblerState* state) {
using namespace compiler; using compiler::Node;
Node* array = a->Parameter(1); CodeStubAssembler a(state);
Node* index = a->Parameter(2); Node* array = a.Parameter(1);
Node* context = a->Parameter(3 + 2); Node* index = a.Parameter(2);
Node* context = a.Parameter(3 + 2);
Node* instance_type; Node* instance_type;
Node* backing_store; 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* index_word32 = ConvertTaggedAtomicIndexToWord32(&a, index, context);
Node* array_length_word32 = a->TruncateTaggedToWord32( Node* array_length_word32 = a.TruncateTaggedToWord32(
context, a->LoadObjectField(array, JSTypedArray::kLengthOffset)); context, a.LoadObjectField(array, JSTypedArray::kLengthOffset));
ValidateAtomicIndex(a, index_word32, array_length_word32, context); ValidateAtomicIndex(&a, index_word32, array_length_word32, context);
Node* index_word = a->ChangeUint32ToWord(index_word32); Node* index_word = a.ChangeUint32ToWord(index_word32);
CodeStubAssembler::Label i8(a), u8(a), i16(a), u16(a), i32(a), u32(a), CodeStubAssembler::Label i8(&a), u8(&a), i16(&a), u16(&a), i32(&a), u32(&a),
other(a); other(&a);
int32_t case_values[] = { int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_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[] = { CodeStubAssembler::Label* case_labels[] = {
&i8, &u8, &i16, &u16, &i32, &u32, &i8, &u8, &i16, &u16, &i32, &u32,
}; };
a->Switch(instance_type, &other, case_values, case_labels, a.Switch(instance_type, &other, case_values, case_labels,
arraysize(case_labels)); arraysize(case_labels));
a->Bind(&i8); a.Bind(&i8);
a->Return( a.Return(
a->SmiTag(a->AtomicLoad(MachineType::Int8(), backing_store, index_word))); a.SmiTag(a.AtomicLoad(MachineType::Int8(), backing_store, index_word)));
a->Bind(&u8); a.Bind(&u8);
a->Return(a->SmiTag( a.Return(
a->AtomicLoad(MachineType::Uint8(), backing_store, index_word))); a.SmiTag(a.AtomicLoad(MachineType::Uint8(), backing_store, index_word)));
a->Bind(&i16); a.Bind(&i16);
a->Return(a->SmiTag(a->AtomicLoad(MachineType::Int16(), backing_store, a.Return(a.SmiTag(a.AtomicLoad(MachineType::Int16(), backing_store,
a->WordShl(index_word, 1)))); a.WordShl(index_word, 1))));
a->Bind(&u16); a.Bind(&u16);
a->Return(a->SmiTag(a->AtomicLoad(MachineType::Uint16(), backing_store, a.Return(a.SmiTag(a.AtomicLoad(MachineType::Uint16(), backing_store,
a->WordShl(index_word, 1)))); a.WordShl(index_word, 1))));
a->Bind(&i32); a.Bind(&i32);
a->Return(a->ChangeInt32ToTagged(a->AtomicLoad( a.Return(a.ChangeInt32ToTagged(a.AtomicLoad(
MachineType::Int32(), backing_store, a->WordShl(index_word, 2)))); MachineType::Int32(), backing_store, a.WordShl(index_word, 2))));
a->Bind(&u32); a.Bind(&u32);
a->Return(a->ChangeUint32ToTagged(a->AtomicLoad( a.Return(a.ChangeUint32ToTagged(a.AtomicLoad(
MachineType::Uint32(), backing_store, a->WordShl(index_word, 2)))); MachineType::Uint32(), backing_store, a.WordShl(index_word, 2))));
// This shouldn't happen, we've already validated the type. // This shouldn't happen, we've already validated the type.
a->Bind(&other); a.Bind(&other);
a->Return(a->Int32Constant(0)); a.Return(a.Int32Constant(0));
} }
void Builtins::Generate_AtomicsStore(CodeStubAssembler* a) { void Builtins::Generate_AtomicsStore(compiler::CodeAssemblerState* state) {
using namespace compiler; using compiler::Node;
Node* array = a->Parameter(1); CodeStubAssembler a(state);
Node* index = a->Parameter(2); Node* array = a.Parameter(1);
Node* value = a->Parameter(3); Node* index = a.Parameter(2);
Node* context = a->Parameter(4 + 2); Node* value = a.Parameter(3);
Node* context = a.Parameter(4 + 2);
Node* instance_type; Node* instance_type;
Node* backing_store; 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* index_word32 = ConvertTaggedAtomicIndexToWord32(&a, index, context);
Node* array_length_word32 = a->TruncateTaggedToWord32( Node* array_length_word32 = a.TruncateTaggedToWord32(
context, a->LoadObjectField(array, JSTypedArray::kLengthOffset)); context, a.LoadObjectField(array, JSTypedArray::kLengthOffset));
ValidateAtomicIndex(a, index_word32, array_length_word32, context); ValidateAtomicIndex(&a, index_word32, array_length_word32, context);
Node* index_word = a->ChangeUint32ToWord(index_word32); Node* index_word = a.ChangeUint32ToWord(index_word32);
Node* value_integer = a->ToInteger(context, value); Node* value_integer = a.ToInteger(context, value);
Node* value_word32 = a->TruncateTaggedToWord32(context, value_integer); 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[] = { int32_t case_values[] = {
FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE, FIXED_INT8_ARRAY_TYPE, FIXED_UINT8_ARRAY_TYPE, FIXED_INT16_ARRAY_TYPE,
FIXED_UINT16_ARRAY_TYPE, FIXED_INT32_ARRAY_TYPE, FIXED_UINT32_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[] = { CodeStubAssembler::Label* case_labels[] = {
&u8, &u8, &u16, &u16, &u32, &u32, &u8, &u8, &u16, &u16, &u32, &u32,
}; };
a->Switch(instance_type, &other, case_values, case_labels, a.Switch(instance_type, &other, case_values, case_labels,
arraysize(case_labels)); arraysize(case_labels));
a->Bind(&u8); a.Bind(&u8);
a->AtomicStore(MachineRepresentation::kWord8, backing_store, index_word, a.AtomicStore(MachineRepresentation::kWord8, backing_store, index_word,
value_word32); value_word32);
a->Return(value_integer); a.Return(value_integer);
a->Bind(&u16); a.Bind(&u16);
a->AtomicStore(MachineRepresentation::kWord16, backing_store, a.AtomicStore(MachineRepresentation::kWord16, backing_store,
a->WordShl(index_word, 1), value_word32); a.WordShl(index_word, 1), value_word32);
a->Return(value_integer); a.Return(value_integer);
a->Bind(&u32); a.Bind(&u32);
a->AtomicStore(MachineRepresentation::kWord32, backing_store, a.AtomicStore(MachineRepresentation::kWord32, backing_store,
a->WordShl(index_word, 2), value_word32); a.WordShl(index_word, 2), value_word32);
a->Return(value_integer); a.Return(value_integer);
// This shouldn't happen, we've already validated the type. // This shouldn't happen, we've already validated the type.
a->Bind(&other); a.Bind(&other);
a->Return(a->Int32Constant(0)); a.Return(a.Int32Constant(0));
} }
} // namespace internal } // namespace internal

View File

@ -382,87 +382,97 @@ void GenerateStringRelationalComparison(CodeStubAssembler* assembler,
} // namespace } // namespace
// static // static
void Builtins::Generate_StringEqual(CodeStubAssembler* assembler) { void Builtins::Generate_StringEqual(compiler::CodeAssemblerState* state) {
GenerateStringEqual(assembler, ResultMode::kDontNegateResult); CodeStubAssembler assembler(state);
GenerateStringEqual(&assembler, ResultMode::kDontNegateResult);
} }
// static // static
void Builtins::Generate_StringNotEqual(CodeStubAssembler* assembler) { void Builtins::Generate_StringNotEqual(compiler::CodeAssemblerState* state) {
GenerateStringEqual(assembler, ResultMode::kNegateResult); CodeStubAssembler assembler(state);
GenerateStringEqual(&assembler, ResultMode::kNegateResult);
} }
// static // static
void Builtins::Generate_StringLessThan(CodeStubAssembler* assembler) { void Builtins::Generate_StringLessThan(compiler::CodeAssemblerState* state) {
GenerateStringRelationalComparison(assembler, CodeStubAssembler assembler(state);
GenerateStringRelationalComparison(&assembler,
RelationalComparisonMode::kLessThan); RelationalComparisonMode::kLessThan);
} }
// static // static
void Builtins::Generate_StringLessThanOrEqual(CodeStubAssembler* assembler) { void Builtins::Generate_StringLessThanOrEqual(
compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
GenerateStringRelationalComparison( GenerateStringRelationalComparison(
assembler, RelationalComparisonMode::kLessThanOrEqual); &assembler, RelationalComparisonMode::kLessThanOrEqual);
} }
// static // static
void Builtins::Generate_StringGreaterThan(CodeStubAssembler* assembler) { void Builtins::Generate_StringGreaterThan(compiler::CodeAssemblerState* state) {
GenerateStringRelationalComparison(assembler, CodeStubAssembler assembler(state);
GenerateStringRelationalComparison(&assembler,
RelationalComparisonMode::kGreaterThan); RelationalComparisonMode::kGreaterThan);
} }
// static // static
void Builtins::Generate_StringGreaterThanOrEqual(CodeStubAssembler* assembler) { void Builtins::Generate_StringGreaterThanOrEqual(
compiler::CodeAssemblerState* state) {
CodeStubAssembler assembler(state);
GenerateStringRelationalComparison( GenerateStringRelationalComparison(
assembler, RelationalComparisonMode::kGreaterThanOrEqual); &assembler, RelationalComparisonMode::kGreaterThanOrEqual);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ES6 section 21.1 String Objects // ES6 section 21.1 String Objects
// ES6 section 21.1.2.1 String.fromCharCode ( ...codeUnits ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler assembler(state);
Node* argc = assembler->ChangeInt32ToIntPtr( Node* argc = assembler.ChangeInt32ToIntPtr(
assembler->Parameter(BuiltinDescriptor::kArgumentsCount)); assembler.Parameter(BuiltinDescriptor::kArgumentsCount));
Node* context = assembler->Parameter(BuiltinDescriptor::kContext); 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. // Check if we have exactly one argument (plus the implicit receiver), i.e.
// if the parent frame is not an arguments adaptor frame. // if the parent frame is not an arguments adaptor frame.
Label if_oneargument(assembler), if_notoneargument(assembler); Label if_oneargument(&assembler), if_notoneargument(&assembler);
assembler->Branch(assembler->WordEqual(argc, assembler->IntPtrConstant(1)), assembler.Branch(assembler.WordEqual(argc, assembler.IntPtrConstant(1)),
&if_oneargument, &if_notoneargument); &if_oneargument, &if_notoneargument);
assembler->Bind(&if_oneargument); assembler.Bind(&if_oneargument);
{ {
// Single argument case, perform fast single character string cache lookup // Single argument case, perform fast single character string cache lookup
// for one-byte code units, or fall back to creating a single character // for one-byte code units, or fall back to creating a single character
// string on the fly otherwise. // string on the fly otherwise.
Node* code = arguments.AtIndex(0); Node* code = arguments.AtIndex(0);
Node* code32 = assembler->TruncateTaggedToWord32(context, code); Node* code32 = assembler.TruncateTaggedToWord32(context, code);
Node* code16 = assembler->Word32And( Node* code16 = assembler.Word32And(
code32, assembler->Int32Constant(String::kMaxUtf16CodeUnit)); code32, assembler.Int32Constant(String::kMaxUtf16CodeUnit));
Node* result = assembler->StringFromCharCode(code16); Node* result = assembler.StringFromCharCode(code16);
arguments.PopAndReturn(result); arguments.PopAndReturn(result);
} }
Node* code16 = nullptr; 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. // 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()); Variable max_index(&assembler, MachineType::PointerRepresentation());
max_index.Bind(assembler->IntPtrConstant(0)); max_index.Bind(assembler.IntPtrConstant(0));
// Iterate over the incoming arguments, converting them to 8-bit character // 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 // codes. Stop if any of the conversions generates a code that doesn't fit
// in 8 bits. // 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, arguments.ForEach(vars, [context, &two_byte, &max_index, &code16,
one_byte_result](CodeStubAssembler* assembler, one_byte_result](CodeStubAssembler* assembler,
Node* arg) { Node* arg) {
@ -487,30 +497,30 @@ void Builtins::Generate_StringFromCharCode(CodeStubAssembler* assembler) {
}); });
arguments.PopAndReturn(one_byte_result); 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 // At least one of the characters in the string requires a 16-bit
// representation. Allocate a SeqTwoByteString to hold the resulting // representation. Allocate a SeqTwoByteString to hold the resulting
// string. // 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 // Copy the characters that have already been put in the 8-bit string into
// their corresponding positions in the new 16-bit string. // their corresponding positions in the new 16-bit string.
Node* zero = assembler->IntPtrConstant(0); Node* zero = assembler.IntPtrConstant(0);
assembler->CopyStringCharacters( assembler.CopyStringCharacters(one_byte_result, two_byte_result, zero, zero,
one_byte_result, two_byte_result, zero, zero, max_index.value(), max_index.value(), String::ONE_BYTE_ENCODING,
String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
CodeStubAssembler::INTPTR_PARAMETERS); CodeStubAssembler::INTPTR_PARAMETERS);
// Write the character that caused the 8-bit to 16-bit fault. // 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, max_index.value(), UINT16_ELEMENTS,
CodeStubAssembler::INTPTR_PARAMETERS, CodeStubAssembler::INTPTR_PARAMETERS,
SeqTwoByteString::kHeaderSize - kHeapObjectTag); SeqTwoByteString::kHeaderSize - kHeapObjectTag);
assembler->StoreNoWriteBarrier(MachineRepresentation::kWord16, assembler.StoreNoWriteBarrier(MachineRepresentation::kWord16,
two_byte_result, max_index_offset, code16); two_byte_result, max_index_offset, code16);
max_index.Bind( 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 // 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 // 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 ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* position = assembler->Parameter(1); Node* position = assembler.Parameter(1);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
// Check that {receiver} is coercible to Object and convert it to a String. // Check that {receiver} is coercible to Object and convert it to a String.
receiver = 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 // Convert the {position} to a Smi and check that it's in bounds of the
// {receiver}. // {receiver}.
{ {
Label return_emptystring(assembler, Label::kDeferred); Label return_emptystring(&assembler, Label::kDeferred);
position = assembler->ToInteger(context, position, position = assembler.ToInteger(context, position,
CodeStubAssembler::kTruncateMinusZero); CodeStubAssembler::kTruncateMinusZero);
assembler->GotoUnless(assembler->TaggedIsSmi(position), assembler.GotoUnless(assembler.TaggedIsSmi(position), &return_emptystring);
&return_emptystring);
// Determine the actual length of the {receiver} String. // Determine the actual length of the {receiver} String.
Node* receiver_length = 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}. // Return "" if the Smi {position} is outside the bounds of the {receiver}.
Label if_positioninbounds(assembler); Label if_positioninbounds(&assembler);
assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), assembler.Branch(assembler.SmiAboveOrEqual(position, receiver_length),
&return_emptystring, &if_positioninbounds); &return_emptystring, &if_positioninbounds);
assembler->Bind(&return_emptystring); assembler.Bind(&return_emptystring);
assembler->Return(assembler->EmptyStringConstant()); assembler.Return(assembler.EmptyStringConstant());
assembler->Bind(&if_positioninbounds); assembler.Bind(&if_positioninbounds);
} }
// Load the character code at the {position} from the {receiver}. // 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}. // And return the single character string with only that {code}.
Node* result = assembler->StringFromCharCode(code); Node* result = assembler.StringFromCharCode(code);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos ) // ES6 section 21.1.3.2 String.prototype.charCodeAt ( pos )
void Builtins::Generate_StringPrototypeCharCodeAt( void Builtins::Generate_StringPrototypeCharCodeAt(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* position = assembler->Parameter(1); Node* position = assembler.Parameter(1);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
// Check that {receiver} is coercible to Object and convert it to a String. // Check that {receiver} is coercible to Object and convert it to a String.
receiver = 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 // Convert the {position} to a Smi and check that it's in bounds of the
// {receiver}. // {receiver}.
{ {
Label return_nan(assembler, Label::kDeferred); Label return_nan(&assembler, Label::kDeferred);
position = assembler->ToInteger(context, position, position = assembler.ToInteger(context, position,
CodeStubAssembler::kTruncateMinusZero); CodeStubAssembler::kTruncateMinusZero);
assembler->GotoUnless(assembler->TaggedIsSmi(position), &return_nan); assembler.GotoUnless(assembler.TaggedIsSmi(position), &return_nan);
// Determine the actual length of the {receiver} String. // Determine the actual length of the {receiver} String.
Node* receiver_length = 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}. // Return NaN if the Smi {position} is outside the bounds of the {receiver}.
Label if_positioninbounds(assembler); Label if_positioninbounds(&assembler);
assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length), assembler.Branch(assembler.SmiAboveOrEqual(position, receiver_length),
&return_nan, &if_positioninbounds); &return_nan, &if_positioninbounds);
assembler->Bind(&return_nan); assembler.Bind(&return_nan);
assembler->Return(assembler->NaNConstant()); assembler.Return(assembler.NaNConstant());
assembler->Bind(&if_positioninbounds); assembler.Bind(&if_positioninbounds);
} }
// Load the character at the {position} from the {receiver}. // Load the character at the {position} from the {receiver}.
Node* value = assembler->StringCharCodeAt(receiver, position); Node* value = assembler.StringCharCodeAt(receiver, position);
Node* result = assembler->SmiFromWord32(value); Node* result = assembler.SmiFromWord32(value);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 21.1.3.6 // ES6 section 21.1.3.6
@ -908,125 +920,127 @@ BUILTIN(StringPrototypeNormalize) {
} }
// ES6 section B.2.3.1 String.prototype.substr ( start, length ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; 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_start(&a, MachineRepresentation::kTagged);
Variable var_length(a, MachineRepresentation::kTagged); Variable var_length(&a, MachineRepresentation::kTagged);
Node* const receiver = a->Parameter(0); Node* const receiver = a.Parameter(0);
Node* const start = a->Parameter(1); Node* const start = a.Parameter(1);
Node* const length = a->Parameter(2); Node* const length = a.Parameter(2);
Node* const context = a->Parameter(5); 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. // Check that {receiver} is coercible to Object and convert it to a String.
Node* const 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}. // Conversions and bounds-checks for {start}.
{ {
Node* const start_int = 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); Label if_issmi(&a), if_isheapnumber(&a, Label::kDeferred);
a->Branch(a->TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber); 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); Node* const length_plus_start = a.SmiAdd(string_length, start_int);
var_start.Bind(a->Select(a->SmiLessThan(start_int, zero), var_start.Bind(a.Select(a.SmiLessThan(start_int, zero),
a->SmiMax(length_plus_start, zero), start_int)); a.SmiMax(length_plus_start, zero), start_int));
a->Goto(&handle_length); 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 // 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 // negative, {start} = max({string_length} + {start}),0) = 0'. If it is
// positive, set {start} to {string_length} which ultimately results in // positive, set {start} to {string_length} which ultimately results in
// returning an empty string. // returning an empty string.
Node* const float_zero = a->Float64Constant(0.); Node* const float_zero = a.Float64Constant(0.);
Node* const start_float = a->LoadHeapNumberValue(start_int); Node* const start_float = a.LoadHeapNumberValue(start_int);
var_start.Bind(a->Select(a->Float64LessThan(start_float, float_zero), var_start.Bind(a.Select(a.Float64LessThan(start_float, float_zero), zero,
zero, string_length)); string_length));
a->Goto(&handle_length); a.Goto(&handle_length);
} }
} }
// Conversions and bounds-checks for {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. // Default to {string_length} if {length} is undefined.
{ {
Label if_isundefined(a, Label::kDeferred), if_isnotundefined(a); Label if_isundefined(&a, Label::kDeferred), if_isnotundefined(&a);
a->Branch(a->WordEqual(length, a->UndefinedConstant()), &if_isundefined, a.Branch(a.WordEqual(length, a.UndefinedConstant()), &if_isundefined,
&if_isnotundefined); &if_isnotundefined);
a->Bind(&if_isundefined); a.Bind(&if_isundefined);
var_length.Bind(string_length); var_length.Bind(string_length);
a->Goto(&if_issmi); a.Goto(&if_issmi);
a->Bind(&if_isnotundefined); a.Bind(&if_isnotundefined);
var_length.Bind( 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} // 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()); Node* const minimal_length = a.SmiSub(string_length, var_start.value());
var_length.Bind(a->SmiMin(positive_length, minimal_length)); var_length.Bind(a.SmiMin(positive_length, minimal_length));
a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out); a.GotoUnless(a.SmiLessThanOrEqual(var_length.value(), zero), &out);
a->Return(a->EmptyStringConstant()); 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 // 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 // two cases according to the spec: if it is negative, "" is returned; if
// it is positive, then length is set to {string_length} - {start}. // it is positive, then length is set to {string_length} - {start}.
CSA_ASSERT(a, a->WordEqual(a->LoadMap(var_length.value()), CSA_ASSERT(&a, a.WordEqual(a.LoadMap(var_length.value()),
a->HeapNumberMapConstant())); a.HeapNumberMapConstant()));
Label if_isnegative(a), if_ispositive(a); Label if_isnegative(&a), if_ispositive(&a);
Node* const float_zero = a->Float64Constant(0.); Node* const float_zero = a.Float64Constant(0.);
Node* const length_float = a->LoadHeapNumberValue(var_length.value()); Node* const length_float = a.LoadHeapNumberValue(var_length.value());
a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative, a.Branch(a.Float64LessThan(length_float, float_zero), &if_isnegative,
&if_ispositive); &if_ispositive);
a->Bind(&if_isnegative); a.Bind(&if_isnegative);
a->Return(a->EmptyStringConstant()); a.Return(a.EmptyStringConstant());
a->Bind(&if_ispositive); a.Bind(&if_ispositive);
{ {
var_length.Bind(a->SmiSub(string_length, var_start.value())); var_length.Bind(a.SmiSub(string_length, var_start.value()));
a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out); a.GotoUnless(a.SmiLessThanOrEqual(var_length.value(), zero), &out);
a->Return(a->EmptyStringConstant()); a.Return(a.EmptyStringConstant());
} }
} }
} }
a->Bind(&out); a.Bind(&out);
{ {
Node* const end = a->SmiAdd(var_start.value(), var_length.value()); Node* const end = a.SmiAdd(var_start.value(), var_length.value());
Node* const result = a->SubString(context, string, var_start.value(), end); Node* const result = a.SubString(context, string, var_start.value(), end);
a->Return(result); a.Return(result);
} }
} }
@ -1089,55 +1103,57 @@ compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a,
} // namespace } // namespace
// ES6 section 21.1.3.19 String.prototype.substring ( start, end ) // 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 CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler a(state);
Label out(a); Label out(&a);
Variable var_start(a, MachineRepresentation::kTagged); Variable var_start(&a, MachineRepresentation::kTagged);
Variable var_end(a, MachineRepresentation::kTagged); Variable var_end(&a, MachineRepresentation::kTagged);
Node* const receiver = a->Parameter(0); Node* const receiver = a.Parameter(0);
Node* const start = a->Parameter(1); Node* const start = a.Parameter(1);
Node* const end = a->Parameter(2); Node* const end = a.Parameter(2);
Node* const context = a->Parameter(5); Node* const context = a.Parameter(5);
// Check that {receiver} is coercible to Object and convert it to a String. // Check that {receiver} is coercible to Object and convert it to a String.
Node* const 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}. // 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}. // Conversion and bounds-checks for {end}.
{ {
var_end.Bind(length); 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); Label if_endislessthanstart(&a);
a->Branch(a->SmiLessThan(var_end.value(), var_start.value()), a.Branch(a.SmiLessThan(var_end.value(), var_start.value()),
&if_endislessthanstart, &out); &if_endislessthanstart, &out);
a->Bind(&if_endislessthanstart); a.Bind(&if_endislessthanstart);
{ {
Node* const tmp = var_end.value(); Node* const tmp = var_end.value();
var_end.Bind(var_start.value()); var_end.Bind(var_start.value());
var_start.Bind(tmp); var_start.Bind(tmp);
a->Goto(&out); a.Goto(&out);
} }
} }
a->Bind(&out); a.Bind(&out);
{ {
Node* result = Node* result =
a->SubString(context, string, var_start.value(), var_end.value()); a.SubString(context, string, var_start.value(), var_end.value());
a->Return(result); a.Return(result);
} }
} }
@ -1191,15 +1207,17 @@ BUILTIN(StringPrototypeStartsWith) {
} }
// ES6 section 21.1.3.25 String.prototype.toString () // 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* result = assembler->ToThisValue( Node* result = assembler.ToThisValue(
context, receiver, PrimitiveType::kString, "String.prototype.toString"); context, receiver, PrimitiveType::kString, "String.prototype.toString");
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 21.1.3.27 String.prototype.trim () // ES6 section 21.1.3.27 String.prototype.trim ()
@ -1224,43 +1242,47 @@ BUILTIN(StringPrototypeTrimRight) {
} }
// ES6 section 21.1.3.28 String.prototype.valueOf ( ) // 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* result = assembler->ToThisValue( Node* result = assembler.ToThisValue(
context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* string = assembler->ToThisString(context, receiver, Node* string = assembler.ToThisString(context, receiver,
"String.prototype[Symbol.iterator]"); "String.prototype[Symbol.iterator]");
Node* native_context = assembler->LoadNativeContext(context); Node* native_context = assembler.LoadNativeContext(context);
Node* map = assembler->LoadFixedArrayElement( Node* map = assembler.LoadFixedArrayElement(
native_context, native_context,
assembler->IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0, assembler.IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0,
CodeStubAssembler::INTPTR_PARAMETERS); CodeStubAssembler::INTPTR_PARAMETERS);
Node* iterator = assembler->Allocate(JSStringIterator::kSize); Node* iterator = assembler.Allocate(JSStringIterator::kSize);
assembler->StoreMapNoWriteBarrier(iterator, map); assembler.StoreMapNoWriteBarrier(iterator, map);
assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset, assembler.StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex); Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset, assembler.StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex); Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldNoWriteBarrier( assembler.StoreObjectFieldNoWriteBarrier(
iterator, JSStringIterator::kStringOffset, string); iterator, JSStringIterator::kStringOffset, string);
Node* index = assembler->SmiConstant(Smi::kZero); Node* index = assembler.SmiConstant(Smi::kZero);
assembler->StoreObjectFieldNoWriteBarrier( assembler.StoreObjectFieldNoWriteBarrier(
iterator, JSStringIterator::kNextIndexOffset, index); iterator, JSStringIterator::kNextIndexOffset, index);
assembler->Return(iterator); assembler.Return(iterator);
} }
namespace { namespace {
@ -1355,80 +1377,81 @@ compiler::Node* LoadSurrogatePairAt(CodeStubAssembler* assembler,
} // namespace } // namespace
void Builtins::Generate_StringIteratorPrototypeNext( void Builtins::Generate_StringIteratorPrototypeNext(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler assembler(state);
Variable var_value(assembler, MachineRepresentation::kTagged); Variable var_value(&assembler, MachineRepresentation::kTagged);
Variable var_done(assembler, MachineRepresentation::kTagged); Variable var_done(&assembler, MachineRepresentation::kTagged);
var_value.Bind(assembler->UndefinedConstant()); var_value.Bind(assembler.UndefinedConstant());
var_done.Bind(assembler->BooleanConstant(true)); var_done.Bind(assembler.BooleanConstant(true));
Label throw_bad_receiver(assembler), next_codepoint(assembler), Label throw_bad_receiver(&assembler), next_codepoint(&assembler),
return_result(assembler); return_result(&assembler);
Node* iterator = assembler->Parameter(0); Node* iterator = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
assembler->GotoIf(assembler->TaggedIsSmi(iterator), &throw_bad_receiver); assembler.GotoIf(assembler.TaggedIsSmi(iterator), &throw_bad_receiver);
assembler->GotoUnless( assembler.GotoUnless(
assembler->WordEqual(assembler->LoadInstanceType(iterator), assembler.WordEqual(assembler.LoadInstanceType(iterator),
assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)), assembler.Int32Constant(JS_STRING_ITERATOR_TYPE)),
&throw_bad_receiver); &throw_bad_receiver);
Node* string = Node* string =
assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset); assembler.LoadObjectField(iterator, JSStringIterator::kStringOffset);
Node* position = Node* position =
assembler->LoadObjectField(iterator, JSStringIterator::kNextIndexOffset); assembler.LoadObjectField(iterator, JSStringIterator::kNextIndexOffset);
Node* length = assembler->LoadObjectField(string, String::kLengthOffset); Node* length = assembler.LoadObjectField(string, String::kLengthOffset);
assembler->Branch(assembler->SmiLessThan(position, length), &next_codepoint, assembler.Branch(assembler.SmiLessThan(position, length), &next_codepoint,
&return_result); &return_result);
assembler->Bind(&next_codepoint); assembler.Bind(&next_codepoint);
{ {
Node* ch = LoadSurrogatePairAt(assembler, string, length, position); Node* ch = LoadSurrogatePairAt(&assembler, string, length, position);
Node* value = assembler->StringFromCodePoint(ch, UnicodeEncoding::UTF16); Node* value = assembler.StringFromCodePoint(ch, UnicodeEncoding::UTF16);
var_value.Bind(value); var_value.Bind(value);
Node* length = assembler->LoadObjectField(value, String::kLengthOffset); Node* length = assembler.LoadObjectField(value, String::kLengthOffset);
assembler->StoreObjectFieldNoWriteBarrier( assembler.StoreObjectFieldNoWriteBarrier(
iterator, JSStringIterator::kNextIndexOffset, iterator, JSStringIterator::kNextIndexOffset,
assembler->SmiAdd(position, length)); assembler.SmiAdd(position, length));
var_done.Bind(assembler->BooleanConstant(false)); var_done.Bind(assembler.BooleanConstant(false));
assembler->Goto(&return_result); assembler.Goto(&return_result);
} }
assembler->Bind(&return_result); assembler.Bind(&return_result);
{ {
Node* native_context = assembler->LoadNativeContext(context); Node* native_context = assembler.LoadNativeContext(context);
Node* map = assembler->LoadFixedArrayElement( Node* map = assembler.LoadFixedArrayElement(
native_context, native_context,
assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0, assembler.IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
CodeStubAssembler::INTPTR_PARAMETERS); CodeStubAssembler::INTPTR_PARAMETERS);
Node* result = assembler->Allocate(JSIteratorResult::kSize); Node* result = assembler.Allocate(JSIteratorResult::kSize);
assembler->StoreMapNoWriteBarrier(result, map); assembler.StoreMapNoWriteBarrier(result, map);
assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset, assembler.StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
Heap::kEmptyFixedArrayRootIndex); Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset, assembler.StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
Heap::kEmptyFixedArrayRootIndex); Heap::kEmptyFixedArrayRootIndex);
assembler->StoreObjectFieldNoWriteBarrier( assembler.StoreObjectFieldNoWriteBarrier(
result, JSIteratorResult::kValueOffset, var_value.value()); result, JSIteratorResult::kValueOffset, var_value.value());
assembler->StoreObjectFieldNoWriteBarrier( assembler.StoreObjectFieldNoWriteBarrier(
result, JSIteratorResult::kDoneOffset, var_done.value()); 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. // The {receiver} is not a valid JSGeneratorObject.
Node* result = assembler->CallRuntime( Node* result = assembler.CallRuntime(
Runtime::kThrowIncompatibleMethodReceiver, context, Runtime::kThrowIncompatibleMethodReceiver, context,
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( assembler.HeapConstant(assembler.factory()->NewStringFromAsciiChecked(
"String Iterator.prototype.next", TENURED)), "String Iterator.prototype.next", TENURED)),
iterator); 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 ) // ES6 section 19.4.3.4 Symbol.prototype [ @@toPrimitive ] ( hint )
void Builtins::Generate_SymbolPrototypeToPrimitive( void Builtins::Generate_SymbolPrototypeToPrimitive(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(4); Node* context = assembler.Parameter(4);
Node* result = Node* result =
assembler->ToThisValue(context, receiver, PrimitiveType::kSymbol, assembler.ToThisValue(context, receiver, PrimitiveType::kSymbol,
"Symbol.prototype [ @@toPrimitive ]"); "Symbol.prototype [ @@toPrimitive ]");
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 19.4.3.2 Symbol.prototype.toString ( ) // 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* value = assembler->ToThisValue( Node* value = assembler.ToThisValue(context, receiver, PrimitiveType::kSymbol,
context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.toString"); "Symbol.prototype.toString");
Node* result = Node* result =
assembler->CallRuntime(Runtime::kSymbolDescriptiveString, context, value); assembler.CallRuntime(Runtime::kSymbolDescriptiveString, context, value);
assembler->Return(result); assembler.Return(result);
} }
// ES6 section 19.4.3.3 Symbol.prototype.valueOf ( ) // 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; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Node* result = assembler->ToThisValue( Node* result = assembler.ToThisValue(
context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.valueOf"); context, receiver, PrimitiveType::kSymbol, "Symbol.prototype.valueOf");
assembler->Return(result); assembler.Return(result);
} }
} // namespace internal } // namespace internal

View File

@ -20,48 +20,48 @@ BUILTIN(TypedArrayPrototypeBuffer) {
namespace { namespace {
void Generate_TypedArrayProtoypeGetter(CodeStubAssembler* assembler, void Generate_TypedArrayProtoypeGetter(compiler::CodeAssemblerState* state,
const char* method_name, const char* method_name,
int object_offset) { int object_offset) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node; typedef compiler::Node Node;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
// Check if the {receiver} is actually a JSTypedArray. // Check if the {receiver} is actually a JSTypedArray.
Label if_receiverisincompatible(assembler, Label::kDeferred); Label if_receiverisincompatible(&assembler, Label::kDeferred);
assembler->GotoIf(assembler->TaggedIsSmi(receiver), assembler.GotoIf(assembler.TaggedIsSmi(receiver), &if_receiverisincompatible);
&if_receiverisincompatible); Node* receiver_instance_type = assembler.LoadInstanceType(receiver);
Node* receiver_instance_type = assembler->LoadInstanceType(receiver); assembler.GotoUnless(
assembler->GotoUnless( assembler.Word32Equal(receiver_instance_type,
assembler->Word32Equal(receiver_instance_type, assembler.Int32Constant(JS_TYPED_ARRAY_TYPE)),
assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)),
&if_receiverisincompatible); &if_receiverisincompatible);
// Check if the {receiver}'s JSArrayBuffer was neutered. // Check if the {receiver}'s JSArrayBuffer was neutered.
Node* receiver_buffer = Node* receiver_buffer =
assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset); assembler.LoadObjectField(receiver, JSTypedArray::kBufferOffset);
Label if_receiverisneutered(assembler, Label::kDeferred); Label if_receiverisneutered(&assembler, Label::kDeferred);
assembler->GotoIf(assembler->IsDetachedBuffer(receiver_buffer), assembler.GotoIf(assembler.IsDetachedBuffer(receiver_buffer),
&if_receiverisneutered); &if_receiverisneutered);
assembler->Return(assembler->LoadObjectField(receiver, object_offset)); assembler.Return(assembler.LoadObjectField(receiver, object_offset));
assembler->Bind(&if_receiverisneutered); assembler.Bind(&if_receiverisneutered);
{ {
// The {receiver}s buffer was neutered, default to zero. // 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. // The {receiver} is not a valid JSGeneratorObject.
Node* result = assembler->CallRuntime( Node* result = assembler.CallRuntime(
Runtime::kThrowIncompatibleMethodReceiver, context, Runtime::kThrowIncompatibleMethodReceiver, context,
assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( assembler.HeapConstant(assembler.factory()->NewStringFromAsciiChecked(
method_name, TENURED)), method_name, TENURED)),
receiver); 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 // ES6 section 22.2.3.2 get %TypedArray%.prototype.byteLength
void Builtins::Generate_TypedArrayPrototypeByteLength( void Builtins::Generate_TypedArrayPrototypeByteLength(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_TypedArrayProtoypeGetter(assembler, Generate_TypedArrayProtoypeGetter(state,
"get TypedArray.prototype.byteLength", "get TypedArray.prototype.byteLength",
JSTypedArray::kByteLengthOffset); JSTypedArray::kByteLengthOffset);
} }
// ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset // ES6 section 22.2.3.3 get %TypedArray%.prototype.byteOffset
void Builtins::Generate_TypedArrayPrototypeByteOffset( void Builtins::Generate_TypedArrayPrototypeByteOffset(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_TypedArrayProtoypeGetter(assembler, Generate_TypedArrayProtoypeGetter(state,
"get TypedArray.prototype.byteOffset", "get TypedArray.prototype.byteOffset",
JSTypedArray::kByteOffsetOffset); JSTypedArray::kByteOffsetOffset);
} }
// ES6 section 22.2.3.18 get %TypedArray%.prototype.length // ES6 section 22.2.3.18 get %TypedArray%.prototype.length
void Builtins::Generate_TypedArrayPrototypeLength( void Builtins::Generate_TypedArrayPrototypeLength(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_TypedArrayProtoypeGetter(assembler, Generate_TypedArrayProtoypeGetter(state, "get TypedArray.prototype.length",
"get TypedArray.prototype.length",
JSTypedArray::kLengthOffset); JSTypedArray::kLengthOffset);
} }
namespace { namespace {
template <IterationKind kIterationKind> template <IterationKind kIterationKind>
void Generate_TypedArrayPrototypeIterationMethod(CodeStubAssembler* assembler, void Generate_TypedArrayPrototypeIterationMethod(
const char* method_name) { compiler::CodeAssemblerState* state, const char* method_name) {
typedef compiler::Node Node; typedef compiler::Node Node;
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
CodeStubAssembler assembler(state);
Node* receiver = assembler->Parameter(0); Node* receiver = assembler.Parameter(0);
Node* context = assembler->Parameter(3); Node* context = assembler.Parameter(3);
Label throw_bad_receiver(assembler, Label::kDeferred); Label throw_bad_receiver(&assembler, Label::kDeferred);
Label throw_typeerror(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* map = assembler.LoadMap(receiver);
Node* instance_type = assembler->LoadMapInstanceType(map); Node* instance_type = assembler.LoadMapInstanceType(map);
assembler->GotoIf( assembler.GotoIf(
assembler->Word32NotEqual(instance_type, assembler.Word32NotEqual(instance_type,
assembler->Int32Constant(JS_TYPED_ARRAY_TYPE)), assembler.Int32Constant(JS_TYPED_ARRAY_TYPE)),
&throw_bad_receiver); &throw_bad_receiver);
// Check if the {receiver}'s JSArrayBuffer was neutered. // Check if the {receiver}'s JSArrayBuffer was neutered.
Node* receiver_buffer = Node* receiver_buffer =
assembler->LoadObjectField(receiver, JSTypedArray::kBufferOffset); assembler.LoadObjectField(receiver, JSTypedArray::kBufferOffset);
Label if_receiverisneutered(assembler, Label::kDeferred); Label if_receiverisneutered(&assembler, Label::kDeferred);
assembler->GotoIf(assembler->IsDetachedBuffer(receiver_buffer), assembler.GotoIf(assembler.IsDetachedBuffer(receiver_buffer),
&if_receiverisneutered); &if_receiverisneutered);
assembler->Return(assembler->CreateArrayIterator(receiver, map, instance_type, assembler.Return(assembler.CreateArrayIterator(receiver, map, instance_type,
context, kIterationKind)); context, kIterationKind));
Variable var_message(assembler, MachineRepresentation::kTagged); Variable var_message(&assembler, MachineRepresentation::kTagged);
assembler->Bind(&throw_bad_receiver); assembler.Bind(&throw_bad_receiver);
var_message.Bind( var_message.Bind(
assembler->SmiConstant(Smi::FromInt(MessageTemplate::kNotTypedArray))); assembler.SmiConstant(Smi::FromInt(MessageTemplate::kNotTypedArray)));
assembler->Goto(&throw_typeerror); assembler.Goto(&throw_typeerror);
assembler->Bind(&if_receiverisneutered); assembler.Bind(&if_receiverisneutered);
var_message.Bind(assembler->SmiConstant( var_message.Bind(
Smi::FromInt(MessageTemplate::kDetachedOperation))); assembler.SmiConstant(Smi::FromInt(MessageTemplate::kDetachedOperation)));
assembler->Goto(&throw_typeerror); assembler.Goto(&throw_typeerror);
assembler->Bind(&throw_typeerror); assembler.Bind(&throw_typeerror);
{ {
Node* arg1 = assembler->HeapConstant( Node* arg1 = assembler.HeapConstant(
assembler->isolate()->factory()->NewStringFromAsciiChecked(method_name, assembler.isolate()->factory()->NewStringFromAsciiChecked(method_name,
TENURED)); TENURED));
Node* result = assembler->CallRuntime(Runtime::kThrowTypeError, context, Node* result = assembler.CallRuntime(Runtime::kThrowTypeError, context,
var_message.value(), arg1); var_message.value(), arg1);
assembler->Return(result); assembler.Return(result);
} }
} }
} // namespace } // namespace
void Builtins::Generate_TypedArrayPrototypeValues( void Builtins::Generate_TypedArrayPrototypeValues(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kValues>( Generate_TypedArrayPrototypeIterationMethod<IterationKind::kValues>(
assembler, "%TypedArray%.prototype.values()"); state, "%TypedArray%.prototype.values()");
} }
void Builtins::Generate_TypedArrayPrototypeEntries( void Builtins::Generate_TypedArrayPrototypeEntries(
CodeStubAssembler* assembler) { compiler::CodeAssemblerState* state) {
Generate_TypedArrayPrototypeIterationMethod<IterationKind::kEntries>( 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>( Generate_TypedArrayPrototypeIterationMethod<IterationKind::kKeys>(
assembler, "%TypedArray%.prototype.keys()"); state, "%TypedArray%.prototype.keys()");
} }
} // namespace internal } // namespace internal

View File

@ -4,7 +4,7 @@
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/code-events.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/ic/ic-state.h"
#include "src/interface-descriptors.h" #include "src/interface-descriptors.h"
#include "src/isolate.h" #include "src/isolate.h"
@ -42,7 +42,7 @@ void PostBuildProfileAndTracing(Isolate* isolate, Code* code,
} }
typedef void (*MacroAssemblerGenerator)(MacroAssembler*); typedef void (*MacroAssemblerGenerator)(MacroAssembler*);
typedef void (*CodeAssemblerGenerator)(CodeStubAssembler*); typedef void (*CodeAssemblerGenerator)(compiler::CodeAssemblerState*);
Code* BuildWithMacroAssembler(Isolate* isolate, Code* BuildWithMacroAssembler(Isolate* isolate,
MacroAssemblerGenerator generator, MacroAssemblerGenerator generator,
@ -86,9 +86,10 @@ Code* BuildWithCodeStubAssemblerJS(Isolate* isolate,
Zone zone(isolate->allocator(), ZONE_NAME); Zone zone(isolate->allocator(), ZONE_NAME);
const int argc_with_recv = const int argc_with_recv =
(argc == SharedFunctionInfo::kDontAdaptArgumentsSentinel) ? 0 : argc + 1; (argc == SharedFunctionInfo::kDontAdaptArgumentsSentinel) ? 0 : argc + 1;
CodeStubAssembler assembler(isolate, &zone, argc_with_recv, flags, name); compiler::CodeAssemblerState state(isolate, &zone, argc_with_recv, flags,
generator(&assembler); name);
Handle<Code> code = assembler.GenerateCode(); generator(&state);
Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name); PostBuildProfileAndTracing(isolate, *code, name);
return *code; return *code;
} }
@ -105,9 +106,9 @@ Code* BuildWithCodeStubAssemblerCS(Isolate* isolate,
CallInterfaceDescriptor descriptor(isolate, interface_descriptor); CallInterfaceDescriptor descriptor(isolate, interface_descriptor);
// Ensure descriptor is already initialized. // Ensure descriptor is already initialized.
DCHECK_LE(0, descriptor.GetRegisterParameterCount()); DCHECK_LE(0, descriptor.GetRegisterParameterCount());
CodeStubAssembler assembler(isolate, &zone, descriptor, flags, name); compiler::CodeAssemblerState state(isolate, &zone, descriptor, flags, name);
generator(&assembler); generator(&state);
Handle<Code> code = assembler.GenerateCode(); Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
PostBuildProfileAndTracing(isolate, *code, name); PostBuildProfileAndTracing(isolate, *code, name);
return *code; return *code;
} }

View File

@ -716,8 +716,10 @@ namespace internal {
IGNORE_BUILTIN, IGNORE_BUILTIN, V) IGNORE_BUILTIN, IGNORE_BUILTIN, V)
// Forward declarations. // Forward declarations.
class CodeStubAssembler;
class ObjectVisitor; class ObjectVisitor;
namespace compiler {
class CodeAssemblerState;
}
class Builtins { class Builtins {
public: public:
@ -816,16 +818,13 @@ class Builtins {
static void Generate_InterpreterPushArgsAndConstructImpl( static void Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, CallableType function_type); MacroAssembler* masm, CallableType function_type);
static void Generate_DatePrototype_GetField(CodeStubAssembler* masm,
int field_index);
enum class MathMaxMinKind { kMax, kMin }; enum class MathMaxMinKind { kMax, kMin };
static void Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind); static void Generate_MathMaxMin(MacroAssembler* masm, MathMaxMinKind kind);
#define DECLARE_ASM(Name, ...) \ #define DECLARE_ASM(Name, ...) \
static void Generate_##Name(MacroAssembler* masm); static void Generate_##Name(MacroAssembler* masm);
#define DECLARE_TF(Name, ...) \ #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, BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, DECLARE_TF, DECLARE_TF,
DECLARE_ASM, DECLARE_ASM, DECLARE_ASM) DECLARE_ASM, DECLARE_ASM, DECLARE_ASM)

View File

@ -13,18 +13,6 @@ namespace internal {
using compiler::Node; 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, void CodeStubAssembler::Assert(ConditionBody codition_body, const char* message,
const char* file, int line) { const char* file, int line) {
#if defined(DEBUG) #if defined(DEBUG)

View File

@ -44,17 +44,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
// from a compiler directory OWNER). // from a compiler directory OWNER).
class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
public: public:
// Create with CallStub linkage. CodeStubAssembler(compiler::CodeAssemblerState* state)
// |result_size| specifies the number of results returned by the stub. : compiler::CodeAssembler(state) {}
// 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);
enum AllocationFlag : uint8_t { enum AllocationFlag : uint8_t {
kNone = 0, kNone = 0,

View File

@ -251,8 +251,9 @@ Handle<Code> HydrogenCodeStub::GenerateRuntimeTailCall(
const char* name = CodeStub::MajorName(MajorKey()); const char* name = CodeStub::MajorName(MajorKey());
Zone zone(isolate()->allocator(), ZONE_NAME); Zone zone(isolate()->allocator(), ZONE_NAME);
CallInterfaceDescriptor interface_descriptor(GetCallInterfaceDescriptor()); CallInterfaceDescriptor interface_descriptor(GetCallInterfaceDescriptor());
CodeStubAssembler assembler(isolate(), &zone, interface_descriptor, compiler::CodeAssemblerState state(isolate(), &zone, interface_descriptor,
GetCodeFlags(), name); GetCodeFlags(), name);
CodeStubAssembler assembler(&state);
int total_params = interface_descriptor.GetStackParameterCount() + int total_params = interface_descriptor.GetStackParameterCount() +
interface_descriptor.GetRegisterParameterCount(); interface_descriptor.GetRegisterParameterCount();
switch (total_params) { switch (total_params) {
@ -284,7 +285,7 @@ Handle<Code> HydrogenCodeStub::GenerateRuntimeTailCall(
UNIMPLEMENTED(); UNIMPLEMENTED();
break; break;
} }
return assembler.GenerateCode(); return compiler::CodeAssembler::GenerateCode(&state);
} }
template <class Stub> template <class Stub>

File diff suppressed because it is too large Load Diff

View File

@ -370,7 +370,6 @@ class CodeStub BASE_EMBEDDED {
public: \ public: \
inline Major MajorKey() const override { return NAME; }; \ inline Major MajorKey() const override { return NAME; }; \
\ \
protected: \
DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER) DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
@ -386,59 +385,27 @@ class CodeStub BASE_EMBEDDED {
Handle<Code> GenerateCode() override; \ Handle<Code> GenerateCode() override; \
DEFINE_CODE_STUB(NAME, SUPER) DEFINE_CODE_STUB(NAME, SUPER)
#define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \ #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER) \
public: \ public: \
void GenerateAssembly(CodeStubAssembler* assembler) const override; \ void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
DEFINE_CODE_STUB(NAME, SUPER) DEFINE_CODE_STUB(NAME, SUPER)
#define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NAME, SUPER) \ #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
public: \ public: \
static compiler::Node* Generate(CodeStubAssembler* assembler, \ static compiler::Node* Generate( \
compiler::Node* left, compiler::Node* right, \ CodeStubAssembler* assembler, compiler::Node* left, \
compiler::Node* context); \ compiler::Node* right, compiler::Node* slot_id, \
void GenerateAssembly(CodeStubAssembler* assembler) const override { \ compiler::Node* type_feedback_vector, compiler::Node* context); \
assembler->Return(Generate(assembler, assembler->Parameter(0), \ void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
assembler->Parameter(1), \
assembler->Parameter(2))); \
} \
DEFINE_CODE_STUB(NAME, SUPER) DEFINE_CODE_STUB(NAME, SUPER)
#define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \ #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER) \
public: \ public: \
static compiler::Node* Generate( \ static compiler::Node* Generate( \
CodeStubAssembler* assembler, compiler::Node* left, \ CodeStubAssembler* assembler, compiler::Node* value, \
compiler::Node* right, compiler::Node* slot_id, \ compiler::Node* context, compiler::Node* type_feedback_vector, \
compiler::Node* type_feedback_vector, compiler::Node* context); \ compiler::Node* slot_id); \
void GenerateAssembly(CodeStubAssembler* assembler) const override { \ void GenerateAssembly(compiler::CodeAssemblerState* state) 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_CODE_STUB(NAME, SUPER) DEFINE_CODE_STUB(NAME, SUPER)
#define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \ #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
@ -638,7 +605,7 @@ class TurboFanCodeStub : public CodeStub {
protected: protected:
explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {} explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
virtual void GenerateAssembly(CodeStubAssembler* assembler) const = 0; virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0;
private: private:
DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub); DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
@ -794,13 +761,11 @@ class StoreInterceptorStub : public TurboFanCodeStub {
public: public:
explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(CodeStubAssembler* assember) const override;
Code::Kind GetCodeKind() const override { return Code::HANDLER; } Code::Kind GetCodeKind() const override { return Code::HANDLER; }
ExtraICState GetExtraICState() const override { return Code::STORE_IC; } ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
DEFINE_CODE_STUB(StoreInterceptor, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
}; };
class LoadIndexedInterceptorStub : public TurboFanCodeStub { class LoadIndexedInterceptorStub : public TurboFanCodeStub {
@ -1975,12 +1940,10 @@ class LoadICTrampolineStub : public TurboFanCodeStub {
public: public:
explicit LoadICTrampolineStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit LoadICTrampolineStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::LOAD_IC; } Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
DEFINE_CALL_INTERFACE_DESCRIPTOR(Load); DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
DEFINE_CODE_STUB(LoadICTrampoline, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(LoadICTrampoline, TurboFanCodeStub);
}; };
class LoadGlobalICTrampolineStub : public TurboFanCodeStub { class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
@ -1991,8 +1954,6 @@ class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
minor_key_ = state.GetExtraICState(); minor_key_ = state.GetExtraICState();
} }
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; } Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
@ -2000,7 +1961,7 @@ class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
} }
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal); DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal);
DEFINE_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub);
}; };
class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub { class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub {
@ -2008,11 +1969,9 @@ class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub {
explicit KeyedLoadICTrampolineTFStub(Isolate* isolate) explicit KeyedLoadICTrampolineTFStub(Isolate* isolate)
: LoadICTrampolineStub(isolate) {} : LoadICTrampolineStub(isolate) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; } 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 { class StoreICTrampolineStub : public TurboFanCodeStub {
@ -2022,8 +1981,6 @@ class StoreICTrampolineStub : public TurboFanCodeStub {
minor_key_ = state.GetExtraICState(); minor_key_ = state.GetExtraICState();
} }
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::STORE_IC; } Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
@ -2034,7 +1991,7 @@ class StoreICTrampolineStub : public TurboFanCodeStub {
StoreICState state() const { return StoreICState(GetExtraICState()); } StoreICState state() const { return StoreICState(GetExtraICState()); }
DEFINE_CALL_INTERFACE_DESCRIPTOR(Store); DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
DEFINE_CODE_STUB(StoreICTrampoline, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StoreICTrampoline, TurboFanCodeStub);
}; };
class KeyedStoreICTrampolineStub : public PlatformCodeStub { class KeyedStoreICTrampolineStub : public PlatformCodeStub {
@ -2063,11 +2020,9 @@ class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub {
KeyedStoreICTrampolineTFStub(Isolate* isolate, const StoreICState& state) KeyedStoreICTrampolineTFStub(Isolate* isolate, const StoreICState& state)
: StoreICTrampolineStub(isolate, state) {} : StoreICTrampolineStub(isolate, state) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } 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 { class CallICTrampolineStub : public PlatformCodeStub {
@ -2096,22 +2051,18 @@ class LoadICStub : public TurboFanCodeStub {
public: public:
explicit LoadICStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit LoadICStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::LOAD_IC; } Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector); DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
DEFINE_CODE_STUB(LoadIC, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(LoadIC, TurboFanCodeStub);
}; };
class LoadICProtoArrayStub : public TurboFanCodeStub { class LoadICProtoArrayStub : public TurboFanCodeStub {
public: public:
explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {} explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray); DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray);
DEFINE_CODE_STUB(LoadICProtoArray, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(LoadICProtoArray, TurboFanCodeStub);
}; };
class LoadGlobalICStub : public TurboFanCodeStub { class LoadGlobalICStub : public TurboFanCodeStub {
@ -2121,8 +2072,6 @@ class LoadGlobalICStub : public TurboFanCodeStub {
minor_key_ = state.GetExtraICState(); minor_key_ = state.GetExtraICState();
} }
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; } Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
@ -2130,18 +2079,16 @@ class LoadGlobalICStub : public TurboFanCodeStub {
} }
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector); DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector);
DEFINE_CODE_STUB(LoadGlobalIC, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(LoadGlobalIC, TurboFanCodeStub);
}; };
class KeyedLoadICTFStub : public LoadICStub { class KeyedLoadICTFStub : public LoadICStub {
public: public:
explicit KeyedLoadICTFStub(Isolate* isolate) : LoadICStub(isolate) {} explicit KeyedLoadICTFStub(Isolate* isolate) : LoadICStub(isolate) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; } 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 { class StoreICStub : public TurboFanCodeStub {
@ -2151,15 +2098,13 @@ class StoreICStub : public TurboFanCodeStub {
minor_key_ = state.GetExtraICState(); minor_key_ = state.GetExtraICState();
} }
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::STORE_IC; } Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
ExtraICState GetExtraICState() const final { ExtraICState GetExtraICState() const final {
return static_cast<ExtraICState>(minor_key_); return static_cast<ExtraICState>(minor_key_);
} }
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector); DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
DEFINE_CODE_STUB(StoreIC, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(StoreIC, TurboFanCodeStub);
}; };
class KeyedStoreICStub : public PlatformCodeStub { class KeyedStoreICStub : public PlatformCodeStub {
@ -2189,11 +2134,9 @@ class KeyedStoreICTFStub : public StoreICStub {
KeyedStoreICTFStub(Isolate* isolate, const StoreICState& state) KeyedStoreICTFStub(Isolate* isolate, const StoreICState& state)
: StoreICStub(isolate, state) {} : StoreICStub(isolate, state) {}
void GenerateAssembly(CodeStubAssembler* assembler) const override;
Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; } 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 { class DoubleToIStub : public PlatformCodeStub {
@ -2398,23 +2341,22 @@ class AllocateHeapNumberStub : public TurboFanCodeStub {
: TurboFanCodeStub(isolate) {} : TurboFanCodeStub(isolate) {}
void InitializeDescriptor(CodeStubDescriptor* descriptor) override; void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
void GenerateAssembly(CodeStubAssembler* assembler) const override;
DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber); 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) \ #define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type) \
class Allocate##Type##Stub : public TurboFanCodeStub { \ class Allocate##Type##Stub : public TurboFanCodeStub { \
public: \ public: \
explicit Allocate##Type##Stub(Isolate* isolate) \ explicit Allocate##Type##Stub(Isolate* isolate) \
: TurboFanCodeStub(isolate) {} \ : TurboFanCodeStub(isolate) {} \
\ \
void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \ void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
void GenerateAssembly(CodeStubAssembler* assembler) const override; \ void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
\ \
DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type); \ DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type); \
DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub); \ DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub); \
}; };
SIMD128_TYPES(SIMD128_ALLOC_STUB) SIMD128_TYPES(SIMD128_ALLOC_STUB)
#undef SIMD128_ALLOC_STUB #undef SIMD128_ALLOC_STUB
@ -2713,16 +2655,8 @@ class SubStringStub : public TurboFanCodeStub {
compiler::Node* string, compiler::Node* from, compiler::Node* string, compiler::Node* from,
compiler::Node* to, compiler::Node* context); 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_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 internal {
namespace compiler { namespace compiler {
CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, CodeAssemblerState::CodeAssemblerState(
const CallInterfaceDescriptor& descriptor, Isolate* isolate, Zone* zone, const CallInterfaceDescriptor& descriptor,
Code::Flags flags, const char* name, Code::Flags flags, const char* name, size_t result_size)
size_t result_size) : CodeAssemblerState(
: CodeAssembler(
isolate, zone, isolate, zone,
Linkage::GetStubCallDescriptor( Linkage::GetStubCallDescriptor(
isolate, zone, descriptor, descriptor.GetStackParameterCount(), isolate, zone, descriptor, descriptor.GetStackParameterCount(),
@ -38,19 +37,20 @@ CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
MachineType::AnyTagged(), result_size), MachineType::AnyTagged(), result_size),
flags, name) {} flags, name) {}
CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, int parameter_count, CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
Code::Flags flags, const char* name) int parameter_count, Code::Flags flags,
: CodeAssembler(isolate, zone, const char* name)
Linkage::GetJSCallDescriptor( : CodeAssemblerState(isolate, zone,
zone, false, parameter_count, Linkage::GetJSCallDescriptor(
Code::ExtractKindFromFlags(flags) == Code::BUILTIN zone, false, parameter_count,
? CallDescriptor::kPushArgumentCount Code::ExtractKindFromFlags(flags) == Code::BUILTIN
: CallDescriptor::kNoFlags), ? CallDescriptor::kPushArgumentCount
flags, name) {} : CallDescriptor::kNoFlags),
flags, name) {}
CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone, CodeAssemblerState::CodeAssemblerState(Isolate* isolate, Zone* zone,
CallDescriptor* call_descriptor, Code::Flags flags, CallDescriptor* call_descriptor,
const char* name) Code::Flags flags, const char* name)
: raw_assembler_(new RawMachineAssembler( : raw_assembler_(new RawMachineAssembler(
isolate, new (zone) Graph(zone), call_descriptor, isolate, new (zone) Graph(zone), call_descriptor,
MachineType::PointerRepresentation(), MachineType::PointerRepresentation(),
@ -61,52 +61,56 @@ CodeAssembler::CodeAssembler(Isolate* isolate, Zone* zone,
code_generated_(false), code_generated_(false),
variables_(zone) {} variables_(zone) {}
CodeAssemblerState::~CodeAssemblerState() {}
CodeAssembler::~CodeAssembler() {} CodeAssembler::~CodeAssembler() {}
void CodeAssembler::CallPrologue() {} void CodeAssembler::CallPrologue() {}
void CodeAssembler::CallEpilogue() {} void CodeAssembler::CallEpilogue() {}
Handle<Code> CodeAssembler::GenerateCode() { // static
DCHECK(!code_generated_); 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( Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
isolate(), raw_assembler_->call_descriptor(), raw_assembler_->graph(), rasm->isolate(), rasm->call_descriptor(), rasm->graph(), schedule,
schedule, flags_, name_); state->flags_, state->name_);
code_generated_ = true; state->code_generated_ = true;
return code; return code;
} }
bool CodeAssembler::Is64() const { return raw_assembler_->machine()->Is64(); } bool CodeAssembler::Is64() const { return raw_assembler()->machine()->Is64(); }
bool CodeAssembler::IsFloat64RoundUpSupported() const { bool CodeAssembler::IsFloat64RoundUpSupported() const {
return raw_assembler_->machine()->Float64RoundUp().IsSupported(); return raw_assembler()->machine()->Float64RoundUp().IsSupported();
} }
bool CodeAssembler::IsFloat64RoundDownSupported() const { bool CodeAssembler::IsFloat64RoundDownSupported() const {
return raw_assembler_->machine()->Float64RoundDown().IsSupported(); return raw_assembler()->machine()->Float64RoundDown().IsSupported();
} }
bool CodeAssembler::IsFloat64RoundTruncateSupported() const { bool CodeAssembler::IsFloat64RoundTruncateSupported() const {
return raw_assembler_->machine()->Float64RoundTruncate().IsSupported(); return raw_assembler()->machine()->Float64RoundTruncate().IsSupported();
} }
Node* CodeAssembler::Int32Constant(int32_t value) { Node* CodeAssembler::Int32Constant(int32_t value) {
return raw_assembler_->Int32Constant(value); return raw_assembler()->Int32Constant(value);
} }
Node* CodeAssembler::Int64Constant(int64_t value) { Node* CodeAssembler::Int64Constant(int64_t value) {
return raw_assembler_->Int64Constant(value); return raw_assembler()->Int64Constant(value);
} }
Node* CodeAssembler::IntPtrConstant(intptr_t value) { Node* CodeAssembler::IntPtrConstant(intptr_t value) {
return raw_assembler_->IntPtrConstant(value); return raw_assembler()->IntPtrConstant(value);
} }
Node* CodeAssembler::NumberConstant(double value) { Node* CodeAssembler::NumberConstant(double value) {
return raw_assembler_->NumberConstant(value); return raw_assembler()->NumberConstant(value);
} }
Node* CodeAssembler::SmiConstant(Smi* value) { Node* CodeAssembler::SmiConstant(Smi* value) {
@ -118,19 +122,19 @@ Node* CodeAssembler::SmiConstant(int value) {
} }
Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) { Node* CodeAssembler::HeapConstant(Handle<HeapObject> object) {
return raw_assembler_->HeapConstant(object); return raw_assembler()->HeapConstant(object);
} }
Node* CodeAssembler::BooleanConstant(bool value) { Node* CodeAssembler::BooleanConstant(bool value) {
return raw_assembler_->BooleanConstant(value); return raw_assembler()->BooleanConstant(value);
} }
Node* CodeAssembler::ExternalConstant(ExternalReference address) { Node* CodeAssembler::ExternalConstant(ExternalReference address) {
return raw_assembler_->ExternalConstant(address); return raw_assembler()->ExternalConstant(address);
} }
Node* CodeAssembler::Float64Constant(double value) { Node* CodeAssembler::Float64Constant(double value) {
return raw_assembler_->Float64Constant(value); return raw_assembler()->Float64Constant(value);
} }
Node* CodeAssembler::NaNConstant() { Node* CodeAssembler::NaNConstant() {
@ -176,18 +180,18 @@ bool CodeAssembler::ToIntPtrConstant(Node* node, intptr_t& out_value) {
} }
Node* CodeAssembler::Parameter(int value) { Node* CodeAssembler::Parameter(int value) {
return raw_assembler_->Parameter(value); return raw_assembler()->Parameter(value);
} }
void CodeAssembler::Return(Node* value) { void CodeAssembler::Return(Node* value) {
return raw_assembler_->Return(value); return raw_assembler()->Return(value);
} }
void CodeAssembler::PopAndReturn(Node* pop, Node* 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, ...) { void CodeAssembler::Comment(const char* format, ...) {
if (!FLAG_code_comments) return; if (!FLAG_code_comments) return;
@ -206,81 +210,81 @@ void CodeAssembler::Comment(const char* format, ...) {
MemCopy(copy + prefix_len, builder.Finalize(), length); MemCopy(copy + prefix_len, builder.Finalize(), length);
copy[0] = ';'; copy[0] = ';';
copy[1] = ' '; copy[1] = ' ';
raw_assembler_->Comment(copy); raw_assembler()->Comment(copy);
} }
void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); } void CodeAssembler::Bind(CodeAssembler::Label* label) { return label->Bind(); }
Node* CodeAssembler::LoadFramePointer() { Node* CodeAssembler::LoadFramePointer() {
return raw_assembler_->LoadFramePointer(); return raw_assembler()->LoadFramePointer();
} }
Node* CodeAssembler::LoadParentFramePointer() { Node* CodeAssembler::LoadParentFramePointer() {
return raw_assembler_->LoadParentFramePointer(); return raw_assembler()->LoadParentFramePointer();
} }
Node* CodeAssembler::LoadStackPointer() { Node* CodeAssembler::LoadStackPointer() {
return raw_assembler_->LoadStackPointer(); return raw_assembler()->LoadStackPointer();
} }
#define DEFINE_CODE_ASSEMBLER_BINARY_OP(name) \ #define DEFINE_CODE_ASSEMBLER_BINARY_OP(name) \
Node* CodeAssembler::name(Node* a, Node* b) { \ 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) CODE_ASSEMBLER_BINARY_OP_LIST(DEFINE_CODE_ASSEMBLER_BINARY_OP)
#undef DEFINE_CODE_ASSEMBLER_BINARY_OP #undef DEFINE_CODE_ASSEMBLER_BINARY_OP
Node* CodeAssembler::WordShl(Node* value, int shift) { 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; : value;
} }
Node* CodeAssembler::WordShr(Node* value, int shift) { 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; : value;
} }
Node* CodeAssembler::Word32Shr(Node* value, int shift) { 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; : value;
} }
Node* CodeAssembler::ChangeUint32ToWord(Node* value) { Node* CodeAssembler::ChangeUint32ToWord(Node* value) {
if (raw_assembler_->machine()->Is64()) { if (raw_assembler()->machine()->Is64()) {
value = raw_assembler_->ChangeUint32ToUint64(value); value = raw_assembler()->ChangeUint32ToUint64(value);
} }
return value; return value;
} }
Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) { Node* CodeAssembler::ChangeInt32ToIntPtr(Node* value) {
if (raw_assembler_->machine()->Is64()) { if (raw_assembler()->machine()->Is64()) {
value = raw_assembler_->ChangeInt32ToInt64(value); value = raw_assembler()->ChangeInt32ToInt64(value);
} }
return value; return value;
} }
Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) { Node* CodeAssembler::RoundIntPtrToFloat64(Node* value) {
if (raw_assembler_->machine()->Is64()) { if (raw_assembler()->machine()->Is64()) {
return raw_assembler_->RoundInt64ToFloat64(value); return raw_assembler()->RoundInt64ToFloat64(value);
} }
return raw_assembler_->ChangeInt32ToFloat64(value); return raw_assembler()->ChangeInt32ToFloat64(value);
} }
#define DEFINE_CODE_ASSEMBLER_UNARY_OP(name) \ #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) CODE_ASSEMBLER_UNARY_OP_LIST(DEFINE_CODE_ASSEMBLER_UNARY_OP)
#undef DEFINE_CODE_ASSEMBLER_UNARY_OP #undef DEFINE_CODE_ASSEMBLER_UNARY_OP
Node* CodeAssembler::Load(MachineType rep, Node* base) { 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) { 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) { 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) { 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) { 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* CodeAssembler::Store(MachineRepresentation rep, Node* base, Node* index,
Node* value) { 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* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
Node* value) { 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* CodeAssembler::StoreNoWriteBarrier(MachineRepresentation rep, Node* base,
Node* index, Node* value) { 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* CodeAssembler::AtomicStore(MachineRepresentation rep, Node* base,
Node* index, Node* value) { 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) { 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) { Node* CodeAssembler::Retain(Node* value) {
return raw_assembler_->Retain(value); return raw_assembler()->Retain(value);
} }
Node* CodeAssembler::Projection(int index, Node* 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, void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
@ -346,11 +350,11 @@ void CodeAssembler::GotoIfException(Node* node, Label* if_exception,
exception.MergeVariables(); exception.MergeVariables();
DCHECK(!node->op()->HasProperty(Operator::kNoThrow)); DCHECK(!node->op()->HasProperty(Operator::kNoThrow));
raw_assembler_->Continuations(node, success.label_, exception.label_); raw_assembler()->Continuations(node, success.label_, exception.label_);
Bind(&exception); Bind(&exception);
const Operator* op = raw_assembler_->common()->IfException(); const Operator* op = raw_assembler()->common()->IfException();
Node* exception_value = raw_assembler_->AddNode(op, node, node); Node* exception_value = raw_assembler()->AddNode(op, node, node);
if (exception_var != nullptr) { if (exception_var != nullptr) {
exception_var->Bind(exception_value); 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* CodeAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
Node** args) { Node** args) {
CallPrologue(); CallPrologue();
Node* return_value = raw_assembler_->CallN(descriptor, code_target, args); Node* return_value = raw_assembler()->CallN(descriptor, code_target, args);
CallEpilogue(); CallEpilogue();
return return_value; return return_value;
} }
Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target, Node* CodeAssembler::TailCallN(CallDescriptor* descriptor, Node* code_target,
Node** args) { 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* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* context) { Node* context) {
CallPrologue(); CallPrologue();
Node* return_value = raw_assembler_->CallRuntime0(function_id, context); Node* return_value = raw_assembler()->CallRuntime0(function_id, context);
CallEpilogue(); CallEpilogue();
return return_value; return return_value;
} }
@ -383,7 +387,8 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context, Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
Node* arg1) { Node* arg1) {
CallPrologue(); CallPrologue();
Node* return_value = raw_assembler_->CallRuntime1(function_id, arg1, context); Node* return_value =
raw_assembler()->CallRuntime1(function_id, arg1, context);
CallEpilogue(); CallEpilogue();
return return_value; return return_value;
} }
@ -392,7 +397,7 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
Node* arg1, Node* arg2) { Node* arg1, Node* arg2) {
CallPrologue(); CallPrologue();
Node* return_value = Node* return_value =
raw_assembler_->CallRuntime2(function_id, arg1, arg2, context); raw_assembler()->CallRuntime2(function_id, arg1, arg2, context);
CallEpilogue(); CallEpilogue();
return return_value; return return_value;
} }
@ -401,7 +406,7 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
Node* arg1, Node* arg2, Node* arg3) { Node* arg1, Node* arg2, Node* arg3) {
CallPrologue(); CallPrologue();
Node* return_value = Node* return_value =
raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, context); raw_assembler()->CallRuntime3(function_id, arg1, arg2, arg3, context);
CallEpilogue(); CallEpilogue();
return return_value; return return_value;
} }
@ -410,8 +415,8 @@ Node* CodeAssembler::CallRuntime(Runtime::FunctionId function_id, Node* context,
Node* arg1, Node* arg2, Node* arg3, Node* arg1, Node* arg2, Node* arg3,
Node* arg4) { Node* arg4) {
CallPrologue(); CallPrologue();
Node* return_value = raw_assembler_->CallRuntime4(function_id, arg1, arg2, Node* return_value = raw_assembler()->CallRuntime4(function_id, arg1, arg2,
arg3, arg4, context); arg3, arg4, context);
CallEpilogue(); CallEpilogue();
return return_value; 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* arg1, Node* arg2, Node* arg3, Node* arg4,
Node* arg5) { Node* arg5) {
CallPrologue(); CallPrologue();
Node* return_value = raw_assembler_->CallRuntime5(function_id, arg1, arg2, Node* return_value = raw_assembler()->CallRuntime5(function_id, arg1, arg2,
arg3, arg4, arg5, context); arg3, arg4, arg5, context);
CallEpilogue(); CallEpilogue();
return return_value; return return_value;
} }
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context) { Node* context) {
return raw_assembler_->TailCallRuntime0(function_id, context); return raw_assembler()->TailCallRuntime0(function_id, context);
} }
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context, Node* arg1) { 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* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context, Node* arg1, Node* arg2) { 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* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context, Node* arg1, Node* arg2, Node* context, Node* arg1, Node* arg2,
Node* arg3) { Node* arg3) {
return raw_assembler_->TailCallRuntime3(function_id, arg1, arg2, arg3, return raw_assembler()->TailCallRuntime3(function_id, arg1, arg2, arg3,
context); context);
} }
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context, Node* arg1, Node* arg2, Node* context, Node* arg1, Node* arg2,
Node* arg3, Node* arg4) { Node* arg3, Node* arg4) {
return raw_assembler_->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4, return raw_assembler()->TailCallRuntime4(function_id, arg1, arg2, arg3, arg4,
context); context);
} }
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context, Node* arg1, Node* arg2, Node* context, Node* arg1, Node* arg2,
Node* arg3, Node* arg4, Node* arg5) { Node* arg3, Node* arg4, Node* arg5) {
return raw_assembler_->TailCallRuntime5(function_id, arg1, arg2, arg3, arg4, return raw_assembler()->TailCallRuntime5(function_id, arg1, arg2, arg3, arg4,
arg5, context); arg5, context);
} }
Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id, Node* CodeAssembler::TailCallRuntime(Runtime::FunctionId function_id,
Node* context, Node* arg1, Node* arg2, Node* context, Node* arg1, Node* arg2,
Node* arg3, Node* arg4, Node* arg5, Node* arg3, Node* arg4, Node* arg5,
Node* arg6) { Node* arg6) {
return raw_assembler_->TailCallRuntime6(function_id, arg1, arg2, arg3, arg4, return raw_assembler()->TailCallRuntime6(function_id, arg1, arg2, arg3, arg4,
arg5, arg6, context); arg5, arg6, context);
} }
Node* CodeAssembler::CallStub(Callable const& callable, Node* context, Node* CodeAssembler::CallStub(Callable const& callable, Node* context,
@ -752,7 +757,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[0] = arg1; args[0] = arg1;
args[1] = context; 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -768,7 +773,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[1] = arg2; args[1] = arg2;
args[2] = context; 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -785,7 +790,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[2] = arg3; args[2] = arg3;
args[3] = context; 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -804,7 +809,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[3] = arg4; args[3] = arg4;
args[4] = context; 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -824,7 +829,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[4] = arg5; args[4] = arg5;
args[5] = context; 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -845,7 +850,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[5] = arg6; args[5] = arg6;
args[6] = context; 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -867,7 +872,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[kArgsCount - 1] = context; args[kArgsCount - 1] = context;
DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr)); 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, Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
@ -891,7 +896,7 @@ Node* CodeAssembler::TailCallStub(const CallInterfaceDescriptor& descriptor,
args[kArgsCount - 1] = context; args[kArgsCount - 1] = context;
DCHECK_EQ(0, std::count(&args[0], &args[kArgsCount], nullptr)); 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( Node* CodeAssembler::TailCallBytecodeDispatch(
@ -900,7 +905,7 @@ Node* CodeAssembler::TailCallBytecodeDispatch(
CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor( CallDescriptor* descriptor = Linkage::GetBytecodeDispatchCallDescriptor(
isolate(), zone(), interface_descriptor, isolate(), zone(), interface_descriptor,
interface_descriptor.GetStackParameterCount()); 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, Node* CodeAssembler::CallJS(Callable const& callable, Node* context,
@ -973,13 +978,13 @@ Node* CodeAssembler::CallCFunction2(MachineType return_type,
MachineType arg0_type, MachineType arg0_type,
MachineType arg1_type, Node* function, MachineType arg1_type, Node* function,
Node* arg0, Node* arg1) { Node* arg0, Node* arg1) {
return raw_assembler_->CallCFunction2(return_type, arg0_type, arg1_type, return raw_assembler()->CallCFunction2(return_type, arg0_type, arg1_type,
function, arg0, arg1); function, arg0, arg1);
} }
void CodeAssembler::Goto(CodeAssembler::Label* label) { void CodeAssembler::Goto(CodeAssembler::Label* label) {
label->MergeVariables(); label->MergeVariables();
raw_assembler_->Goto(label->label_); raw_assembler()->Goto(label->label_);
} }
void CodeAssembler::GotoIf(Node* condition, Label* true_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) { CodeAssembler::Label* false_label) {
true_label->MergeVariables(); true_label->MergeVariables();
false_label->MergeVariables(); false_label->MergeVariables();
return raw_assembler_->Branch(condition, true_label->label_, return raw_assembler()->Branch(condition, true_label->label_,
false_label->label_); false_label->label_);
} }
void CodeAssembler::Switch(Node* index, Label* default_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(); case_labels[i]->MergeVariables();
default_label->MergeVariables(); default_label->MergeVariables();
} }
return raw_assembler_->Switch(index, default_label->label_, case_values, return raw_assembler()->Switch(index, default_label->label_, case_values,
labels, case_count); labels, case_count);
} }
Node* CodeAssembler::Select(Node* condition, Node* true_value, Node* CodeAssembler::Select(Node* condition, Node* true_value,
@ -1039,11 +1044,15 @@ Node* CodeAssembler::Select(Node* condition, Node* true_value,
} }
// RawMachineAssembler delegate helpers: // 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(); } 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 // The core implementation of Variable is stored through an indirection so
// that it can outlive the often block-scoped Variable declarations. This is // 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, CodeAssembler::Variable::Variable(CodeAssembler* assembler,
MachineRepresentation rep) MachineRepresentation rep)
: impl_(new (assembler->zone()) Impl(rep)), assembler_(assembler) { : impl_(new (assembler->zone()) Impl(rep)), state_(assembler->state_) {
assembler->variables_.insert(impl_); 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; } 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, CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
Variable** vars, CodeAssembler::Label::Type type) 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)); void* buffer = assembler->zone()->New(sizeof(RawMachineLabel));
label_ = new (buffer) label_ = new (buffer)
RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred RawMachineLabel(type == kDeferred ? RawMachineLabel::kDeferred
@ -1093,7 +1105,7 @@ CodeAssembler::Label::Label(CodeAssembler* assembler, size_t vars_count,
void CodeAssembler::Label::MergeVariables() { void CodeAssembler::Label::MergeVariables() {
++merge_count_; ++merge_count_;
for (auto var : assembler_->variables_) { for (auto var : state_->variables_) {
size_t count = 0; size_t count = 0;
Node* node = var->value_; Node* node = var->value_;
if (node != nullptr) { if (node != nullptr) {
@ -1118,7 +1130,7 @@ void CodeAssembler::Label::MergeVariables() {
auto phi = variable_phis_.find(var); auto phi = variable_phis_.find(var);
if (phi != variable_phis_.end()) { if (phi != variable_phis_.end()) {
DCHECK_NOT_NULL(phi->second); DCHECK_NOT_NULL(phi->second);
assembler_->raw_assembler_->AppendPhiInput(phi->second, node); state_->raw_assembler_->AppendPhiInput(phi->second, node);
} else { } else {
auto i = variable_merges_.find(var); auto i = variable_merges_.find(var);
if (i != variable_merges_.end()) { if (i != variable_merges_.end()) {
@ -1139,11 +1151,11 @@ void CodeAssembler::Label::MergeVariables() {
void CodeAssembler::Label::Bind() { void CodeAssembler::Label::Bind() {
DCHECK(!bound_); 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 // Make sure that all variables that have changed along any path up to this
// point are marked as merge variables. // point are marked as merge variables.
for (auto var : assembler_->variables_) { for (auto var : state_->variables_) {
Node* shared_value = nullptr; Node* shared_value = nullptr;
auto i = variable_merges_.find(var); auto i = variable_merges_.find(var);
if (i != variable_merges_.end()) { 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 // 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. // have been merged into the label up to this point.
DCHECK(i != variable_merges_.end() && i->second.size() == merge_count_); 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])); var.first->rep_, static_cast<int>(merge_count_), &(i->second[0]));
variable_phis_[var_impl] = phi; variable_phis_[var_impl] = phi;
} }
// Bind all variables to a merge phi, the common value along all paths or // Bind all variables to a merge phi, the common value along all paths or
// null. // null.
for (auto var : assembler_->variables_) { for (auto var : state_->variables_) {
auto i = variable_phis_.find(var); auto i = variable_phis_.find(var);
if (i != variable_phis_.end()) { if (i != variable_phis_.end()) {
var->value_ = i->second; var->value_ = i->second;

View File

@ -30,6 +30,7 @@ class Zone;
namespace compiler { namespace compiler {
class CallDescriptor; class CallDescriptor;
class CodeAssemblerState;
class Node; class Node;
class RawMachineAssembler; class RawMachineAssembler;
class RawMachineLabel; class RawMachineLabel;
@ -173,22 +174,17 @@ class RawMachineLabel;
// clients, CodeAssembler also provides an abstraction for creating variables // clients, CodeAssembler also provides an abstraction for creating variables
// and enhanced Label functionality to merge variable values along paths where // and enhanced Label functionality to merge variable values along paths where
// they have differing values, including loops. // 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 { class V8_EXPORT_PRIVATE CodeAssembler {
public: public:
// Create with CallStub linkage. explicit CodeAssembler(CodeAssemblerState* state) : state_(state) {}
// |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);
virtual ~CodeAssembler(); virtual ~CodeAssembler();
Handle<Code> GenerateCode(); static Handle<Code> GenerateCode(CodeAssemblerState* state);
bool Is64() const; bool Is64() const;
bool IsFloat64RoundUpSupported() const; bool IsFloat64RoundUpSupported() const;
@ -207,9 +203,10 @@ class V8_EXPORT_PRIVATE CodeAssembler {
private: private:
friend class CodeAssembler; friend class CodeAssembler;
friend class CodeAssemblerState;
class Impl; class Impl;
Impl* impl_; Impl* impl_;
CodeAssembler* assembler_; CodeAssemblerState* state_;
}; };
typedef ZoneList<Variable*> VariableList; typedef ZoneList<Variable*> VariableList;
@ -471,17 +468,12 @@ class V8_EXPORT_PRIVATE CodeAssembler {
virtual void CallEpilogue(); virtual void CallEpilogue();
private: 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* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args); Node* TailCallN(CallDescriptor* descriptor, Node* code_target, Node** args);
std::unique_ptr<RawMachineAssembler> raw_assembler_; RawMachineAssembler* raw_assembler() const;
Code::Flags flags_;
const char* name_; CodeAssemblerState* state_;
bool code_generated_;
ZoneSet<Variable::Impl*> variables_;
DISALLOW_COPY_AND_ASSIGN(CodeAssembler); DISALLOW_COPY_AND_ASSIGN(CodeAssembler);
}; };
@ -513,7 +505,7 @@ class CodeAssembler::Label {
bool bound_; bool bound_;
size_t merge_count_; size_t merge_count_;
CodeAssembler* assembler_; CodeAssemblerState* state_;
RawMachineLabel* label_; RawMachineLabel* label_;
// Map of variables that need to be merged to their phi nodes (or placeholders // Map of variables that need to be merged to their phi nodes (or placeholders
// for those phis). // for those phis).
@ -523,6 +515,38 @@ class CodeAssembler::Label {
std::map<Variable::Impl*, std::vector<Node*>> variable_merges_; 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 compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -10,7 +10,6 @@
#include "src/handles-inl.h" #include "src/handles-inl.h"
#include "src/objects.h" // For FAA::LoadInternalField impl. #include "src/objects.h" // For FAA::LoadInternalField impl.
using v8::internal::CodeStubAssembler;
using v8::internal::compiler::Node; using v8::internal::compiler::Node;
namespace v8 { namespace v8 {
@ -19,9 +18,9 @@ namespace internal {
FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate) FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate)
: zone_(isolate->allocator(), ZONE_NAME), : zone_(isolate->allocator(), ZONE_NAME),
isolate_(isolate), isolate_(isolate),
assembler_(new CodeStubAssembler(isolate, zone(), 1, assembler_state_(isolate, zone(), 1, Code::ComputeFlags(Code::STUB),
Code::ComputeFlags(Code::STUB), "FastAccessorAssembler"),
"FastAccessorAssembler")), assembler_(new CodeStubAssembler(&assembler_state_)),
state_(kBuilding) {} state_(kBuilding) {}
FastAccessorAssembler::~FastAccessorAssembler() { Clear(); } FastAccessorAssembler::~FastAccessorAssembler() { Clear(); }
@ -248,7 +247,7 @@ void FastAccessorAssembler::CheckIsJSObjectOrJump(ValueId value_id,
MaybeHandle<Code> FastAccessorAssembler::Build() { MaybeHandle<Code> FastAccessorAssembler::Build() {
CHECK_EQ(kBuilding, state_); CHECK_EQ(kBuilding, state_);
Handle<Code> code = assembler_->GenerateCode(); Handle<Code> code = compiler::CodeAssembler::GenerateCode(&assembler_state_);
state_ = !code.is_null() ? kBuilt : kError; state_ = !code.is_null() ? kBuilt : kError;
Clear(); Clear();
return code; return code;

View File

@ -98,6 +98,7 @@ class FastAccessorAssembler {
Zone zone_; Zone zone_;
Isolate* isolate_; Isolate* isolate_;
compiler::CodeAssemblerState assembler_state_;
std::unique_ptr<CodeStubAssembler> assembler_; std::unique_ptr<CodeStubAssembler> assembler_;
// To prevent exposing the RMA internals to the outside world, we'll map // 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/ic/keyed-store-generic.h"
#include "src/compiler/code-assembler.h" #include "src/code-stub-assembler.h"
#include "src/contexts.h" #include "src/contexts.h"
#include "src/interface-descriptors.h"
#include "src/isolate.h" #include "src/isolate.h"
namespace v8 { namespace v8 {
@ -15,6 +16,9 @@ using compiler::Node;
class KeyedStoreGenericAssembler : public CodeStubAssembler { class KeyedStoreGenericAssembler : public CodeStubAssembler {
public: public:
explicit KeyedStoreGenericAssembler(compiler::CodeAssemblerState* state)
: CodeStubAssembler(state) {}
void KeyedStoreGeneric(const StoreICParameters* p, void KeyedStoreGeneric(const StoreICParameters* p,
LanguageMode language_mode); LanguageMode language_mode);
@ -59,17 +63,23 @@ class KeyedStoreGenericAssembler : public CodeStubAssembler {
Node* current_elements_kind, Node* context, Node* current_elements_kind, Node* context,
ElementsKind packed_kind, ElementsKind packed_kind,
ElementsKind packed_kind_2, Label* bailout); ElementsKind packed_kind_2, Label* bailout);
// Do not add fields, so that this is safe to reinterpret_cast to CSA.
}; };
void KeyedStoreGenericGenerator::Generate( void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
CodeStubAssembler* assembler, const CodeStubAssembler::StoreICParameters* p, LanguageMode language_mode) {
LanguageMode language_mode) { typedef StoreWithVectorDescriptor Descriptor;
STATIC_ASSERT(sizeof(CodeStubAssembler) == KeyedStoreGenericAssembler assembler(state);
sizeof(KeyedStoreGenericAssembler));
auto assm = reinterpret_cast<KeyedStoreGenericAssembler*>(assembler); Node* receiver = assembler.Parameter(Descriptor::kReceiver);
assm->KeyedStoreGeneric(p, language_mode); 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( void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(

View File

@ -5,15 +5,18 @@
#ifndef V8_SRC_IC_KEYED_STORE_GENERIC_H_ #ifndef V8_SRC_IC_KEYED_STORE_GENERIC_H_
#define 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 v8 {
namespace internal { namespace internal {
namespace compiler {
class CodeAssemblerState;
}
class KeyedStoreGenericGenerator { class KeyedStoreGenericGenerator {
public: public:
static void Generate(CodeStubAssembler* assembler, static void Generate(compiler::CodeAssemblerState* state,
const CodeStubAssembler::StoreICParameters* p,
LanguageMode language_mode); LanguageMode language_mode);
}; };

View File

@ -157,8 +157,7 @@ class CallDescriptors {
}; };
}; };
class V8_EXPORT_PRIVATE CallInterfaceDescriptor {
class CallInterfaceDescriptor {
public: public:
CallInterfaceDescriptor() : data_(NULL) {} CallInterfaceDescriptor() : data_(NULL) {}
virtual ~CallInterfaceDescriptor() {} virtual ~CallInterfaceDescriptor() {}
@ -775,7 +774,8 @@ class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
static const Register KeyRegister(); static const Register KeyRegister();
}; };
class InterpreterDispatchDescriptor : public CallInterfaceDescriptor { class V8_EXPORT_PRIVATE InterpreterDispatchDescriptor
: public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kAccumulator, kBytecodeOffset, kBytecodeArray, DEFINE_PARAMETERS(kAccumulator, kBytecodeOffset, kBytecodeArray,
kDispatchTable) kDispatchTable)

View File

@ -20,15 +20,13 @@ namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
using compiler::CodeAssemblerState;
using compiler::Node; using compiler::Node;
InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone, InterpreterAssembler::InterpreterAssembler(CodeAssemblerState* state,
Bytecode bytecode, Bytecode bytecode,
OperandScale operand_scale) OperandScale operand_scale)
: CodeStubAssembler(isolate, zone, InterpreterDispatchDescriptor(isolate), : CodeStubAssembler(state),
Code::ComputeFlags(Code::BYTECODE_HANDLER),
Bytecodes::ToString(bytecode),
Bytecodes::ReturnCount(bytecode)),
bytecode_(bytecode), bytecode_(bytecode),
operand_scale_(operand_scale), operand_scale_(operand_scale),
bytecode_offset_(this, MachineType::PointerRepresentation()), bytecode_offset_(this, MachineType::PointerRepresentation()),

View File

@ -20,7 +20,7 @@ namespace interpreter {
class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler { class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler {
public: public:
InterpreterAssembler(Isolate* isolate, Zone* zone, Bytecode bytecode, InterpreterAssembler(compiler::CodeAssemblerState* state, Bytecode bytecode,
OperandScale operand_scale); OperandScale operand_scale);
virtual ~InterpreterAssembler(); virtual ~InterpreterAssembler();

View File

@ -76,10 +76,16 @@ void Interpreter::Initialize() {
#define GENERATE_CODE(Name, ...) \ #define GENERATE_CODE(Name, ...) \
{ \ { \
if (Bytecodes::BytecodeHasHandler(Bytecode::k##Name, operand_scale)) { \ 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); \ operand_scale); \
Do##Name(&assembler); \ Do##Name(&assembler); \
Handle<Code> code = assembler.GenerateCode(); \ Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state); \
size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale); \ size_t index = GetDispatchTableIndex(Bytecode::k##Name, operand_scale); \
dispatch_table_[index] = code->entry(); \ dispatch_table_[index] = code->entry(); \
TraceCodegen(code); \ TraceCodegen(code); \

View File

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "src/compiler/code-assembler.h"
#include "src/handles.h" #include "src/handles.h"
#include "src/interface-descriptors.h" #include "src/interface-descriptors.h"
#include "src/isolate.h" #include "src/isolate.h"
@ -11,51 +12,43 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
class ZoneHolder { class CodeAssemblerTester {
public: public:
explicit ZoneHolder(Isolate* isolate) // Test generating code for a stub. Assumes VoidDescriptor call interface.
: held_zone_(isolate->allocator(), ZONE_NAME) {} explicit CodeAssemblerTester(Isolate* isolate)
Zone* held_zone() { return &held_zone_; } : zone_(isolate->allocator(), ZONE_NAME),
scope_(isolate),
private: state_(isolate, &zone_, VoidDescriptor(isolate),
Zone held_zone_; Code::ComputeFlags(Code::STUB), "test") {}
};
// 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 JS function (e.g. builtins). // Test generating code for a JS function (e.g. builtins).
CodeAssemblerTesterImpl(Isolate* isolate, int parameter_count, CodeAssemblerTester(Isolate* isolate, int parameter_count,
Code::Kind kind = Code::BUILTIN) Code::Kind kind = Code::BUILTIN)
: ZoneHolder(isolate), : zone_(isolate->allocator(), ZONE_NAME),
CodeAssemblerT(isolate, ZoneHolder::held_zone(), parameter_count, scope_(isolate),
Code::ComputeFlags(kind), "test"), state_(isolate, &zone_, parameter_count, Code::ComputeFlags(kind),
scope_(isolate) {} "test") {}
// This constructor is intended to be used for creating code objects with // This constructor is intended to be used for creating code objects with
// specific flags. // specific flags.
CodeAssemblerTesterImpl(Isolate* isolate, Code::Flags flags) CodeAssemblerTester(Isolate* isolate, Code::Flags flags)
: ZoneHolder(isolate), : zone_(isolate->allocator(), ZONE_NAME),
CodeAssemblerT(isolate, ZoneHolder::held_zone(), 0, flags, "test"), scope_(isolate),
scope_(isolate) {} state_(isolate, &zone_, 0, flags, "test") {}
CodeAssemblerState* state() { return &state_; }
Handle<Code> GenerateCode() { return CodeAssembler::GenerateCode(&state_); }
Handle<Code> GenerateCodeCloseAndEscape() { Handle<Code> GenerateCodeCloseAndEscape() {
return scope_.CloseAndEscape(CodeAssemblerT::GenerateCode()); return scope_.CloseAndEscape(CodeAssembler::GenerateCode(&state_));
} }
private: private:
Zone zone_;
HandleScope scope_; HandleScope scope_;
LocalContext context_; LocalContext context_;
CodeAssemblerState state_;
}; };
} // namespace compiler } // namespace compiler

View File

@ -46,9 +46,7 @@ FunctionTester::FunctionTester(Handle<Code> code, int param_count)
function->ReplaceCode(*code); function->ReplaceCode(*code);
} }
FunctionTester::FunctionTester(const CallInterfaceDescriptor& descriptor, FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {}
Handle<Code> code)
: FunctionTester(code, descriptor.GetParameterCount()) {}
MaybeHandle<Object> FunctionTester::Call() { MaybeHandle<Object> FunctionTester::Call() {
return Execution::Call(isolate, function, undefined(), 0, nullptr); 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(Handle<Code> code, int param_count);
FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code); // Assumes VoidDescriptor call interface.
explicit FunctionTester(Handle<Code> code);
Isolate* isolate; Isolate* isolate;
Handle<JSFunction> function; Handle<JSFunction> function;

View File

@ -12,11 +12,9 @@ namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
typedef CodeAssemblerTesterImpl<CodeAssembler> CodeAssemblerTester;
namespace { namespace {
Node* SmiTag(CodeAssemblerTester& m, Node* value) { Node* SmiTag(CodeAssembler& m, Node* value) {
int32_t constant_value; int32_t constant_value;
if (m.ToInt32Constant(value, constant_value) && if (m.ToInt32Constant(value, constant_value) &&
Smi::IsValid(constant_value)) { Smi::IsValid(constant_value)) {
@ -25,11 +23,11 @@ Node* SmiTag(CodeAssemblerTester& m, Node* value) {
return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize)); return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize));
} }
Node* UndefinedConstant(CodeAssemblerTester& m) { Node* UndefinedConstant(CodeAssembler& m) {
return m.LoadRoot(Heap::kUndefinedValueRootIndex); 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()) { MachineType rep = MachineType::AnyTagged()) {
return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag)); return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag));
} }
@ -38,23 +36,23 @@ Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset,
TEST(SimpleSmiReturn) { TEST(SimpleSmiReturn) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
m.Return(SmiTag(m, m.Int32Constant(37))); m.Return(SmiTag(m, m.Int32Constant(37)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
TEST(SimpleIntPtrReturn) { TEST(SimpleIntPtrReturn) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
int test; int test;
m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test))); m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(reinterpret_cast<intptr_t>(&test), CHECK_EQ(reinterpret_cast<intptr_t>(&test),
reinterpret_cast<intptr_t>(*result.ToHandleChecked())); reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
@ -62,65 +60,65 @@ TEST(SimpleIntPtrReturn) {
TEST(SimpleDoubleReturn) { TEST(SimpleDoubleReturn) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
m.Return(m.NumberConstant(0.5)); m.Return(m.NumberConstant(0.5));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value()); CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
} }
TEST(SimpleCallRuntime1Arg) { TEST(SimpleCallRuntime1Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* b = SmiTag(m, m.Int32Constant(0)); Node* b = SmiTag(m, m.Int32Constant(0));
m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b)); m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
TEST(SimpleTailCallRuntime1Arg) { TEST(SimpleTailCallRuntime1Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* b = SmiTag(m, m.Int32Constant(0)); Node* b = SmiTag(m, m.Int32Constant(0));
m.TailCallRuntime(Runtime::kNumberToSmi, context, b); m.TailCallRuntime(Runtime::kNumberToSmi, context, b);
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
TEST(SimpleCallRuntime2Arg) { TEST(SimpleCallRuntime2Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* a = SmiTag(m, m.Int32Constant(2)); Node* a = SmiTag(m, m.Int32Constant(2));
Node* b = SmiTag(m, m.Int32Constant(4)); Node* b = SmiTag(m, m.Int32Constant(4));
m.Return(m.CallRuntime(Runtime::kAdd, context, a, b)); m.Return(m.CallRuntime(Runtime::kAdd, context, a, b));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
TEST(SimpleTailCallRuntime2Arg) { TEST(SimpleTailCallRuntime2Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* a = SmiTag(m, m.Int32Constant(2)); Node* a = SmiTag(m, m.Int32Constant(2));
Node* b = SmiTag(m, m.Int32Constant(4)); Node* b = SmiTag(m, m.Int32Constant(4));
m.TailCallRuntime(Runtime::kAdd, context, a, b); m.TailCallRuntime(Runtime::kAdd, context, a, b);
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
@ -144,7 +142,8 @@ Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) {
TEST(SimpleCallJSFunction0Arg) { TEST(SimpleCallJSFunction0Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1; const int kNumParams = 1;
CodeAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeAssembler m(data.state());
{ {
Node* function = m.Parameter(0); Node* function = m.Parameter(0);
Node* context = m.Parameter(kNumParams + 2); Node* context = m.Parameter(kNumParams + 2);
@ -155,7 +154,7 @@ TEST(SimpleCallJSFunction0Arg) {
Node* result = m.CallJS(callable, context, function, receiver); Node* result = m.CallJS(callable, context, function, receiver);
m.Return(result); m.Return(result);
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
@ -166,7 +165,8 @@ TEST(SimpleCallJSFunction0Arg) {
TEST(SimpleCallJSFunction1Arg) { TEST(SimpleCallJSFunction1Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2; const int kNumParams = 2;
CodeAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeAssembler m(data.state());
{ {
Node* function = m.Parameter(0); Node* function = m.Parameter(0);
Node* context = m.Parameter(1); Node* context = m.Parameter(1);
@ -178,7 +178,7 @@ TEST(SimpleCallJSFunction1Arg) {
Node* result = m.CallJS(callable, context, function, receiver, a); Node* result = m.CallJS(callable, context, function, receiver, a);
m.Return(result); m.Return(result);
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
@ -189,7 +189,8 @@ TEST(SimpleCallJSFunction1Arg) {
TEST(SimpleCallJSFunction2Arg) { TEST(SimpleCallJSFunction2Arg) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2; const int kNumParams = 2;
CodeAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeAssembler m(data.state());
{ {
Node* function = m.Parameter(0); Node* function = m.Parameter(0);
Node* context = m.Parameter(1); Node* context = m.Parameter(1);
@ -202,7 +203,7 @@ TEST(SimpleCallJSFunction2Arg) {
Node* result = m.CallJS(callable, context, function, receiver, a, b); Node* result = m.CallJS(callable, context, function, receiver, a, b);
m.Return(result); m.Return(result);
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
@ -212,8 +213,8 @@ TEST(SimpleCallJSFunction2Arg) {
TEST(VariableMerge1) { TEST(VariableMerge1) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
Node* temp = m.Int32Constant(0); Node* temp = m.Int32Constant(0);
@ -231,8 +232,8 @@ TEST(VariableMerge1) {
TEST(VariableMerge2) { TEST(VariableMerge2) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
Node* temp = m.Int32Constant(0); Node* temp = m.Int32Constant(0);
@ -252,8 +253,8 @@ TEST(VariableMerge2) {
TEST(VariableMerge3) { TEST(VariableMerge3) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged); CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
@ -277,8 +278,8 @@ TEST(VariableMerge3) {
TEST(VariableMergeBindFirst) { TEST(VariableMergeBindFirst) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m); CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
Node* temp = m.Int32Constant(0); Node* temp = m.Int32Constant(0);
@ -303,8 +304,8 @@ TEST(VariableMergeBindFirst) {
TEST(VariableMergeSwitch) { TEST(VariableMergeSwitch) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m); CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
CodeStubAssembler::Label* labels[] = {&l1, &l2}; CodeStubAssembler::Label* labels[] = {&l1, &l2};
@ -325,20 +326,20 @@ TEST(VariableMergeSwitch) {
TEST(SplitEdgeBranchMerge) { TEST(SplitEdgeBranchMerge) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Label l1(&m), merge(&m); CodeStubAssembler::Label l1(&m), merge(&m);
m.Branch(m.Int32Constant(1), &l1, &merge); m.Branch(m.Int32Constant(1), &l1, &merge);
m.Bind(&l1); m.Bind(&l1);
m.Goto(&merge); m.Goto(&merge);
m.Bind(&merge); m.Bind(&merge);
USE(m.GenerateCode()); USE(data.GenerateCode());
} }
TEST(SplitEdgeSwitchMerge) { TEST(SplitEdgeSwitchMerge) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m); CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m);
CodeStubAssembler::Label* labels[] = {&l1, &l2}; CodeStubAssembler::Label* labels[] = {&l1, &l2};
int32_t values[] = {1, 2}; int32_t values[] = {1, 2};
@ -350,13 +351,13 @@ TEST(SplitEdgeSwitchMerge) {
m.Bind(&l2); m.Bind(&l2);
m.Goto(&default_label); m.Goto(&default_label);
m.Bind(&default_label); m.Bind(&default_label);
USE(m.GenerateCode()); USE(data.GenerateCode());
} }
TEST(TestToConstant) { TEST(TestToConstant) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
int32_t value32; int32_t value32;
int64_t value64; int64_t value64;
Node* a = m.Int32Constant(5); Node* a = m.Int32Constant(5);
@ -385,8 +386,8 @@ TEST(DeferredCodePhiHints) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
Label block1(&m, Label::kDeferred); Label block1(&m, Label::kDeferred);
m.Goto(&block1); m.Goto(&block1);
m.Bind(&block1); m.Bind(&block1);
@ -402,15 +403,15 @@ TEST(DeferredCodePhiHints) {
m.Goto(&loop); m.Goto(&loop);
} }
} }
CHECK(!m.GenerateCode().is_null()); CHECK(!data.GenerateCode().is_null());
} }
TEST(TestOutOfScopeVariable) { TEST(TestOutOfScopeVariable) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeAssemblerTester m(isolate, descriptor); CodeAssembler m(data.state());
Label block1(&m); Label block1(&m);
Label block2(&m); Label block2(&m);
Label block3(&m); Label block3(&m);
@ -431,7 +432,7 @@ TEST(TestOutOfScopeVariable) {
m.Goto(&block1); m.Goto(&block1);
} }
m.Bind(&block1); m.Bind(&block1);
CHECK(!m.GenerateCode().is_null()); CHECK(!data.GenerateCode().is_null());
} }
} // namespace compiler } // namespace compiler

View File

@ -14,48 +14,46 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
using compiler::CodeAssemblerTester;
using compiler::FunctionTester; using compiler::FunctionTester;
using compiler::Node; using compiler::Node;
typedef compiler::CodeAssemblerTesterImpl<CodeStubAssembler>
CodeStubAssemblerTester;
TEST(FixedArrayAccessSmiIndex) { TEST(FixedArrayAccessSmiIndex) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeStubAssemblerTester m(isolate, descriptor); CodeStubAssembler m(data.state());
Handle<FixedArray> array = isolate->factory()->NewFixedArray(5); Handle<FixedArray> array = isolate->factory()->NewFixedArray(5);
array->set(4, Smi::FromInt(733)); array->set(4, Smi::FromInt(733));
m.Return(m.LoadFixedArrayElement(m.HeapConstant(array), m.Return(m.LoadFixedArrayElement(m.HeapConstant(array),
m.SmiTag(m.Int32Constant(4)), 0, m.SmiTag(m.Int32Constant(4)), 0,
CodeStubAssembler::SMI_PARAMETERS)); CodeStubAssembler::SMI_PARAMETERS));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
TEST(LoadHeapNumberValue) { TEST(LoadHeapNumberValue) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeStubAssemblerTester m(isolate, descriptor); CodeStubAssembler m(data.state());
Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234); Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234);
m.Return(m.SmiTag( m.Return(m.SmiTag(
m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number))))); m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number)))));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value()); CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value());
} }
TEST(LoadInstanceType) { TEST(LoadInstanceType) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeStubAssemblerTester m(isolate, descriptor); CodeStubAssembler m(data.state());
Handle<HeapObject> undefined = isolate->factory()->undefined_value(); Handle<HeapObject> undefined = isolate->factory()->undefined_value();
m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined)))); m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined))));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
CHECK_EQ(InstanceType::ODDBALL_TYPE, CHECK_EQ(InstanceType::ODDBALL_TYPE,
Handle<Smi>::cast(result.ToHandleChecked())->value()); Handle<Smi>::cast(result.ToHandleChecked())->value());
@ -63,14 +61,14 @@ TEST(LoadInstanceType) {
TEST(DecodeWordFromWord32) { TEST(DecodeWordFromWord32) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeStubAssemblerTester m(isolate, descriptor); CodeStubAssembler m(data.state());
class TestBitField : public BitField<unsigned, 3, 3> {}; class TestBitField : public BitField<unsigned, 3, 3> {};
m.Return( m.Return(
m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2f)))); m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2f))));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(descriptor, code); FunctionTester ft(code);
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
// value = 00101111 // value = 00101111
// mask = 00111000 // mask = 00111000
@ -81,11 +79,12 @@ TEST(DecodeWordFromWord32) {
TEST(JSFunction) { TEST(JSFunction) {
const int kNumParams = 3; // Receiver, left, right. const int kNumParams = 3; // Receiver, left, right.
Isolate* isolate(CcTest::InitIsolateOnce()); 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.Return(m.SmiFromWord32(m.Int32Add(m.SmiToWord32(m.Parameter(1)),
m.SmiToWord32(m.Parameter(2))))); m.SmiToWord32(m.Parameter(2)))));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(), MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(),
@ -97,11 +96,12 @@ TEST(JSFunction) {
TEST(ComputeIntegerHash) { TEST(ComputeIntegerHash) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2; const int kNumParams = 2;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
m.Return(m.SmiFromWord32(m.ComputeIntegerHash( m.Return(m.SmiFromWord32(m.ComputeIntegerHash(
m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1))))); m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1)))));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Smi> hash_seed = isolate->factory()->hash_seed(); Handle<Smi> hash_seed = isolate->factory()->hash_seed();
@ -123,10 +123,11 @@ TEST(ComputeIntegerHash) {
TEST(ToString) { TEST(ToString) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1; 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))); 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); FunctionTester ft(code, kNumParams);
Handle<FixedArray> test_cases = isolate->factory()->NewFixedArray(5); Handle<FixedArray> test_cases = isolate->factory()->NewFixedArray(5);
@ -179,10 +180,11 @@ TEST(ToString) {
TEST(FlattenString) { TEST(FlattenString) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1; const int kNumParams = 1;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
m.Return(m.FlattenString(m.Parameter(0))); m.Return(m.FlattenString(m.Parameter(0)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<FixedArray> test_cases(isolate->factory()->NewFixedArray(4)); Handle<FixedArray> test_cases(isolate->factory()->NewFixedArray(4));
@ -222,7 +224,8 @@ TEST(TryToName) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 3; const int kNumParams = 3;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
enum Result { kKeyIsIndex, kKeyIsUnique, kBailout }; enum Result { kKeyIsIndex, kKeyIsUnique, kBailout };
{ {
@ -261,7 +264,7 @@ TEST(TryToName) {
m.Return(m.BooleanConstant(false)); m.Return(m.BooleanConstant(false));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate); Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate);
@ -352,14 +355,15 @@ void TestEntryToIndex() {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1; const int kNumParams = 1;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
{ {
Node* entry = m.SmiUntag(m.Parameter(0)); Node* entry = m.SmiUntag(m.Parameter(0));
Node* result = m.EntryToIndex<Dictionary>(entry); Node* result = m.EntryToIndex<Dictionary>(entry);
m.Return(m.SmiTag(result)); m.Return(m.SmiTag(result));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
// Test a wide range of entries but staying linear in the first 100 entries. // Test a wide range of entries but staying linear in the first 100 entries.
@ -385,7 +389,8 @@ void TestNameDictionaryLookup() {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound }; enum Result { kFound, kNotFound };
{ {
@ -419,7 +424,7 @@ void TestNameDictionaryLookup() {
m.Return(m.BooleanConstant(false)); m.Return(m.BooleanConstant(false));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate); Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
@ -491,7 +496,8 @@ void TestNumberDictionaryLookup() {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound }; enum Result { kFound, kNotFound };
{ {
@ -525,7 +531,7 @@ void TestNumberDictionaryLookup() {
m.Return(m.BooleanConstant(false)); m.Return(m.BooleanConstant(false));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate); Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
@ -628,7 +634,8 @@ TEST(TryHasOwnProperty) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound, kBailout }; enum Result { kFound, kNotFound, kBailout };
{ {
@ -666,7 +673,7 @@ TEST(TryHasOwnProperty) {
m.Return(m.BooleanConstant(false)); m.Return(m.BooleanConstant(false));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Object> expect_found(Smi::FromInt(kFound), isolate); Handle<Object> expect_found(Smi::FromInt(kFound), isolate);
@ -814,7 +821,8 @@ TEST(TryGetOwnProperty) {
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
const int kNumParams = 2; 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> not_found_symbol = factory->NewSymbol();
Handle<Symbol> bailout_symbol = factory->NewSymbol(); Handle<Symbol> bailout_symbol = factory->NewSymbol();
@ -843,7 +851,7 @@ TEST(TryGetOwnProperty) {
m.Return(m.HeapConstant(bailout_symbol)); m.Return(m.HeapConstant(bailout_symbol));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Name> deleted_property_name = Handle<Name> deleted_property_name =
@ -1030,7 +1038,8 @@ TEST(TryLookupElement) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 3; const int kNumParams = 3;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
enum Result { kFound, kNotFound, kBailout }; enum Result { kFound, kNotFound, kBailout };
{ {
@ -1068,7 +1077,7 @@ TEST(TryLookupElement) {
m.Return(m.BooleanConstant(false)); m.Return(m.BooleanConstant(false));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
@ -1216,8 +1225,8 @@ TEST(DeferredCodePhiHints) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeStubAssemblerTester m(isolate, descriptor); CodeStubAssembler m(data.state());
Label block1(&m, Label::kDeferred); Label block1(&m, Label::kDeferred);
m.Goto(&block1); m.Goto(&block1);
m.Bind(&block1); m.Bind(&block1);
@ -1233,15 +1242,15 @@ TEST(DeferredCodePhiHints) {
m.Goto(&loop); m.Goto(&loop);
} }
} }
CHECK(!m.GenerateCode().is_null()); CHECK(!data.GenerateCode().is_null());
} }
TEST(TestOutOfScopeVariable) { TEST(TestOutOfScopeVariable) {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
VoidDescriptor descriptor(isolate); CodeAssemblerTester data(isolate);
CodeStubAssemblerTester m(isolate, descriptor); CodeStubAssembler m(data.state());
Label block1(&m); Label block1(&m);
Label block2(&m); Label block2(&m);
Label block3(&m); Label block3(&m);
@ -1262,7 +1271,7 @@ TEST(TestOutOfScopeVariable) {
m.Goto(&block1); m.Goto(&block1);
} }
m.Bind(&block1); m.Bind(&block1);
CHECK(!m.GenerateCode().is_null()); CHECK(!data.GenerateCode().is_null());
} }
namespace { namespace {
@ -1270,7 +1279,8 @@ namespace {
void TestStubCacheOffsetCalculation(StubCache::Table table) { void TestStubCacheOffsetCalculation(StubCache::Table table) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 2; const int kNumParams = 2;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
{ {
Node* name = m.Parameter(0); Node* name = m.Parameter(0);
@ -1286,7 +1296,7 @@ void TestStubCacheOffsetCalculation(StubCache::Table table) {
m.Return(m.SmiFromWord32(result)); m.Return(m.SmiFromWord32(result));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
@ -1354,9 +1364,10 @@ namespace {
Handle<Code> CreateCodeWithFlags(Code::Flags flags) { Handle<Code> CreateCodeWithFlags(Code::Flags flags) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, flags); CodeAssemblerTester data(isolate, flags);
CodeStubAssembler m(data.state());
m.Return(m.UndefinedConstant()); m.Return(m.UndefinedConstant());
return m.GenerateCodeCloseAndEscape(); return data.GenerateCodeCloseAndEscape();
} }
} // namespace } // namespace
@ -1366,7 +1377,8 @@ TEST(TryProbeStubCache) {
typedef CodeStubAssembler::Variable Variable; typedef CodeStubAssembler::Variable Variable;
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 3; const int kNumParams = 3;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
Code::Kind ic_kind = Code::LOAD_IC; Code::Kind ic_kind = Code::LOAD_IC;
StubCache stub_cache(isolate, ic_kind); StubCache stub_cache(isolate, ic_kind);
@ -1399,7 +1411,7 @@ TEST(TryProbeStubCache) {
m.Return(m.BooleanConstant(false)); m.Return(m.BooleanConstant(false));
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
std::vector<Handle<Name>> names; std::vector<Handle<Name>> names;
@ -1510,8 +1522,8 @@ TEST(GotoIfException) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1; const int kNumParams = 1;
// Emulate TFJ builtin CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN); CodeStubAssembler m(data.state());
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* to_string_tag = Node* to_string_tag =
@ -1527,13 +1539,13 @@ TEST(GotoIfException) {
m.Bind(&exception_handler); m.Bind(&exception_handler);
m.Return(exception.value()); m.Return(exception.value());
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Object> result = ft.Call().ToHandleChecked(); Handle<Object> result = ft.Call().ToHandleChecked();
// Should be a TypeError // Should be a TypeError.
CHECK(result->IsJSObject()); CHECK(result->IsJSObject());
Handle<Object> constructor = Handle<Object> constructor =
@ -1549,8 +1561,8 @@ TEST(GotoIfExceptionMultiple) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; // receiver, first, second, third const int kNumParams = 4; // receiver, first, second, third
// Emulate TFJ builtin CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN); CodeStubAssembler m(data.state());
Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Node* first_value = m.Parameter(0); Node* first_value = m.Parameter(0);
@ -1592,25 +1604,25 @@ TEST(GotoIfExceptionMultiple) {
m.Bind(&exception_handler3); m.Bind(&exception_handler3);
m.Return(error.value()); m.Return(error.value());
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Object> result; 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(), result = ft.Call(isolate->factory()->undefined_value(),
isolate->factory()->to_string_tag_symbol()) isolate->factory()->to_string_tag_symbol())
.ToHandleChecked(); .ToHandleChecked();
CHECK(String::cast(*result)->IsOneByteEqualTo(OneByteVector("undefined"))); 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(), result = ft.Call(isolate->factory()->to_string_tag_symbol(),
isolate->factory()->undefined_value()) isolate->factory()->undefined_value())
.ToHandleChecked(); .ToHandleChecked();
CHECK_EQ(7, Smi::cast(*result)->value()); 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(), result = ft.Call(isolate->factory()->to_string_tag_symbol(),
isolate->factory()->to_primitive_symbol()) isolate->factory()->to_primitive_symbol())
.ToHandleChecked(); .ToHandleChecked();
@ -1623,7 +1635,7 @@ TEST(GotoIfExceptionMultiple) {
isolate->factory()->unscopables_symbol()) isolate->factory()->unscopables_symbol())
.ToHandleChecked(); .ToHandleChecked();
// Should be a TypeError // Should be a TypeError.
CHECK(result->IsJSObject()); CHECK(result->IsJSObject());
Handle<Object> constructor = Handle<Object> constructor =
@ -1638,7 +1650,8 @@ TEST(AllocateJSObjectFromMap) {
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
const int kNumParams = 3; const int kNumParams = 3;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
{ {
Node* map = m.Parameter(0); Node* map = m.Parameter(0);
@ -1650,7 +1663,7 @@ TEST(AllocateJSObjectFromMap) {
m.Return(result); m.Return(result);
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
Handle<Map> maps[] = { Handle<Map> maps[] = {
@ -1701,7 +1714,8 @@ TEST(AllocateNameDictionary) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 1; const int kNumParams = 1;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
{ {
Node* capacity = m.Parameter(0); Node* capacity = m.Parameter(0);
@ -1709,7 +1723,7 @@ TEST(AllocateNameDictionary) {
m.Return(result); m.Return(result);
} }
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
{ {
@ -1729,16 +1743,17 @@ TEST(PopAndReturnConstant) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
const int kNumProgramaticParams = 2; const int kNumProgrammaticParams = 2;
CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams); CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams);
CodeStubAssembler m(data.state());
// Call a function that return |kNumProgramaticParams| parameters in addition // Call a function that return |kNumProgramaticParams| parameters in addition
// to those specified by the static descriptor. |kNumProgramaticParams| is // to those specified by the static descriptor. |kNumProgramaticParams| is
// specified as a constant. // specified as a constant.
m.PopAndReturn(m.Int32Constant(kNumProgramaticParams), m.PopAndReturn(m.Int32Constant(kNumProgrammaticParams),
m.SmiConstant(Smi::FromInt(1234))); m.SmiConstant(Smi::FromInt(1234)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
@ -1757,8 +1772,9 @@ TEST(PopAndReturnVariable) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
const int kNumProgramaticParams = 2; const int kNumProgrammaticParams = 2;
CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams); CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams);
CodeStubAssembler m(data.state());
// Call a function that return |kNumProgramaticParams| parameters in addition // Call a function that return |kNumProgramaticParams| parameters in addition
// to those specified by the static descriptor. |kNumProgramaticParams| is // to those specified by the static descriptor. |kNumProgramaticParams| is
@ -1766,7 +1782,7 @@ TEST(PopAndReturnVariable) {
// a constant. // a constant.
m.PopAndReturn(m.SmiUntag(m.Parameter(1)), m.SmiConstant(Smi::FromInt(1234))); 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()); CHECK(!code.is_null());
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
@ -1775,7 +1791,7 @@ TEST(PopAndReturnVariable) {
result = ft.Call(isolate->factory()->undefined_value(), result = ft.Call(isolate->factory()->undefined_value(),
Handle<Smi>(Smi::FromInt(1234), isolate), Handle<Smi>(Smi::FromInt(1234), isolate),
isolate->factory()->undefined_value(), isolate->factory()->undefined_value(),
Handle<Smi>(Smi::FromInt(kNumProgramaticParams), isolate)) Handle<Smi>(Smi::FromInt(kNumProgrammaticParams), isolate))
.ToHandleChecked(); .ToHandleChecked();
CHECK_EQ(1234, Handle<Smi>::cast(result)->value()); CHECK_EQ(1234, Handle<Smi>::cast(result)->value());
} }
@ -1784,7 +1800,9 @@ TEST(PopAndReturnVariable) {
TEST(OneToTwoByteStringCopy) { TEST(OneToTwoByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2); const int kNumParams = 2;
CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
m.CopyStringCharacters( m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@ -1793,7 +1811,7 @@ TEST(OneToTwoByteStringCopy) {
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0))); m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde"); Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
@ -1818,7 +1836,9 @@ TEST(OneToTwoByteStringCopy) {
TEST(OneToOneByteStringCopy) { TEST(OneToOneByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2); const int kNumParams = 2;
CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
m.CopyStringCharacters( m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@ -1827,7 +1847,7 @@ TEST(OneToOneByteStringCopy) {
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0))); m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde"); Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
@ -1852,7 +1872,9 @@ TEST(OneToOneByteStringCopy) {
TEST(OneToOneByteStringCopyNonZeroStart) { TEST(OneToOneByteStringCopyNonZeroStart) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2); const int kNumParams = 2;
CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
m.CopyStringCharacters( m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@ -1861,7 +1883,7 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0))); m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde"); Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde");
@ -1883,7 +1905,9 @@ TEST(OneToOneByteStringCopyNonZeroStart) {
TEST(TwoToTwoByteStringCopy) { TEST(TwoToTwoByteStringCopy) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
CodeStubAssemblerTester m(isolate, 2); const int kNumParams = 2;
CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
m.CopyStringCharacters( m.CopyStringCharacters(
m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)),
@ -1892,7 +1916,7 @@ TEST(TwoToTwoByteStringCopy) {
CodeStubAssembler::SMI_PARAMETERS); CodeStubAssembler::SMI_PARAMETERS);
m.Return(m.SmiConstant(Smi::FromInt(0))); m.Return(m.SmiConstant(Smi::FromInt(0)));
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
uc16 array1[] = {2000, 2001, 2002, 2003, 2004}; uc16 array1[] = {2000, 2001, 2002, 2003, 2004};
@ -1921,7 +1945,8 @@ TEST(Arguments) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
CodeStubArguments arguments(&m, m.IntPtrConstant(3)); CodeStubArguments arguments(&m, m.IntPtrConstant(3));
@ -1934,7 +1959,7 @@ TEST(Arguments) {
m.Return(arguments.GetReceiver()); m.Return(arguments.GetReceiver());
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);
@ -1950,13 +1975,13 @@ TEST(ArgumentsForEach) {
Isolate* isolate(CcTest::InitIsolateOnce()); Isolate* isolate(CcTest::InitIsolateOnce());
const int kNumParams = 4; const int kNumParams = 4;
CodeStubAssemblerTester m(isolate, kNumParams); CodeAssemblerTester data(isolate, kNumParams);
CodeStubAssembler m(data.state());
CodeStubArguments arguments(&m, m.IntPtrConstant(3)); CodeStubArguments arguments(&m, m.IntPtrConstant(3));
CodeStubAssemblerTester::Variable sum(&m, CodeStubAssembler::Variable sum(&m, MachineType::PointerRepresentation());
MachineType::PointerRepresentation()); CodeStubAssembler::VariableList list({&sum}, m.zone());
CodeStubAssemblerTester::VariableList list({&sum}, m.zone());
sum.Bind(m.IntPtrConstant(0)); sum.Bind(m.IntPtrConstant(0));
@ -1966,7 +1991,7 @@ TEST(ArgumentsForEach) {
m.Return(sum.value()); m.Return(sum.value());
Handle<Code> code = m.GenerateCode(); Handle<Code> code = data.GenerateCode();
CHECK(!code.is_null()); CHECK(!code.is_null());
FunctionTester ft(code, kNumParams); FunctionTester ft(code, kNumParams);

View File

@ -5,7 +5,6 @@
#include "test/unittests/interpreter/interpreter-assembler-unittest.h" #include "test/unittests/interpreter/interpreter-assembler-unittest.h"
#include "src/code-factory.h" #include "src/code-factory.h"
#include "src/compiler/graph.h"
#include "src/compiler/node.h" #include "src/compiler/node.h"
#include "src/interface-descriptors.h" #include "src/interface-descriptors.h"
#include "src/isolate.h" #include "src/isolate.h"
@ -21,6 +20,14 @@ using namespace compiler;
namespace interpreter { 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[] = { const interpreter::Bytecode kBytecodes[] = {
#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name, #define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
BYTECODE_LIST(DEFINE_BYTECODE) BYTECODE_LIST(DEFINE_BYTECODE)
@ -298,7 +305,8 @@ InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedOperand(
TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) { TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* tail_call_node = m.Dispatch(); Node* tail_call_node = m.Dispatch();
OperandScale operand_scale = OperandScale::kSingle; OperandScale operand_scale = OperandScale::kSingle;
@ -364,7 +372,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
if (!interpreter::Bytecodes::IsJump(bytecode)) return; 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)); Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd( Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
@ -398,7 +407,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple}; OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
TRACED_FOREACH(interpreter::OperandScale, operand_scale, kOperandScales) { 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 = int number_of_operands =
interpreter::Bytecodes::NumberOfOperands(bytecode); interpreter::Bytecodes::NumberOfOperands(bytecode);
for (int i = 0; i < number_of_operands; i++) { for (int i = 0; i < number_of_operands; i++) {
@ -463,7 +473,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
continue; continue;
} }
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
// Should be incoming accumulator if not set. // Should be incoming accumulator if not set.
EXPECT_THAT(m.GetAccumulator(), EXPECT_THAT(m.GetAccumulator(),
IsParameter(InterpreterDispatchDescriptor::kAccumulator)); IsParameter(InterpreterDispatchDescriptor::kAccumulator));
@ -485,7 +496,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
TARGET_TEST_F(InterpreterAssemblerTest, GetContext) { TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
EXPECT_THAT( EXPECT_THAT(
m.GetContext(), m.GetContext(),
m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(), m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
@ -496,7 +508,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) { TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { 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_index_node = m.IntPtrConstant(44);
Node* reg_location_node = m.RegisterLocation(reg_index_node); Node* reg_location_node = m.RegisterLocation(reg_index_node);
EXPECT_THAT(reg_location_node, EXPECT_THAT(reg_location_node,
@ -508,7 +521,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) { TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { 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_index_node = m.IntPtrConstant(44);
Node* load_reg_node = m.LoadRegister(reg_index_node); Node* load_reg_node = m.LoadRegister(reg_index_node);
EXPECT_THAT(load_reg_node, EXPECT_THAT(load_reg_node,
@ -520,7 +534,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) { TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { 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* store_value = m.Int32Constant(0xdeadbeef);
Node* reg_index_node = m.IntPtrConstant(44); Node* reg_index_node = m.IntPtrConstant(44);
Node* store_reg_node = m.StoreRegister(store_value, reg_index_node); 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) { TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* value = m.Int32Constant(44); Node* value = m.Int32Constant(44);
EXPECT_THAT(m.SmiTag(value), IsBitcastWordToTaggedSigned(IsIntPtrConstant( EXPECT_THAT(m.SmiTag(value), IsBitcastWordToTaggedSigned(IsIntPtrConstant(
static_cast<intptr_t>(44) static_cast<intptr_t>(44)
@ -549,7 +565,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) { TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* a = m.Int32Constant(0); Node* a = m.Int32Constant(0);
Node* b = m.Int32Constant(1); Node* b = m.Int32Constant(1);
Node* add = m.IntPtrAdd(a, b); Node* add = m.IntPtrAdd(a, b);
@ -559,7 +576,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) { TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* a = m.Int32Constant(0); Node* a = m.Int32Constant(0);
Node* b = m.Int32Constant(1); Node* b = m.Int32Constant(1);
Node* add = m.IntPtrSub(a, b); Node* add = m.IntPtrSub(a, b);
@ -569,7 +587,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
TARGET_TEST_F(InterpreterAssemblerTest, WordShl) { TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* a = m.IntPtrConstant(0); Node* a = m.IntPtrConstant(0);
Node* add = m.WordShl(a, 10); Node* add = m.WordShl(a, 10);
EXPECT_THAT(add, IsWordShl(a, IsIntPtrConstant(10))); EXPECT_THAT(add, IsWordShl(a, IsIntPtrConstant(10)));
@ -578,7 +597,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) { TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* index = m.IntPtrConstant(2); Node* index = m.IntPtrConstant(2);
Node* load_constant = m.LoadConstantPoolEntry(index); Node* load_constant = m.LoadConstantPoolEntry(index);
Matcher<Node*> constant_pool_matcher = m.IsLoad( Matcher<Node*> constant_pool_matcher = m.IsLoad(
@ -596,7 +616,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) { TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* object = m.IntPtrConstant(0xdeadbeef); Node* object = m.IntPtrConstant(0xdeadbeef);
int offset = 16; int offset = 16;
Node* load_field = m.LoadObjectField(object, offset); Node* load_field = m.LoadObjectField(object, offset);
@ -608,7 +629,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) { TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* arg1 = m.Int32Constant(2); Node* arg1 = m.Int32Constant(2);
Node* arg2 = m.Int32Constant(3); Node* arg2 = m.Int32Constant(3);
Node* context = m.Int32Constant(4); Node* context = m.Int32Constant(4);
@ -622,7 +644,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
const int kResultSizes[] = {1, 2}; const int kResultSizes[] = {1, 2};
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
TRACED_FOREACH(int, result_size, kResultSizes) { 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); Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
Node* function_id = m.Int32Constant(0); Node* function_id = m.Int32Constant(0);
@ -653,7 +676,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
TailCallMode::kAllow}; TailCallMode::kAllow};
TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) { TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Callable builtin = Callable builtin =
CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode); CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
Node* function = m.Int32Constant(0); Node* function = m.Int32Constant(0);
@ -670,7 +694,8 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) { TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerTestState state(this, bytecode);
InterpreterAssemblerForTest m(&state, bytecode);
Node* feedback_vector = m.LoadTypeFeedbackVector(); Node* feedback_vector = m.LoadTypeFeedbackVector();
Matcher<Node*> load_function_matcher = Matcher<Node*> load_function_matcher =

View File

@ -5,6 +5,7 @@
#ifndef V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_ #ifndef V8_UNITTESTS_INTERPRETER_INTERPRETER_ASSEMBLER_UNITTEST_H_
#define 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/compiler/machine-operator.h"
#include "src/interpreter/interpreter-assembler.h" #include "src/interpreter/interpreter-assembler.h"
#include "test/unittests/test-utils.h" #include "test/unittests/test-utils.h"
@ -16,6 +17,14 @@ namespace interpreter {
using ::testing::Matcher; using ::testing::Matcher;
class InterpreterAssemblerTest;
class InterpreterAssemblerTestState : public compiler::CodeAssemblerState {
public:
InterpreterAssemblerTestState(InterpreterAssemblerTest* test,
Bytecode bytecode);
};
class InterpreterAssemblerTest : public TestWithIsolateAndZone { class InterpreterAssemblerTest : public TestWithIsolateAndZone {
public: public:
InterpreterAssemblerTest() {} InterpreterAssemblerTest() {}
@ -24,10 +33,9 @@ class InterpreterAssemblerTest : public TestWithIsolateAndZone {
class InterpreterAssemblerForTest final : public InterpreterAssembler { class InterpreterAssemblerForTest final : public InterpreterAssembler {
public: public:
InterpreterAssemblerForTest( InterpreterAssemblerForTest(
InterpreterAssemblerTest* test, Bytecode bytecode, InterpreterAssemblerTestState* state, Bytecode bytecode,
OperandScale operand_scale = OperandScale::kSingle) OperandScale operand_scale = OperandScale::kSingle)
: InterpreterAssembler(test->isolate(), test->zone(), bytecode, : InterpreterAssembler(state, bytecode, operand_scale) {}
operand_scale) {}
~InterpreterAssemblerForTest() override; ~InterpreterAssemblerForTest() override;
Matcher<compiler::Node*> IsLoad( Matcher<compiler::Node*> IsLoad(