Revert "[literals] Introduce CreateEmptyArrayLiteral Bytecode"
This reverts commit 4851745fe3
.
Reason for revert: Top crasher on Canary, see https://crbug.com/746935
Original change's description:
> [literals] Introduce CreateEmptyArrayLiteral Bytecode
>
> Empty Array literals are amongst the most commonly used literal types on our
> top25 page list. Using a custom bytecode we can drop the boilerplate for empty
> Array literals alltogether. However, we still need a proper AllocationSite to
> track ElementsKind transitions.
>
> Bug: v8:6211
> Change-Id: Id5dbdac0ea8e24dd474e679c902c6e4a2957af1d
> Reviewed-on: https://chromium-review.googlesource.com/567079
> Commit-Queue: Camillo Bruni <cbruni@chromium.org>
> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
> Reviewed-by: Igor Sheludko <ishell@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#46752}
TBR=rmcilroy@chromium.org,mstarzinger@chromium.org,cbruni@chromium.org,ishell@chromium.org,rmcilroy@google.com
Bug: v8:6211, chromium:746935
Change-Id: Ibf19a923688c071d03bad8661a10e08f8414db56
Reviewed-on: https://chromium-review.googlesource.com/580193
Commit-Queue: Adam Klein <adamk@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46804}
This commit is contained in:
parent
8ab48b6c04
commit
62f8337742
@ -1442,12 +1442,6 @@ class ArrayLiteral final : public AggregateLiteral {
|
||||
|
||||
ZoneList<Expression*>* values() const { return values_; }
|
||||
|
||||
bool is_empty() const {
|
||||
DCHECK(is_initialized());
|
||||
return values()->is_empty() &&
|
||||
(constant_elements().is_null() || constant_elements()->is_empty());
|
||||
}
|
||||
|
||||
// Populate the depth field and flags, returns the depth.
|
||||
int InitDepthAndFlags();
|
||||
|
||||
|
@ -197,6 +197,14 @@ Node* ConstructorBuiltinsAssembler::EmitFastNewClosure(Node* shared_info,
|
||||
return result;
|
||||
}
|
||||
|
||||
Node* ConstructorBuiltinsAssembler::LoadFeedbackVectorSlot(
|
||||
Node* closure, Node* literal_index) {
|
||||
Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
|
||||
Node* feedback_vector = LoadObjectField(cell, Cell::kValueOffset);
|
||||
return LoadFixedArrayElement(feedback_vector, literal_index, 0,
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
}
|
||||
|
||||
Node* ConstructorBuiltinsAssembler::NotHasBoilerplate(Node* literal_site) {
|
||||
return TaggedIsSmi(literal_site);
|
||||
}
|
||||
@ -207,29 +215,6 @@ Node* ConstructorBuiltinsAssembler::LoadAllocationSiteBoilerplate(Node* site) {
|
||||
AllocationSite::kTransitionInfoOrBoilerplateOffset);
|
||||
}
|
||||
|
||||
Node* ConstructorBuiltinsAssembler::AllocateAllocationSite(
|
||||
Node* closure, Node* literal_index) {
|
||||
CSA_ASSERT(this, TaggedIsPositiveSmi(literal_index));
|
||||
Node* result = Allocate(AllocationSite::kSize);
|
||||
StoreMapNoWriteBarrier(result, Heap::kAllocationSiteMapRootIndex);
|
||||
// Should match AllocationSite::Initialize.
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
result, AllocationSite::kTransitionInfoOrBoilerplateOffset,
|
||||
SmiConstant(0));
|
||||
StoreObjectFieldNoWriteBarrier(result, AllocationSite::kNestedSiteOffset,
|
||||
SmiConstant(0));
|
||||
StoreObjectFieldNoWriteBarrier(result, AllocationSite::kPretenureDataOffset,
|
||||
SmiConstant(0));
|
||||
StoreObjectFieldNoWriteBarrier(
|
||||
result, AllocationSite::kPretenureCreateCountOffset, SmiConstant(0));
|
||||
StoreObjectFieldNoWriteBarrier(result, AllocationSite::kWeakNextOffset,
|
||||
SmiConstant(0));
|
||||
StoreObjectFieldRoot(result, AllocationSite::kDependentCodeOffset,
|
||||
Heap::kEmptyFixedArrayRootIndex);
|
||||
StoreFeedbackVectorSlot(closure, literal_index, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
TF_BUILTIN(FastNewClosure, ConstructorBuiltinsAssembler) {
|
||||
Node* shared = Parameter(FastNewClosureDescriptor::kSharedFunctionInfo);
|
||||
Node* context = Parameter(FastNewClosureDescriptor::kContext);
|
||||
@ -580,55 +565,6 @@ TF_BUILTIN(FastCloneShallowArrayDontTrack, ConstructorBuiltinsAssembler) {
|
||||
CreateFastCloneShallowArrayBuiltin(DONT_TRACK_ALLOCATION_SITE);
|
||||
}
|
||||
|
||||
Node* ConstructorBuiltinsAssembler::EmitCreateEmptyArrayLiteral(
|
||||
Node* closure, Node* literal_index, Node* context) {
|
||||
// Array literals always have a valid AllocationSite to properly track
|
||||
// elements transitions.
|
||||
VARIABLE(allocation_site, MachineRepresentation::kTagged,
|
||||
LoadFeedbackVectorSlot(closure, literal_index));
|
||||
|
||||
Label create_empty_array(this),
|
||||
initialize_allocation_site(this, Label::kDeferred), done(this);
|
||||
Branch(TaggedIsSmi(allocation_site.value()), &initialize_allocation_site,
|
||||
&create_empty_array);
|
||||
|
||||
// TODO(cbruni): create the AllocationSite in CSA.
|
||||
BIND(&initialize_allocation_site);
|
||||
{
|
||||
allocation_site.Bind(AllocateAllocationSite(closure, literal_index));
|
||||
Goto(&create_empty_array);
|
||||
}
|
||||
|
||||
BIND(&create_empty_array);
|
||||
CSA_ASSERT(this, IsAllocationSite(allocation_site.value()));
|
||||
Node* kind = SmiToWord32(
|
||||
LoadObjectField(allocation_site.value(),
|
||||
AllocationSite::kTransitionInfoOrBoilerplateOffset));
|
||||
CSA_ASSERT(this, IsFastElementsKind(kind));
|
||||
Node* native_context = LoadNativeContext(context);
|
||||
Comment("LoadJSArrayElementsMap");
|
||||
Node* array_map = LoadJSArrayElementsMap(kind, native_context);
|
||||
Node* zero = SmiConstant(0);
|
||||
Comment("Allocate JSArray");
|
||||
Node* result =
|
||||
AllocateJSArray(GetInitialFastElementsKind(), array_map, zero, zero,
|
||||
allocation_site.value(), ParameterMode::SMI_PARAMETERS);
|
||||
|
||||
Goto(&done);
|
||||
BIND(&done);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TF_BUILTIN(CreateEmptyArrayLiteral, ConstructorBuiltinsAssembler) {
|
||||
Node* closure = Parameter(CreateEmptyArrayLiteralDescriptor::kClosure);
|
||||
Node* literal_index =
|
||||
Parameter(CreateEmptyArrayLiteralDescriptor::kLiteralIndex);
|
||||
Node* context = Parameter(CreateEmptyArrayLiteralDescriptor::kContext);
|
||||
Node* result = EmitCreateEmptyArrayLiteral(closure, literal_index, context);
|
||||
Return(result);
|
||||
}
|
||||
|
||||
Node* ConstructorBuiltinsAssembler::EmitFastCloneShallowObject(
|
||||
Label* call_runtime, Node* closure, Node* literals_index) {
|
||||
Node* allocation_site = LoadFeedbackVectorSlot(closure, literals_index);
|
||||
|
@ -26,8 +26,6 @@ class ConstructorBuiltinsAssembler : public CodeStubAssembler {
|
||||
Node* context, Label* call_runtime,
|
||||
AllocationSiteMode allocation_site_mode);
|
||||
|
||||
Node* EmitCreateEmptyArrayLiteral(Node* closure, Node* iteral_index,
|
||||
Node* context);
|
||||
void CreateFastCloneShallowArrayBuiltin(
|
||||
AllocationSiteMode allocation_site_mode);
|
||||
|
||||
@ -45,12 +43,9 @@ class ConstructorBuiltinsAssembler : public CodeStubAssembler {
|
||||
Node* capacity, ElementsKind kind);
|
||||
Node* CopyFixedArrayBase(Node* elements);
|
||||
|
||||
Node* LoadFeedbackVectorSlot(Node* closure, Node* literal_index);
|
||||
Node* NotHasBoilerplate(Node* literal_site);
|
||||
Node* LoadAllocationSiteBoilerplate(Node* allocation_site);
|
||||
|
||||
// Allocate an AllocationSite and store it at the {literal_index} in the
|
||||
// feedback vector of the given {closure}.
|
||||
Node* AllocateAllocationSite(Node* closure, Node* literal_index);
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -103,7 +103,6 @@ namespace internal {
|
||||
TFC(FastCloneRegExp, FastCloneRegExp, 1) \
|
||||
TFC(FastCloneShallowArrayTrack, FastCloneShallowArray, 1) \
|
||||
TFC(FastCloneShallowArrayDontTrack, FastCloneShallowArray, 1) \
|
||||
TFS(CreateEmptyArrayLiteral, kClosure, kLiteralIndex) \
|
||||
TFC(FastCloneShallowObject, FastCloneShallowObject, 1) \
|
||||
/* ES6 section 9.5.14 [[Construct]] ( argumentsList, newTarget) */ \
|
||||
TFC(ConstructProxy, ConstructTrampoline, 1) \
|
||||
|
@ -1430,15 +1430,6 @@ Node* CodeStubAssembler::LoadNativeContext(Node* context) {
|
||||
return LoadContextElement(context, Context::NATIVE_CONTEXT_INDEX);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadJSArrayElementsMap(Node* kind,
|
||||
Node* native_context) {
|
||||
CSA_ASSERT(this, IsFastElementsKind(kind));
|
||||
CSA_ASSERT(this, IsNativeContext(native_context));
|
||||
Node* offset = IntPtrAdd(IntPtrConstant(Context::FIRST_JS_ARRAY_MAP_SLOT),
|
||||
ChangeInt32ToIntPtr(kind));
|
||||
return LoadContextElement(native_context, offset);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind,
|
||||
Node* native_context) {
|
||||
CSA_ASSERT(this, IsNativeContext(native_context));
|
||||
@ -6316,30 +6307,11 @@ Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
|
||||
return IntPtrAdd(IntPtrConstant(base_size), shifted_index);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadFeedbackVector(Node* closure) {
|
||||
Node* cell = LoadObjectField(closure, JSFunction::kFeedbackVectorOffset);
|
||||
return LoadObjectField(cell, Cell::kValueOffset);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadFeedbackVectorForStub() {
|
||||
Node* function =
|
||||
LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset);
|
||||
return LoadFeedbackVector(function);
|
||||
}
|
||||
|
||||
Node* CodeStubAssembler::LoadFeedbackVectorSlot(Node* closure,
|
||||
Node* smi_index) {
|
||||
Node* feedback_vector = LoadFeedbackVector(closure);
|
||||
return LoadFixedArrayElement(feedback_vector, smi_index, 0,
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
}
|
||||
|
||||
void CodeStubAssembler::StoreFeedbackVectorSlot(Node* closure, Node* smi_index,
|
||||
Node* value) {
|
||||
Node* feedback_vector = LoadFeedbackVector(closure);
|
||||
StoreFixedArrayElement(feedback_vector, smi_index, value,
|
||||
UPDATE_WRITE_BARRIER, 0,
|
||||
CodeStubAssembler::SMI_PARAMETERS);
|
||||
Node* cell = LoadObjectField(function, JSFunction::kFeedbackVectorOffset);
|
||||
return LoadObjectField(cell, Cell::kValueOffset);
|
||||
}
|
||||
|
||||
void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector,
|
||||
|
@ -482,7 +482,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
Node* LoadNativeContext(Node* context);
|
||||
|
||||
Node* LoadJSArrayElementsMap(ElementsKind kind, Node* native_context);
|
||||
Node* LoadJSArrayElementsMap(Node* kind, Node* native_context);
|
||||
|
||||
// Load the "prototype" property of a JSFunction.
|
||||
Node* LoadJSFunctionPrototype(Node* function, Label* if_bailout);
|
||||
@ -1297,10 +1296,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
|
||||
// Load type feedback vector from the stub caller's frame.
|
||||
Node* LoadFeedbackVectorForStub();
|
||||
|
||||
Node* LoadFeedbackVector(Node* closure);
|
||||
Node* LoadFeedbackVectorSlot(Node* closure, Node* smi_index);
|
||||
void StoreFeedbackVectorSlot(Node* closure, Node* smi_index, Node* value);
|
||||
|
||||
// Update the type feedback vector.
|
||||
void UpdateFeedback(Node* feedback, Node* feedback_vector, Node* slot_id,
|
||||
Node* function);
|
||||
|
@ -1486,13 +1486,6 @@ void BytecodeGraphBuilder::VisitCreateArrayLiteral() {
|
||||
environment()->BindAccumulator(literal, Environment::kAttachFrameState);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() {
|
||||
int literal_index = bytecode_iterator().GetIndexOperand(0);
|
||||
Node* literal = NewNode(javascript()->CreateEmptyLiteralArray(literal_index),
|
||||
GetFunctionClosure());
|
||||
environment()->BindAccumulator(literal);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
|
||||
Handle<BoilerplateDescription> constant_properties =
|
||||
Handle<BoilerplateDescription>::cast(
|
||||
|
@ -223,8 +223,6 @@ Reduction JSCreateLowering::Reduce(Node* node) {
|
||||
return ReduceJSCreateLiteralArrayOrObject(node);
|
||||
case IrOpcode::kJSCreateLiteralRegExp:
|
||||
return ReduceJSCreateLiteralRegExp(node);
|
||||
case IrOpcode::kJSCreateEmptyLiteralArray:
|
||||
return ReduceJSCreateEmptyLiteralArray(node);
|
||||
case IrOpcode::kJSCreateFunctionContext:
|
||||
return ReduceJSCreateFunctionContext(node);
|
||||
case IrOpcode::kJSCreateWithContext:
|
||||
@ -625,8 +623,7 @@ Reduction JSCreateLowering::ReduceJSCreateGeneratorObject(Node* node) {
|
||||
Reduction JSCreateLowering::ReduceNewArray(Node* node, Node* length,
|
||||
int capacity,
|
||||
Handle<AllocationSite> site) {
|
||||
DCHECK(node->opcode() == IrOpcode::kJSCreateArray ||
|
||||
node->opcode() == IrOpcode::kJSCreateEmptyLiteralArray);
|
||||
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
Node* control = NodeProperties::GetControlInput(node);
|
||||
|
||||
@ -941,23 +938,6 @@ Reduction JSCreateLowering::ReduceJSCreateLiteralRegExp(Node* node) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction JSCreateLowering::ReduceJSCreateFunctionContext(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kJSCreateFunctionContext, node->opcode());
|
||||
const CreateFunctionContextParameters& parameters =
|
||||
|
@ -54,7 +54,6 @@ class V8_EXPORT_PRIVATE JSCreateLowering final
|
||||
Reduction ReduceJSCreateArray(Node* node);
|
||||
Reduction ReduceJSCreateIterResultObject(Node* node);
|
||||
Reduction ReduceJSCreateKeyValueArray(Node* node);
|
||||
Reduction ReduceJSCreateEmptyLiteralArray(Node* node);
|
||||
Reduction ReduceJSCreateLiteralArrayOrObject(Node* node);
|
||||
Reduction ReduceJSCreateLiteralRegExp(Node* node);
|
||||
Reduction ReduceJSCreateFunctionContext(Node* node);
|
||||
|
@ -476,14 +476,6 @@ 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));
|
||||
Callable callable =
|
||||
Builtins::CallableFor(isolate(), Builtins::kCreateEmptyArrayLiteral);
|
||||
ReplaceWithStubCall(node, callable, flags);
|
||||
}
|
||||
|
||||
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
|
||||
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
|
||||
|
@ -1039,15 +1039,6 @@ const Operator* JSOperatorBuilder::CreateLiteralArray(
|
||||
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::CreateLiteralObject(
|
||||
Handle<BoilerplateDescription> constant_properties, int literal_flags,
|
||||
int literal_index, int number_of_properties) {
|
||||
|
@ -660,8 +660,6 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
|
||||
const Operator* CreateLiteralArray(Handle<ConstantElementsPair> constant,
|
||||
int literal_flags, int literal_index,
|
||||
int number_of_elements);
|
||||
const Operator* CreateEmptyLiteralArray(int literal_index);
|
||||
|
||||
const Operator* CreateLiteralObject(Handle<BoilerplateDescription> constant,
|
||||
int literal_flags, int literal_index,
|
||||
int number_of_properties);
|
||||
|
@ -135,7 +135,6 @@
|
||||
V(JSCreateIterResultObject) \
|
||||
V(JSCreateKeyValueArray) \
|
||||
V(JSCreateLiteralArray) \
|
||||
V(JSCreateEmptyLiteralArray) \
|
||||
V(JSCreateLiteralObject) \
|
||||
V(JSCreateLiteralRegExp) \
|
||||
V(JSLoadProperty) \
|
||||
|
@ -1124,9 +1124,6 @@ Type* Typer::Visitor::TypeJSCreateLiteralArray(Node* node) {
|
||||
return Type::Array();
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeJSCreateEmptyLiteralArray(Node* node) {
|
||||
return Type::Array();
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeJSCreateLiteralObject(Node* node) {
|
||||
return Type::OtherObject();
|
||||
|
@ -611,10 +611,6 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
// Type is Array.
|
||||
CheckTypeIs(node, Type::Array());
|
||||
break;
|
||||
case IrOpcode::kJSCreateEmptyLiteralArray:
|
||||
// Type is Array.
|
||||
CheckTypeIs(node, Type::Array());
|
||||
break;
|
||||
case IrOpcode::kJSCreateLiteralObject:
|
||||
case IrOpcode::kJSCreateLiteralRegExp:
|
||||
// Type is OtherObject.
|
||||
|
@ -954,12 +954,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateEmptyArrayLiteral(
|
||||
int literal_index) {
|
||||
OutputCreateEmptyArrayLiteral(literal_index);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
|
||||
size_t constant_elements_entry, int literal_index, int flags) {
|
||||
OutputCreateArrayLiteral(constant_elements_entry, literal_index, flags);
|
||||
|
@ -220,7 +220,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
|
||||
int literal_index, int flags);
|
||||
BytecodeArrayBuilder& CreateArrayLiteral(size_t constant_elements_entry,
|
||||
int literal_index, int flags);
|
||||
BytecodeArrayBuilder& CreateEmptyArrayLiteral(int literal_index);
|
||||
BytecodeArrayBuilder& CreateObjectLiteral(size_t constant_properties_entry,
|
||||
int literal_index, int flags,
|
||||
Register output);
|
||||
|
@ -2070,18 +2070,12 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
|
||||
void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
// Deep-copy the literal boilerplate.
|
||||
int literal_index = feedback_index(expr->literal_slot());
|
||||
if (expr->is_empty()) {
|
||||
// Empty array literal fast-path.
|
||||
DCHECK(expr->IsFastCloningSupported());
|
||||
builder()->CreateEmptyArrayLiteral(literal_index);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t flags = CreateArrayLiteralFlags::Encode(
|
||||
expr->IsFastCloningSupported(), expr->ComputeFlags());
|
||||
|
||||
size_t entry = builder()->AllocateDeferredConstantPoolEntry();
|
||||
builder()->CreateArrayLiteral(entry, literal_index, flags);
|
||||
builder()->CreateArrayLiteral(entry, feedback_index(expr->literal_slot()),
|
||||
flags);
|
||||
array_literals_.push_back(std::make_pair(expr, entry));
|
||||
|
||||
Register index, literal;
|
||||
|
@ -227,7 +227,6 @@ namespace interpreter {
|
||||
OperandType::kIdx, OperandType::kFlag8) \
|
||||
V(CreateArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx, \
|
||||
OperandType::kIdx, OperandType::kFlag8) \
|
||||
V(CreateEmptyArrayLiteral, AccumulatorUse::kWrite, OperandType::kIdx) \
|
||||
V(CreateObjectLiteral, AccumulatorUse::kNone, OperandType::kIdx, \
|
||||
OperandType::kIdx, OperandType::kFlag8, OperandType::kRegOut) \
|
||||
\
|
||||
|
@ -2648,20 +2648,6 @@ IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
|
||||
}
|
||||
}
|
||||
|
||||
// CreateEmptyArrayLiteral <literal_idx>
|
||||
//
|
||||
// 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* context = GetContext();
|
||||
ConstructorBuiltinsAssembler constructor_assembler(state());
|
||||
Node* result = constructor_assembler.EmitCreateEmptyArrayLiteral(
|
||||
closure, literal_index, context);
|
||||
SetAccumulator(result);
|
||||
Dispatch();
|
||||
}
|
||||
|
||||
// CreateObjectLiteral <element_idx> <literal_idx> <flags>
|
||||
//
|
||||
// Creates an object literal for literal index <literal_idx> with
|
||||
|
@ -4426,9 +4426,6 @@ ACCESSORS(ContextExtension, extension, Object, kExtensionOffset)
|
||||
SMI_ACCESSORS(ConstantElementsPair, elements_kind, kElementsKindOffset)
|
||||
ACCESSORS(ConstantElementsPair, constant_values, FixedArrayBase,
|
||||
kConstantValuesOffset)
|
||||
bool ConstantElementsPair::is_empty() const {
|
||||
return constant_values()->length() == 0;
|
||||
}
|
||||
|
||||
ACCESSORS(JSModuleNamespace, module, Module, kModuleOffset)
|
||||
|
||||
|
@ -45,8 +45,6 @@ class ConstantElementsPair : public Tuple2 {
|
||||
DECL_INT_ACCESSORS(elements_kind)
|
||||
DECL_ACCESSORS(constant_values, FixedArrayBase)
|
||||
|
||||
inline bool is_empty() const;
|
||||
|
||||
DECL_CAST(ConstantElementsPair)
|
||||
|
||||
static const int kElementsKindOffset = kValue1Offset;
|
||||
|
@ -16,8 +16,8 @@ namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
bool IsUninitializedLiteralSite(Object* literal_site) {
|
||||
return literal_site == Smi::kZero;
|
||||
bool IsUninitializedLiteralSite(Handle<Object> literal_site) {
|
||||
return *literal_site == Smi::kZero;
|
||||
}
|
||||
|
||||
bool HasBoilerplate(Isolate* isolate, Handle<Object> literal_site) {
|
||||
@ -478,7 +478,7 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
|
||||
// TODO(cbruni): Even in the case where we need an initial allocation site
|
||||
// we could still create the boilerplate lazily to save memory.
|
||||
if (!needs_initial_allocation_site &&
|
||||
IsUninitializedLiteralSite(*literal_site)) {
|
||||
IsUninitializedLiteralSite(literal_site)) {
|
||||
PreInitializeLiteralSite(vector, literals_slot);
|
||||
boilerplate =
|
||||
Boilerplate::Create(isolate, description, flags, NOT_TENURED);
|
||||
@ -559,7 +559,7 @@ RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {
|
||||
if (!HasBoilerplate(isolate, literal_site)) {
|
||||
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
||||
isolate, boilerplate, JSRegExp::New(pattern, JSRegExp::Flags(flags)));
|
||||
if (IsUninitializedLiteralSite(*literal_site)) {
|
||||
if (IsUninitializedLiteralSite(literal_site)) {
|
||||
PreInitializeLiteralSite(vector, literal_slot);
|
||||
return *boilerplate;
|
||||
}
|
||||
|
@ -2526,29 +2526,6 @@ TEST(DirectMemoryTest16BitWord32) {
|
||||
CHECK_EQ(1, ft.CallChecked<Smi>()->value());
|
||||
}
|
||||
|
||||
TEST(LoadJSArrayElementsMap) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
const int kNumParams = 1;
|
||||
CodeAssemblerTester asm_tester(isolate, kNumParams);
|
||||
{
|
||||
CodeStubAssembler m(asm_tester.state());
|
||||
Node* context = m.Parameter(kNumParams + 2);
|
||||
Node* native_context = m.LoadNativeContext(context);
|
||||
Node* kind = m.SmiToWord32(m.Parameter(0));
|
||||
m.Return(m.LoadJSArrayElementsMap(kind, native_context));
|
||||
}
|
||||
|
||||
FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
|
||||
for (int kind = 0; kind <= HOLEY_DOUBLE_ELEMENTS; kind++) {
|
||||
Handle<Map> csa_result =
|
||||
ft.CallChecked<Map>(handle(Smi::FromInt(kind), isolate));
|
||||
ElementsKind elements_kind = static_cast<ElementsKind>(kind);
|
||||
Handle<Map> result(
|
||||
isolate->native_context()->GetInitialJSArrayMap(elements_kind));
|
||||
CHECK_EQ(*csa_result, *result);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -29,9 +29,9 @@
|
||||
// Flags: --opt --no-always-opt --no-stress-fullcodegen
|
||||
|
||||
var elements_kind = {
|
||||
packed_smi : 'packed smi elements',
|
||||
packed : 'packed elements',
|
||||
packed_double : 'packed double elements',
|
||||
fast_smi_only : 'fast smi only elements',
|
||||
fast : 'fast elements',
|
||||
fast_double : 'fast double elements',
|
||||
dictionary : 'dictionary elements',
|
||||
external_byte : 'external byte elements',
|
||||
external_unsigned_byte : 'external unsigned byte elements',
|
||||
@ -45,9 +45,9 @@ var elements_kind = {
|
||||
}
|
||||
|
||||
function getKind(obj) {
|
||||
if (%HasSmiElements(obj)) return elements_kind.packed_smi;
|
||||
if (%HasObjectElements(obj)) return elements_kind.packed;
|
||||
if (%HasDoubleElements(obj)) return elements_kind.packed_double;
|
||||
if (%HasSmiElements(obj)) return elements_kind.fast_smi_only;
|
||||
if (%HasObjectElements(obj)) return elements_kind.fast;
|
||||
if (%HasDoubleElements(obj)) return elements_kind.fast_double;
|
||||
if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ assertOptimized(get_literal);
|
||||
|
||||
|
||||
// Test: make sure allocation site information is updated through a
|
||||
// transition from SMI->DOUBLE->PACKED
|
||||
// transition from SMI->DOUBLE->FAST
|
||||
(function() {
|
||||
function bar(a, b, c) {
|
||||
return [a, b, c];
|
||||
@ -103,132 +103,5 @@ assertOptimized(get_literal);
|
||||
a[0] = 3.5;
|
||||
a[1] = 'hi';
|
||||
b = bar(1, 2, 3);
|
||||
assertKind(elements_kind.packed, b);
|
||||
})();
|
||||
|
||||
|
||||
(function changeOptimizedEmptyArrayKind() {
|
||||
function f() {
|
||||
return new Array();
|
||||
}
|
||||
var a = f();
|
||||
assertKind('packed smi elements', a);
|
||||
a = f();
|
||||
assertKind('packed smi elements', a);
|
||||
a = f();
|
||||
a.push(0.5);
|
||||
assertKind('packed double elements', a);
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
a = f();
|
||||
assertKind('packed double elements', a);
|
||||
})();
|
||||
|
||||
(function changeOptimizedArrayLiteralKind() {
|
||||
function f() {
|
||||
return [1, 2];
|
||||
}
|
||||
var a = f();
|
||||
assertKind('packed smi elements', a);
|
||||
|
||||
a = f();
|
||||
a.push(0.5);
|
||||
assertKind('packed double elements', a);
|
||||
|
||||
a = f();
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
a.push(undefined);
|
||||
assertKind('packed elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
|
||||
a = f();
|
||||
assertKind('packed elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
})();
|
||||
|
||||
(function changeOptimizedEmptyArrayLiteralKind() {
|
||||
function f() {
|
||||
return [];
|
||||
}
|
||||
var a = f();
|
||||
assertKind('packed smi elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
a.push(0.5);
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
|
||||
a = f();
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
})();
|
||||
|
||||
(function changeEmptyArrayLiteralKind2() {
|
||||
function f() {
|
||||
var literal = [];
|
||||
%HeapObjectVerify(literal);
|
||||
return literal;
|
||||
}
|
||||
var a = f();
|
||||
assertKind('packed smi elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
a.push(0.5);
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed double elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
a.push(undefined);
|
||||
assertKind('packed elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
a[10] = 1;
|
||||
assertKind('packed elements', a);
|
||||
assertTrue(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed elements', a);
|
||||
assertTrue(isHoley(a));
|
||||
|
||||
a = f();
|
||||
a[10000] = 1;
|
||||
assertKind('dictionary elements', a);
|
||||
assertFalse(isHoley(a));
|
||||
|
||||
a = f();
|
||||
assertKind('packed elements', a);
|
||||
assertTrue(isHoley(a));
|
||||
assertKind(elements_kind.fast, b);
|
||||
})();
|
||||
|
@ -147,7 +147,7 @@ array = deopt_array_literal_all_smis(4);
|
||||
assertEquals(0, array[0]);
|
||||
assertEquals(1, array[1]);
|
||||
assertEquals(4, array[2]);
|
||||
%OptimizeFunctionOnNextCall(deopt_array_literal_all_smis);
|
||||
%OptimizeFunctionOnNextCall(deopt_array_literal_all_smis);
|
||||
array = deopt_array_literal_all_smis(5);
|
||||
array = deopt_array_literal_all_smis(6);
|
||||
assertOptimized(deopt_array_literal_all_smis);
|
||||
@ -172,7 +172,7 @@ array = deopt_array_literal_all_doubles(0.5);
|
||||
assertEquals(0.5, array[0]);
|
||||
assertEquals(1, array[1]);
|
||||
assertEquals(0.5, array[2]);
|
||||
%OptimizeFunctionOnNextCall(deopt_array_literal_all_doubles);
|
||||
%OptimizeFunctionOnNextCall(deopt_array_literal_all_doubles);
|
||||
array = deopt_array_literal_all_doubles(5);
|
||||
array = deopt_array_literal_all_doubles(6);
|
||||
assertOptimized(deopt_array_literal_all_doubles);
|
||||
|
@ -351,7 +351,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
builder
|
||||
.CreateRegExpLiteral(ast_factory.GetOneByteString("wide_literal"), 0, 0)
|
||||
.CreateArrayLiteral(0, 0, 0)
|
||||
.CreateEmptyArrayLiteral(0)
|
||||
.CreateObjectLiteral(0, 0, 0, reg);
|
||||
|
||||
// Emit load and store operations for module variables.
|
||||
|
Loading…
Reference in New Issue
Block a user