[turbofan] Properly optimize literals in inlined functions.

When inlining based on SharedFunctionInfo rather than based on concrete
JSFunction, we weren't able to properly optimize array, object and
regexp literals inside the inlinee, because we didn't know the concrete
FeedbackVector for the inlinee inside JSCreateLowering. This was because
JSCreateLowering wasn't properly updated after the literals moved to the
FeedbackVector. Now with this CL we also have the VectorSlotPair on the
literal creation operators, just like we do for property accesses and
calls, and are thus able to always access the appropriate FeedbackVector
and optimize the literal creation.

The impact is illustrated by the micro-benchmark on the tracking bug,
which goes from

  createEmptyArrayLiteral: 1846 ms.
  createShallowArrayLiteral: 1868 ms.
  createShallowObjectLiteral: 2246 ms.

to

  createEmptyArrayLiteral: 1175 ms.
  createShallowArrayLiteral: 1187 ms.
  createShallowObjectLiteral: 1195 ms.

with this CL, so up to 2x faster now.

Drive-by-fix: Also remove the unused CreateEmptyObjectLiteral builtin
and cleanup the names of the other builtins to be consistent with the
names of the TurboFan operators and Ignition bytecodes.

Bug: v8:6856
Change-Id: I453828d019b27c9aa1344edac0dd84e91a457097
Reviewed-on: https://chromium-review.googlesource.com/680656
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48140}
This commit is contained in:
Benedikt Meurer 2017-09-25 14:30:25 +02:00 committed by Commit Bot
parent 63f9ee1645
commit 855b88ae5a
30 changed files with 227 additions and 535 deletions

View File

@ -90,27 +90,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3, r2, r1, r0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3, r2, r1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3, r2, r1, r0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r1};

View File

@ -92,38 +92,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x3: closure
// x2: object literal index
// x1: constant properties
// x0: object literal flags
Register registers[] = {x3, x2, x1, x0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x3: closure
// x2: array literal index
// x1: constant elements
Register registers[] = {x3, x2, x1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x3: closure
// x2: object literal index
// x1: constant properties
// x0: object literal flags
Register registers[] = {x3, x2, x1, x0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
// x1 function the function to call

View File

@ -634,7 +634,7 @@ void ObjectLiteral::BuildConstantProperties(Isolate* isolate) {
}
bool ObjectLiteral::IsFastCloningSupported() const {
// The FastCloneShallowObject builtin doesn't copy elements, and object
// The CreateShallowObjectLiteratal builtin doesn't copy elements, and object
// literals don't support copy-on-write (COW) elements for now.
// TODO(mvstanton): make object literals support COW elements.
return fast_elements() && is_shallow() &&

View File

@ -1321,7 +1321,7 @@ class ObjectLiteral final : public AggregateLiteral {
// marked expressions, no store code is emitted.
void CalculateEmitStore(Zone* zone);
// Determines whether the {FastCloneShallowObject} builtin can be used.
// Determines whether the {CreateShallowObjectLiteratal} builtin can be used.
bool IsFastCloningSupported() const;
// Assemble bitfield of flags for the CreateObjectLiteral helper.
@ -1449,7 +1449,7 @@ class ArrayLiteral final : public AggregateLiteral {
// Populate the constant elements fixed array.
void BuildConstantElements(Isolate* isolate);
// Determines whether the {FastCloneShallowArray} builtin can be used.
// Determines whether the {CreateShallowArrayLiteral} builtin can be used.
bool IsFastCloningSupported() const;
// Assemble bitfield of flags for the CreateArrayLiteral helper.

View File

@ -334,17 +334,14 @@ TF_BUILTIN(FastNewFunctionContextFunction, ConstructorBuiltinsAssembler) {
ScopeType::FUNCTION_SCOPE));
}
Node* ConstructorBuiltinsAssembler::EmitFastCloneRegExp(Node* closure,
Node* literal_index,
Node* pattern,
Node* flags,
Node* context) {
Node* ConstructorBuiltinsAssembler::EmitCreateRegExpLiteral(
Node* feedback_vector, Node* slot, Node* pattern, Node* flags,
Node* context) {
Label call_runtime(this, Label::kDeferred), end(this);
VARIABLE(result, MachineRepresentation::kTagged);
Node* feedback_vector = LoadFeedbackVector(closure);
Node* literal_site =
LoadFeedbackVectorSlot(feedback_vector, literal_index, 0, SMI_PARAMETERS);
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS);
GotoIf(NotHasBoilerplate(literal_site), &call_runtime);
{
Node* boilerplate = literal_site;
@ -361,8 +358,8 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneRegExp(Node* closure,
BIND(&call_runtime);
{
result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context, closure,
literal_index, pattern, flags));
result.Bind(CallRuntime(Runtime::kCreateRegExpLiteral, context,
feedback_vector, SmiTag(slot), pattern, flags));
Goto(&end);
}
@ -370,14 +367,15 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneRegExp(Node* closure,
return result.value();
}
TF_BUILTIN(FastCloneRegExp, ConstructorBuiltinsAssembler) {
Node* closure = Parameter(FastCloneRegExpDescriptor::kClosure);
Node* literal_index = Parameter(FastCloneRegExpDescriptor::kLiteralIndex);
Node* pattern = Parameter(FastCloneRegExpDescriptor::kPattern);
Node* flags = Parameter(FastCloneRegExpDescriptor::kFlags);
Node* context = Parameter(FastCloneRegExpDescriptor::kContext);
Return(EmitFastCloneRegExp(closure, literal_index, pattern, flags, context));
TF_BUILTIN(CreateRegExpLiteral, ConstructorBuiltinsAssembler) {
Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
Node* pattern = Parameter(Descriptor::kPattern);
Node* flags = Parameter(Descriptor::kFlags);
Node* context = Parameter(Descriptor::kContext);
Node* result =
EmitCreateRegExpLiteral(feedback_vector, slot, pattern, flags, context);
Return(result);
}
Node* ConstructorBuiltinsAssembler::NonEmptyShallowClone(
@ -402,16 +400,15 @@ Node* ConstructorBuiltinsAssembler::NonEmptyShallowClone(
return array;
}
Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowArray(
Node* closure, Node* literal_index, Node* context, Label* call_runtime,
Node* ConstructorBuiltinsAssembler::EmitCreateShallowArrayLiteral(
Node* feedback_vector, Node* slot, Node* context, Label* call_runtime,
AllocationSiteMode allocation_site_mode) {
Label zero_capacity(this), cow_elements(this), fast_elements(this),
return_result(this);
VARIABLE(result, MachineRepresentation::kTagged);
Node* feedback_vector = LoadFeedbackVector(closure);
Node* allocation_site =
LoadFeedbackVectorSlot(feedback_vector, literal_index, 0, SMI_PARAMETERS);
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS);
GotoIf(NotHasBoilerplate(allocation_site), call_runtime);
Node* boilerplate = LoadAllocationSiteBoilerplate(allocation_site);
@ -484,49 +481,32 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowArray(
return result.value();
}
void ConstructorBuiltinsAssembler::CreateFastCloneShallowArrayBuiltin(
AllocationSiteMode allocation_site_mode) {
Node* closure = Parameter(FastCloneShallowArrayDescriptor::kClosure);
Node* literal_index =
Parameter(FastCloneShallowArrayDescriptor::kLiteralIndex);
Node* constant_elements =
Parameter(FastCloneShallowArrayDescriptor::kConstantElements);
Node* context = Parameter(FastCloneShallowArrayDescriptor::kContext);
TF_BUILTIN(CreateShallowArrayLiteral, ConstructorBuiltinsAssembler) {
Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
Node* constant_elements = Parameter(Descriptor::kConstantElements);
Node* context = Parameter(Descriptor::kContext);
Label call_runtime(this, Label::kDeferred);
Return(EmitFastCloneShallowArray(closure, literal_index, context,
&call_runtime, allocation_site_mode));
Return(EmitCreateShallowArrayLiteral(feedback_vector, slot, context,
&call_runtime,
DONT_TRACK_ALLOCATION_SITE));
BIND(&call_runtime);
{
Comment("call runtime");
int flags = AggregateLiteral::kIsShallow;
if (allocation_site_mode == TRACK_ALLOCATION_SITE) {
// Force initial allocation sites on the initial literal setup step.
flags |= AggregateLiteral::kNeedsInitialAllocationSite;
} else {
flags |= AggregateLiteral::kDisableMementos;
}
Return(CallRuntime(Runtime::kCreateArrayLiteral, context, closure,
literal_index, constant_elements, SmiConstant(flags)));
int const flags =
AggregateLiteral::kDisableMementos | AggregateLiteral::kIsShallow;
Return(CallRuntime(Runtime::kCreateArrayLiteral, context, feedback_vector,
SmiTag(slot), constant_elements, SmiConstant(flags)));
}
}
TF_BUILTIN(FastCloneShallowArrayTrack, ConstructorBuiltinsAssembler) {
CreateFastCloneShallowArrayBuiltin(TRACK_ALLOCATION_SITE);
}
TF_BUILTIN(FastCloneShallowArrayDontTrack, ConstructorBuiltinsAssembler) {
CreateFastCloneShallowArrayBuiltin(DONT_TRACK_ALLOCATION_SITE);
}
Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
Node* closure, Node* literal_index, Node* context) {
Node* feedback_vector, Node* slot, Node* context) {
// Array literals always have a valid AllocationSite to properly track
// elements transitions.
Node* feedback_vector = LoadFeedbackVector(closure);
VARIABLE(allocation_site, MachineRepresentation::kTagged,
LoadFeedbackVectorSlot(feedback_vector, literal_index, 0,
SMI_PARAMETERS));
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS));
Label create_empty_array(this),
initialize_allocation_site(this, Label::kDeferred), done(this);
@ -537,7 +517,7 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
BIND(&initialize_allocation_site);
{
allocation_site.Bind(
CreateAllocationSiteInFeedbackVector(feedback_vector, literal_index));
CreateAllocationSiteInFeedbackVector(feedback_vector, SmiTag(slot)));
Goto(&create_empty_array);
}
@ -563,18 +543,17 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
}
TF_BUILTIN(CreateEmptyArrayLiteral, ConstructorBuiltinsAssembler) {
Node* closure = Parameter(Descriptor::kClosure);
Node* literal_index = Parameter(Descriptor::kLiteralIndex);
Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
Node* context = Parameter(Descriptor::kContext);
Node* result = EmitCreateEmptyArrayLiteral(closure, literal_index, context);
Node* result = EmitCreateEmptyArrayLiteral(feedback_vector, slot, context);
Return(result);
}
Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
Label* call_runtime, Node* closure, Node* literals_index) {
Node* feedback_vector = LoadFeedbackVector(closure);
Node* allocation_site = LoadFeedbackVectorSlot(
feedback_vector, literals_index, 0, SMI_PARAMETERS);
Node* ConstructorBuiltinsAssembler::EmitCreateShallowObjectLiteral(
Node* feedback_vector, Node* slot, Label* call_runtime) {
Node* allocation_site =
LoadFeedbackVectorSlot(feedback_vector, slot, 0, INTPTR_PARAMETERS);
GotoIf(NotHasBoilerplate(allocation_site), call_runtime);
Node* boilerplate = LoadAllocationSiteBoilerplate(allocation_site);
@ -730,12 +709,12 @@ Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
return copy;
}
TF_BUILTIN(FastCloneShallowObject, ConstructorBuiltinsAssembler) {
TF_BUILTIN(CreateShallowObjectLiteral, ConstructorBuiltinsAssembler) {
Label call_runtime(this);
Node* closure = Parameter(Descriptor::kClosure);
Node* literals_index = Parameter(Descriptor::kLiteralIndex);
Node* feedback_vector = Parameter(Descriptor::kFeedbackVector);
Node* slot = SmiUntag(Parameter(Descriptor::kSlot));
Node* copy =
EmitFastCloneShallowObject(&call_runtime, closure, literals_index);
EmitCreateShallowObjectLiteral(feedback_vector, slot, &call_runtime);
Return(copy);
BIND(&call_runtime);
@ -743,11 +722,11 @@ TF_BUILTIN(FastCloneShallowObject, ConstructorBuiltinsAssembler) {
Parameter(Descriptor::kBoilerplateDescription);
Node* flags = Parameter(Descriptor::kFlags);
Node* context = Parameter(Descriptor::kContext);
TailCallRuntime(Runtime::kCreateObjectLiteral, context, closure,
literals_index, boilerplate_description, flags);
TailCallRuntime(Runtime::kCreateObjectLiteral, context, feedback_vector,
SmiTag(slot), boilerplate_description, flags);
}
// Used by the CreateEmptyObjectLiteral stub and bytecode.
// Used by the CreateEmptyObjectLiteral bytecode and the Object constructor.
Node* ConstructorBuiltinsAssembler::EmitCreateEmptyObjectLiteral(
Node* context) {
Node* native_context = LoadNativeContext(context);
@ -766,12 +745,6 @@ Node* ConstructorBuiltinsAssembler::EmitCreateEmptyObjectLiteral(
return result;
}
TF_BUILTIN(CreateEmptyObjectLiteral, ConstructorBuiltinsAssembler) {
Node* context = Parameter(Descriptor::kContext);
Node* result = EmitCreateEmptyObjectLiteral(context);
Return(result);
}
TF_BUILTIN(ObjectConstructor, ConstructorBuiltinsAssembler) {
int const kValueArg = 0;
Node* argc =

View File

@ -20,19 +20,17 @@ class ConstructorBuiltinsAssembler : public CodeStubAssembler {
Node* EmitFastNewFunctionContext(Node* closure, Node* slots, Node* context,
ScopeType scope_type);
Node* EmitFastCloneRegExp(Node* closure, Node* literal_index, Node* pattern,
Node* flags, Node* context);
Node* EmitFastCloneShallowArray(Node* closure, Node* literal_index,
Node* context, Label* call_runtime,
AllocationSiteMode allocation_site_mode);
Node* EmitCreateRegExpLiteral(Node* feedback_vector, Node* slot,
Node* pattern, Node* flags, Node* context);
Node* EmitCreateShallowArrayLiteral(Node* feedback_vector, Node* slot,
Node* context, Label* call_runtime,
AllocationSiteMode allocation_site_mode);
Node* EmitCreateEmptyArrayLiteral(Node* closure, Node* iteral_index,
Node* EmitCreateEmptyArrayLiteral(Node* feedback_vector, Node* slot,
Node* context);
void CreateFastCloneShallowArrayBuiltin(
AllocationSiteMode allocation_site_mode);
Node* EmitFastCloneShallowObject(Label* call_runtime, Node* closure,
Node* literals_index);
Node* EmitCreateShallowObjectLiteral(Node* feedback_vector, Node* slot,
Label* call_runtime);
Node* EmitCreateEmptyObjectLiteral(Node* context);
Node* EmitFastNewObject(Node* context, Node* target, Node* new_target);

View File

@ -73,12 +73,11 @@ namespace internal {
TFC(FastNewClosure, FastNewClosure, 1) \
TFC(FastNewFunctionContextEval, FastNewFunctionContext, 1) \
TFC(FastNewFunctionContextFunction, FastNewFunctionContext, 1) \
TFC(FastCloneRegExp, FastCloneRegExp, 1) \
TFC(FastCloneShallowArrayTrack, FastCloneShallowArray, 1) \
TFC(FastCloneShallowArrayDontTrack, FastCloneShallowArray, 1) \
TFS(CreateEmptyArrayLiteral, kClosure, kLiteralIndex) \
TFS(CreateEmptyObjectLiteral, kClosure) \
TFC(FastCloneShallowObject, FastCloneShallowObject, 1) \
TFS(CreateRegExpLiteral, kFeedbackVector, kSlot, kPattern, kFlags) \
TFS(CreateEmptyArrayLiteral, kFeedbackVector, kSlot) \
TFS(CreateShallowArrayLiteral, kFeedbackVector, kSlot, kConstantElements) \
TFS(CreateShallowObjectLiteral, kFeedbackVector, kSlot, \
kBoilerplateDescription, kFlags) \
/* ES6 section 9.5.14 [[Construct]] ( argumentsList, newTarget) */ \
TFC(ConstructProxy, ConstructTrampoline, 1) \
\

View File

@ -113,19 +113,6 @@ Handle<Code> Builtins::NewFunctionContext(ScopeType scope_type) {
return Handle<Code>::null();
}
Handle<Code> Builtins::NewCloneShallowArray(
AllocationSiteMode allocation_mode) {
switch (allocation_mode) {
case TRACK_ALLOCATION_SITE:
return builtin_handle(kFastCloneShallowArrayTrack);
case DONT_TRACK_ALLOCATION_SITE:
return builtin_handle(kFastCloneShallowArrayDontTrack);
default:
UNREACHABLE();
}
return Handle<Code>::null();
}
Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) {
switch (hint) {
case ToPrimitiveHint::kDefault:

View File

@ -68,7 +68,6 @@ class Builtins {
InterpreterPushArgsMode mode);
Handle<Code> InterpreterPushArgsThenConstruct(InterpreterPushArgsMode mode);
Handle<Code> NewFunctionContext(ScopeType scope_type);
Handle<Code> NewCloneShallowArray(AllocationSiteMode allocation_mode);
Handle<Code> JSConstructStubGeneric();
// Used by BuiltinDeserializer.

View File

@ -202,13 +202,6 @@ Callable CodeFactory::HandleDebuggerStatement(Isolate* isolate) {
ContextOnlyDescriptor(isolate));
}
// static
Callable CodeFactory::FastCloneShallowArray(
Isolate* isolate, AllocationSiteMode allocation_mode) {
return Callable(isolate->builtins()->NewCloneShallowArray(allocation_mode),
FastCloneShallowArrayDescriptor(isolate));
}
// static
Callable CodeFactory::FastNewFunctionContext(Isolate* isolate,
ScopeType scope_type) {

View File

@ -60,9 +60,6 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable StringCompare(Isolate* isolate, Token::Value token);
static Callable SubString(Isolate* isolate);
static Callable FastCloneShallowArray(Isolate* isolate,
AllocationSiteMode allocation_mode);
static Callable FastNewFunctionContext(Isolate* isolate,
ScopeType scope_type);

View File

@ -1480,11 +1480,11 @@ void BytecodeGraphBuilder::VisitCreateRestParameter() {
void BytecodeGraphBuilder::VisitCreateRegExpLiteral() {
Handle<String> constant_pattern =
Handle<String>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
int literal_index = bytecode_iterator().GetIndexOperand(1);
int const slot_id = bytecode_iterator().GetIndexOperand(1);
VectorSlotPair pair = CreateVectorSlotPair(slot_id);
int literal_flags = bytecode_iterator().GetFlagOperand(2);
Node* literal = NewNode(javascript()->CreateLiteralRegExp(
constant_pattern, literal_flags, literal_index),
GetFunctionClosure());
Node* literal = NewNode(
javascript()->CreateLiteralRegExp(constant_pattern, pair, literal_flags));
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
}
@ -1492,7 +1492,8 @@ void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
Handle<ConstantElementsPair> constant_elements =
Handle<ConstantElementsPair>::cast(
bytecode_iterator().GetConstantForIndexOperand(0));
int literal_index = bytecode_iterator().GetIndexOperand(1);
int const slot_id = bytecode_iterator().GetIndexOperand(1);
VectorSlotPair pair = CreateVectorSlotPair(slot_id);
int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
int literal_flags =
interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags);
@ -1504,17 +1505,15 @@ void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
// TODO(mstarzinger): Thread through number of elements. The below number is
// only an estimate and does not match {ArrayLiteral::values::length}.
int number_of_elements = constant_elements->constant_values()->length();
Node* literal = NewNode(
javascript()->CreateLiteralArray(constant_elements, literal_flags,
literal_index, number_of_elements),
GetFunctionClosure());
Node* literal = NewNode(javascript()->CreateLiteralArray(
constant_elements, pair, literal_flags, number_of_elements));
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() {
int literal_index = bytecode_iterator().GetIndexOperand(0);
Node* literal = NewNode(javascript()->CreateEmptyLiteralArray(literal_index),
GetFunctionClosure());
int const slot_id = bytecode_iterator().GetIndexOperand(0);
VectorSlotPair pair = CreateVectorSlotPair(slot_id);
Node* literal = NewNode(javascript()->CreateEmptyLiteralArray(pair));
environment()->BindAccumulator(literal);
}
@ -1522,17 +1521,16 @@ void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
Handle<BoilerplateDescription> constant_properties =
Handle<BoilerplateDescription>::cast(
bytecode_iterator().GetConstantForIndexOperand(0));
int literal_index = bytecode_iterator().GetIndexOperand(1);
int const slot_id = bytecode_iterator().GetIndexOperand(1);
VectorSlotPair pair = CreateVectorSlotPair(slot_id);
int bytecode_flags = bytecode_iterator().GetFlagOperand(2);
int literal_flags =
interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags);
// TODO(mstarzinger): Thread through number of properties. The below number is
// only an estimate and does not match {ObjectLiteral::properties_count}.
int number_of_properties = constant_properties->size();
Node* literal = NewNode(
javascript()->CreateLiteralObject(constant_properties, literal_flags,
literal_index, number_of_properties),
GetFunctionClosure());
Node* literal = NewNode(javascript()->CreateLiteralObject(
constant_properties, pair, literal_flags, number_of_properties));
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3),
literal, Environment::kAttachFrameState);
}

View File

@ -854,41 +854,35 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralArrayOrObject(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Handle<FeedbackVector> feedback_vector;
if (GetSpecializationFeedbackVector(node).ToHandle(&feedback_vector)) {
FeedbackSlot slot(FeedbackVector::ToSlot(p.index()));
Handle<Object> literal(feedback_vector->Get(slot), isolate());
if (literal->IsAllocationSite()) {
Handle<AllocationSite> site = Handle<AllocationSite>::cast(literal);
Handle<JSObject> boilerplate(site->boilerplate(), isolate());
int max_properties = kMaxFastLiteralProperties;
if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
AllocationSiteUsageContext site_context(isolate(), site, false);
site_context.EnterNewScope();
Node* value = effect =
AllocateFastLiteral(effect, control, boilerplate, &site_context);
site_context.ExitScope(site, boilerplate);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
Handle<Object> feedback(p.feedback().vector()->Get(p.feedback().slot()),
isolate());
if (feedback->IsAllocationSite()) {
Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
Handle<JSObject> boilerplate(site->boilerplate(), isolate());
int max_properties = kMaxFastLiteralProperties;
if (IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
AllocationSiteUsageContext site_context(isolate(), site, false);
site_context.EnterNewScope();
Node* value = effect =
AllocateFastLiteral(effect, control, boilerplate, &site_context);
site_context.ExitScope(site, boilerplate);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
}
return NoChange();
}
Reduction JSCreateLowering::ReduceJSCreateEmptyLiteralArray(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kJSCreateEmptyLiteralArray);
int literal_index = OpParameter<int>(node);
Handle<FeedbackVector> feedback_vector;
if (GetSpecializationFeedbackVector(node).ToHandle(&feedback_vector)) {
FeedbackSlot slot(FeedbackVector::ToSlot(literal_index));
Handle<Object> raw_site(feedback_vector->Get(slot), isolate());
if (raw_site->IsAllocationSite()) {
Handle<AllocationSite> site = Handle<AllocationSite>::cast(raw_site);
DCHECK(!site->PointsToLiteral());
Node* length = jsgraph()->ZeroConstant();
return ReduceNewArray(node, length, 0, site);
}
DCHECK_EQ(IrOpcode::kJSCreateEmptyLiteralArray, node->opcode());
FeedbackParameter const& p = FeedbackParameterOf(node->op());
Handle<Object> feedback(p.feedback().vector()->Get(p.feedback().slot()),
isolate());
if (feedback->IsAllocationSite()) {
Handle<AllocationSite> site = Handle<AllocationSite>::cast(feedback);
DCHECK(!site->PointsToLiteral());
Node* length = jsgraph()->ZeroConstant();
return ReduceNewArray(node, length, 0, site);
}
return NoChange();
}
@ -930,16 +924,13 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Handle<FeedbackVector> feedback_vector;
if (GetSpecializationFeedbackVector(node).ToHandle(&feedback_vector)) {
FeedbackSlot slot(FeedbackVector::ToSlot(p.index()));
Handle<Object> maybe_boilerplate(feedback_vector->Get(slot), isolate());
if (maybe_boilerplate->IsJSRegExp()) {
Node* value = effect = AllocateLiteralRegExp(
effect, control, Handle<JSRegExp>::cast(maybe_boilerplate));
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
Handle<Object> feedback(p.feedback().vector()->Get(p.feedback().slot()),
isolate());
if (feedback->IsJSRegExp()) {
Handle<JSRegExp> boilerplate = Handle<JSRegExp>::cast(feedback);
Node* value = effect = AllocateLiteralRegExp(effect, control, boilerplate);
ReplaceWithValue(node, value, effect, control);
return Replace(value);
}
return NoChange();
}
@ -1505,30 +1496,6 @@ Node* JSCreateLowering::AllocateLiteralRegExp(Node* effect, Node* control,
return builder.Finish();
}
MaybeHandle<FeedbackVector> JSCreateLowering::GetSpecializationFeedbackVector(
Node* node) {
Node* const closure = NodeProperties::GetValueInput(node, 0);
switch (closure->opcode()) {
case IrOpcode::kHeapConstant: {
Handle<HeapObject> object = OpParameter<Handle<HeapObject>>(closure);
return handle(Handle<JSFunction>::cast(object)->feedback_vector());
}
case IrOpcode::kParameter: {
int const index = ParameterIndexOf(closure->op());
// The closure is always the last parameter to a JavaScript function, and
// {Parameter} indices start at -1, so value outputs of {Start} look like
// this: closure, receiver, param0, ..., paramN, context.
if (index == -1) {
return feedback_vector_;
}
break;
}
default:
break;
}
return MaybeHandle<FeedbackVector>();
}
Factory* JSCreateLowering::factory() const { return isolate()->factory(); }
Graph* JSCreateLowering::graph() const { return jsgraph()->graph(); }

View File

@ -34,12 +34,10 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
public:
JSCreateLowering(Editor* editor, CompilationDependencies* dependencies,
JSGraph* jsgraph,
MaybeHandle<FeedbackVector> feedback_vector,
Handle<Context> native_context, Zone* zone)
: AdvancedReducer(editor),
dependencies_(dependencies),
jsgraph_(jsgraph),
feedback_vector_(feedback_vector),
native_context_(native_context),
zone_(zone) {}
~JSCreateLowering() final {}
@ -99,9 +97,6 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
Reduction ReduceNewArrayToStubCall(Node* node, Handle<AllocationSite> site);
// Infers the FeedbackVector to use for a given {node}.
MaybeHandle<FeedbackVector> GetSpecializationFeedbackVector(Node* node);
Factory* factory() const;
Graph* graph() const;
JSGraph* jsgraph() const { return jsgraph_; }
@ -114,7 +109,6 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
CompilationDependencies* const dependencies_;
JSGraph* const jsgraph_;
MaybeHandle<FeedbackVector> const feedback_vector_;
Handle<Context> const native_context_;
Zone* const zone_;
};

View File

@ -461,15 +461,16 @@ void JSGenericLowering::LowerJSCreateKeyValueArray(Node* node) {
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
// Use the FastCloneShallowArray builtin only for shallow boilerplates without
// properties up to the number of elements that the stubs can handle.
// Use the CreateShallowArrayLiteratlr builtin only for shallow boilerplates
// without properties up to the number of elements that the stubs can handle.
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
Callable callable = CodeFactory::FastCloneShallowArray(
isolate(), DONT_TRACK_ALLOCATION_SITE);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kCreateShallowArrayLiteral);
ReplaceWithStubCall(node, callable, flags);
} else {
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
@ -479,8 +480,10 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
int literal_index = OpParameter<int>(node->op());
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(literal_index));
FeedbackParameter const& p = FeedbackParameterOf(node->op());
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
node->RemoveInput(4); // control
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kCreateEmptyArrayLiteral);
ReplaceWithStubCall(node, callable, flags);
@ -489,17 +492,18 @@ void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
// Use the FastCloneShallowObject builtin only for shallow boilerplates
// Use the CreateShallowObjectLiteratal builtin only for shallow boilerplates
// without elements up to the number of properties that the stubs can handle.
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
p.length() <=
ConstructorBuiltins::kMaximumClonedShallowObjectProperties) {
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kFastCloneShallowObject);
Builtins::CallableFor(isolate(), Builtins::kCreateShallowObjectLiteral);
ReplaceWithStubCall(node, callable, flags);
} else {
ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
@ -507,23 +511,18 @@ void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
}
void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kCreateEmptyObjectLiteral);
ReplaceWithStubCall(node, callable, flags);
UNREACHABLE(); // Eliminated in typed lowering.
}
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
Callable callable =
Builtins::CallableFor(isolate(), Builtins::kFastCloneRegExp);
Node* literal_index = jsgraph()->SmiConstant(p.index());
Node* literal_flags = jsgraph()->SmiConstant(p.flags());
Node* pattern = jsgraph()->HeapConstant(p.constant());
node->InsertInput(graph()->zone(), 1, literal_index);
node->InsertInput(graph()->zone(), 2, pattern);
node->InsertInput(graph()->zone(), 3, literal_flags);
Builtins::CallableFor(isolate(), Builtins::kCreateRegExpLiteral);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector()));
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.feedback().index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
ReplaceWithStubCall(node, callable, flags);
}

View File

@ -290,7 +290,8 @@ std::ostream& operator<<(std::ostream& os, FeedbackParameter const& p) {
}
FeedbackParameter const& FeedbackParameterOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSStoreDataPropertyInLiteral, op->opcode());
DCHECK(op->opcode() == IrOpcode::kJSCreateEmptyLiteralArray ||
op->opcode() == IrOpcode::kJSStoreDataPropertyInLiteral);
return OpParameter<FeedbackParameter>(op);
}
@ -484,8 +485,8 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
bool operator==(CreateLiteralParameters const& lhs,
CreateLiteralParameters const& rhs) {
return lhs.constant().location() == rhs.constant().location() &&
lhs.length() == rhs.length() && lhs.flags() == rhs.flags() &&
lhs.index() == rhs.index();
lhs.feedback() == rhs.feedback() && lhs.length() == rhs.length() &&
lhs.flags() == rhs.flags();
}
@ -496,14 +497,13 @@ bool operator!=(CreateLiteralParameters const& lhs,
size_t hash_value(CreateLiteralParameters const& p) {
return base::hash_combine(p.constant().location(), p.length(), p.flags(),
p.index());
return base::hash_combine(p.constant().location(), p.feedback(), p.length(),
p.flags());
}
std::ostream& operator<<(std::ostream& os, CreateLiteralParameters const& p) {
return os << Brief(*p.constant()) << ", " << p.length() << ", " << p.flags()
<< ", " << p.index();
return os << Brief(*p.constant()) << ", " << p.length() << ", " << p.flags();
}
@ -1049,36 +1049,41 @@ const Operator* JSOperatorBuilder::CreateClosure(
}
const Operator* JSOperatorBuilder::CreateLiteralArray(
Handle<ConstantElementsPair> constant_elements, int literal_flags,
int literal_index, int number_of_elements) {
CreateLiteralParameters parameters(constant_elements, number_of_elements,
literal_flags, literal_index);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralArray, Operator::kNoProperties, // opcode
"JSCreateLiteralArray", // name
1, 1, 1, 1, 1, 2, // counts
parameters); // parameter
Handle<ConstantElementsPair> constant_elements,
VectorSlotPair const& feedback, int literal_flags, int number_of_elements) {
CreateLiteralParameters parameters(constant_elements, feedback,
number_of_elements, literal_flags);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralArray, // opcode
Operator::kNoProperties, // properties
"JSCreateLiteralArray", // name
0, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateEmptyLiteralArray(int literal_index) {
return new (zone()) Operator1<int>( // --
IrOpcode::kJSCreateEmptyLiteralArray, // opcode
Operator::kNoProperties, // properties
"JSCreateEmptyLiteralArray", // name
1, 1, 1, 1, 1, 2, // counts
literal_index); // parameter
const Operator* JSOperatorBuilder::CreateEmptyLiteralArray(
VectorSlotPair const& feedback) {
FeedbackParameter parameters(feedback);
return new (zone()) Operator1<FeedbackParameter>( // --
IrOpcode::kJSCreateEmptyLiteralArray, // opcode
Operator::kEliminatable, // properties
"JSCreateEmptyLiteralArray", // name
0, 1, 1, 1, 1, 0, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateLiteralObject(
Handle<BoilerplateDescription> constant_properties, int literal_flags,
int literal_index, int number_of_properties) {
CreateLiteralParameters parameters(constant_properties, number_of_properties,
literal_flags, literal_index);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralObject, Operator::kNoProperties, // opcode
"JSCreateLiteralObject", // name
1, 1, 1, 1, 1, 2, // counts
parameters); // parameter
Handle<BoilerplateDescription> constant_properties,
VectorSlotPair const& feedback, int literal_flags,
int number_of_properties) {
CreateLiteralParameters parameters(constant_properties, feedback,
number_of_properties, literal_flags);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralObject, // opcode
Operator::kNoProperties, // properties
"JSCreateLiteralObject", // name
0, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateEmptyLiteralObject() {
@ -1090,14 +1095,16 @@ const Operator* JSOperatorBuilder::CreateEmptyLiteralObject() {
}
const Operator* JSOperatorBuilder::CreateLiteralRegExp(
Handle<String> constant_pattern, int literal_flags, int literal_index) {
CreateLiteralParameters parameters(constant_pattern, -1, literal_flags,
literal_index);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralRegExp, Operator::kNoProperties, // opcode
"JSCreateLiteralRegExp", // name
1, 1, 1, 1, 1, 2, // counts
parameters); // parameter
Handle<String> constant_pattern, VectorSlotPair const& feedback,
int literal_flags) {
CreateLiteralParameters parameters(constant_pattern, feedback, -1,
literal_flags);
return new (zone()) Operator1<CreateLiteralParameters>( // --
IrOpcode::kJSCreateLiteralRegExp, // opcode
Operator::kNoProperties, // properties
"JSCreateLiteralRegExp", // name
0, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateFunctionContext(int slot_count,

View File

@ -366,8 +366,8 @@ std::ostream& operator<<(std::ostream&, StoreNamedOwnParameters const&);
const StoreNamedOwnParameters& StoreNamedOwnParametersOf(const Operator* op);
// Defines the feedback, i.e., vector and index, for storing a data property in
// an object literal. This is
// used as a parameter by the JSStoreDataPropertyInLiteral operator.
// an object literal. This is used as a parameter by JSCreateEmptyLiteralArray
// and JSStoreDataPropertyInLiteral operators.
class FeedbackParameter final {
public:
explicit FeedbackParameter(VectorSlotPair const& feedback)
@ -561,20 +561,23 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op);
// JSCreateLiteralRegExp operators.
class CreateLiteralParameters final {
public:
CreateLiteralParameters(Handle<HeapObject> constant, int length, int flags,
int index)
: constant_(constant), length_(length), flags_(flags), index_(index) {}
CreateLiteralParameters(Handle<HeapObject> constant,
VectorSlotPair const& feedback, int length, int flags)
: constant_(constant),
feedback_(feedback),
length_(length),
flags_(flags) {}
Handle<HeapObject> constant() const { return constant_; }
VectorSlotPair const& feedback() const { return feedback_; }
int length() const { return length_; }
int flags() const { return flags_; }
int index() const { return index_; }
private:
Handle<HeapObject> const constant_;
VectorSlotPair const feedback_;
int const length_;
int const flags_;
int const index_;
};
bool operator==(CreateLiteralParameters const&, CreateLiteralParameters const&);
@ -647,16 +650,18 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* CreateIterResultObject();
const Operator* CreateKeyValueArray();
const Operator* CreateLiteralArray(Handle<ConstantElementsPair> constant,
int literal_flags, int literal_index,
int number_of_elements);
const Operator* CreateEmptyLiteralArray(int literal_index);
VectorSlotPair const& feedback,
int literal_flags, int number_of_elements);
const Operator* CreateEmptyLiteralArray(VectorSlotPair const& feedback);
const Operator* CreateEmptyLiteralObject();
const Operator* CreateLiteralObject(Handle<BoilerplateDescription> constant,
int literal_flags, int literal_index,
VectorSlotPair const& feedback,
int literal_flags,
int number_of_properties);
const Operator* CreateLiteralRegExp(Handle<String> constant_pattern,
int literal_flags, int literal_index);
VectorSlotPair const& feedback,
int literal_flags);
const Operator* CallForwardVarargs(size_t arity, uint32_t start_index);
const Operator* Call(

View File

@ -1028,11 +1028,9 @@ struct TypedLoweringPhase {
JSBuiltinReducer builtin_reducer(
&graph_reducer, data->jsgraph(),
data->info()->dependencies(), data->native_context());
Handle<FeedbackVector> feedback_vector(
data->info()->closure()->feedback_vector());
JSCreateLowering create_lowering(
&graph_reducer, data->info()->dependencies(), data->jsgraph(),
feedback_vector, data->native_context(), temp_zone);
data->native_context(), temp_zone);
JSTypedLowering typed_lowering(&graph_reducer, data->jsgraph(), temp_zone);
TypedOptimization typed_optimization(
&graph_reducer, data->info()->dependencies(), data->jsgraph());

View File

@ -90,27 +90,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edi, eax, ecx, edx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax, ebx, ecx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {eax, ebx, ecx, edx};
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {edi};

View File

@ -400,26 +400,6 @@ void NewArgumentsElementsDescriptor::InitializePlatformSpecific(
DefaultInitializePlatformSpecific(data, 3);
}
void FastCloneRegExpDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kClosure, kLiteralIndex, kPattern, kFlags
MachineType machine_types[] = {
MachineType::AnyTagged(), MachineType::TaggedSigned(),
MachineType::AnyTagged(), MachineType::AnyTagged()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void FastCloneShallowArrayDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kClosure, kLiteralIndex, kConstantElements
MachineType machine_types[] = {MachineType::AnyTagged(),
MachineType::TaggedSigned(),
MachineType::AnyTagged()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void CallTrampolineDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kFunction, kActualArgumentsCount

View File

@ -37,9 +37,6 @@ class PlatformInterfaceDescriptor;
V(TypeConversion) \
V(TypeConversionStackParameter) \
V(Typeof) \
V(FastCloneRegExp) \
V(FastCloneShallowArray) \
V(FastCloneShallowObject) \
V(CallFunction) \
V(CallVarargs) \
V(CallForwardVarargs) \
@ -560,29 +557,6 @@ class TypeofDescriptor : public CallInterfaceDescriptor {
DECLARE_DESCRIPTOR(TypeofDescriptor, CallInterfaceDescriptor)
};
class FastCloneRegExpDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kClosure, kLiteralIndex, kPattern, kFlags)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastCloneRegExpDescriptor,
CallInterfaceDescriptor)
};
class FastCloneShallowArrayDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kClosure, kLiteralIndex, kConstantElements)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastCloneShallowArrayDescriptor,
CallInterfaceDescriptor)
};
class FastCloneShallowObjectDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kClosure, kLiteralIndex, kBoilerplateDescription, kFlags)
DECLARE_DESCRIPTOR(FastCloneShallowObjectDescriptor, CallInterfaceDescriptor)
};
class CallTrampolineDescriptor : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kFunction, kActualArgumentsCount)

View File

@ -1933,7 +1933,7 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
object_literals_.push_back(std::make_pair(expr, entry));
}
// TODO(cbruni): Directly generate runtime call for literals we cannot
// optimize once the FastCloneShallowObject stub is in sync with the TF
// optimize once the CreateShallowObjectLiteral stub is in sync with the TF
// optimizations.
builder()->CreateObjectLiteral(entry, literal_index, flags, literal);

View File

@ -2643,15 +2643,15 @@ IGNITION_HANDLER(SwitchOnSmiNoFeedback, InterpreterAssembler) {
// Creates a regular expression literal for literal index <literal_idx> with
// <flags> and the pattern in <pattern_idx>.
IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
Node* index = BytecodeOperandIdx(0);
Node* pattern = LoadConstantPoolEntry(index);
Node* literal_index = BytecodeOperandIdxSmi(1);
Node* pattern_index = BytecodeOperandIdx(0);
Node* pattern = LoadConstantPoolEntry(pattern_index);
Node* feedback_vector = LoadFeedbackVector();
Node* slot_id = BytecodeOperandIdx(1);
Node* flags = SmiFromWord32(BytecodeOperandFlag(2));
Node* closure = LoadRegister(Register::function_closure());
Node* context = GetContext();
ConstructorBuiltinsAssembler constructor_assembler(state());
Node* result = constructor_assembler.EmitFastCloneRegExp(
closure, literal_index, pattern, flags, context);
Node* result = constructor_assembler.EmitCreateRegExpLiteral(
feedback_vector, slot_id, pattern, flags, context);
SetAccumulator(result);
Dispatch();
}
@ -2661,8 +2661,8 @@ IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
// Creates an array literal for literal index <literal_idx> with
// CreateArrayLiteral flags <flags> and constant elements in <element_idx>.
IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
Node* literal_index = BytecodeOperandIdxSmi(1);
Node* closure = LoadRegister(Register::function_closure());
Node* feedback_vector = LoadFeedbackVector();
Node* slot_id = BytecodeOperandIdx(1);
Node* context = GetContext();
Node* bytecode_flags = BytecodeOperandFlag(2);
@ -2674,8 +2674,9 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
BIND(&fast_shallow_clone);
{
ConstructorBuiltinsAssembler constructor_assembler(state());
Node* result = constructor_assembler.EmitFastCloneShallowArray(
closure, literal_index, context, &call_runtime, TRACK_ALLOCATION_SITE);
Node* result = constructor_assembler.EmitCreateShallowArrayLiteral(
feedback_vector, slot_id, context, &call_runtime,
TRACK_ALLOCATION_SITE);
SetAccumulator(result);
Dispatch();
}
@ -2687,8 +2688,9 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
Node* flags = SmiTag(flags_raw);
Node* index = BytecodeOperandIdx(0);
Node* constant_elements = LoadConstantPoolEntry(index);
Node* result = CallRuntime(Runtime::kCreateArrayLiteral, context, closure,
literal_index, constant_elements, flags);
Node* result =
CallRuntime(Runtime::kCreateArrayLiteral, context, feedback_vector,
SmiTag(slot_id), constant_elements, flags);
SetAccumulator(result);
Dispatch();
}
@ -2698,12 +2700,12 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
//
// Creates an empty JSArray literal for literal index <literal_idx>.
IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
Node* literal_index = BytecodeOperandIdxSmi(0);
Node* closure = LoadRegister(Register::function_closure());
Node* feedback_vector = LoadFeedbackVector();
Node* slot_id = BytecodeOperandIdx(0);
Node* context = GetContext();
ConstructorBuiltinsAssembler constructor_assembler(state());
Node* result = constructor_assembler.EmitCreateEmptyArrayLiteral(
closure, literal_index, context);
feedback_vector, slot_id, context);
SetAccumulator(result);
Dispatch();
}
@ -2713,9 +2715,9 @@ IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
// Creates an object literal for literal index <literal_idx> with
// CreateObjectLiteralFlags <flags> and constant elements in <element_idx>.
IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
Node* literal_index = BytecodeOperandIdxSmi(1);
Node* feedback_vector = LoadFeedbackVector();
Node* slot_id = BytecodeOperandIdx(1);
Node* bytecode_flags = BytecodeOperandFlag(2);
Node* closure = LoadRegister(Register::function_closure());
// Check if we can do a fast clone or have to call the runtime.
Label if_fast_clone(this), if_not_fast_clone(this, Label::kDeferred);
@ -2725,10 +2727,10 @@ IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
BIND(&if_fast_clone);
{
// If we can do a fast clone do the fast-path in FastCloneShallowObjectStub.
// If we can do a fast clone do the fast-path in CreateShallowObjectLiteral.
ConstructorBuiltinsAssembler constructor_assembler(state());
Node* result = constructor_assembler.EmitFastCloneShallowObject(
&if_not_fast_clone, closure, literal_index);
Node* result = constructor_assembler.EmitCreateShallowObjectLiteral(
feedback_vector, slot_id, &if_not_fast_clone);
StoreRegister(result, BytecodeOperandReg(3));
Dispatch();
}
@ -2744,8 +2746,9 @@ IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
bytecode_flags);
Node* flags = SmiTag(flags_raw);
Node* result = CallRuntime(Runtime::kCreateObjectLiteral, context, closure,
literal_index, boilerplate_description, flags);
Node* result =
CallRuntime(Runtime::kCreateObjectLiteral, context, feedback_vector,
SmiTag(slot_id), boilerplate_description, flags);
StoreRegister(result, BytecodeOperandReg(3));
// TODO(klaasb) build a single dispatch once the call is inlined
Dispatch();

View File

@ -88,27 +88,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a3, a2, a1, a0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a3, a2, a1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a3, a2, a1, a0};
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a1};

View File

@ -88,27 +88,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a3, a2, a1, a0};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a3, a2, a1};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a3, a2, a1, a0};
data->InitializePlatformSpecific(arraysize(registers), registers, NULL);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {a1};

View File

@ -88,27 +88,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r6, r5, r4, r3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r6, r5, r4};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r6, r5, r4, r3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r4};

View File

@ -451,10 +451,9 @@ Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
template <typename Boilerplate>
MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
Handle<JSFunction> closure,
Handle<FeedbackVector> vector,
int literals_index,
Handle<HeapObject> description, int flags) {
Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
CHECK(literals_slot.ToInt() < vector->length());
Handle<Object> literal_site(vector->Get(literals_slot), isolate);
@ -521,36 +520,35 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(BoilerplateDescription, description, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteral<ObjectBoilerplate>(
isolate, closure, literals_index, description, flags));
isolate, CreateLiteral<ObjectBoilerplate>(isolate, vector, literals_index,
description, flags));
}
RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
CONVERT_SMI_ARG_CHECKED(literals_index, 1);
CONVERT_ARG_HANDLE_CHECKED(ConstantElementsPair, elements, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteral<ArrayBoilerplate>(isolate, closure, literals_index,
isolate, CreateLiteral<ArrayBoilerplate>(isolate, vector, literals_index,
elements, flags));
}
RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
HandleScope scope(isolate);
DCHECK_EQ(4, args.length());
CONVERT_ARG_HANDLE_CHECKED(JSFunction, closure, 0);
CONVERT_ARG_HANDLE_CHECKED(FeedbackVector, vector, 0);
CONVERT_SMI_ARG_CHECKED(index, 1);
CONVERT_ARG_HANDLE_CHECKED(String, pattern, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
Handle<FeedbackVector> vector(closure->feedback_vector(), isolate);
FeedbackSlot literal_slot(FeedbackVector::ToSlot(index));
// Check if boilerplate exists. If not, create it first.

View File

@ -86,24 +86,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r5, r4, r3, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r5, r4, r3};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r5, r4, r3, r2};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {r3};

View File

@ -91,27 +91,6 @@ void TypeofDescriptor::InitializePlatformSpecific(
// static
const Register TypeConversionDescriptor::ArgumentRegister() { return rax; }
void FastCloneRegExpDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdi, rax, rcx, rdx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowArrayDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rax, rbx, rcx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void FastCloneShallowObjectDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rax, rbx, rcx, rdx};
data->InitializePlatformSpecific(arraysize(registers), registers);
}
void CallFunctionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {rdi};

View File

@ -40,8 +40,7 @@ class JSCreateLoweringTest : public TypedGraphTest {
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph,
MaybeHandle<FeedbackVector>(), native_context(),
JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, native_context(),
zone());
return reducer.Reduce(node);
}