[interpreter][runtime] Avoid AllocationSites for oneshot code

No need to create allocation site for literals in oneshot code since
they are executed only once. The interpreter emits a runtime call to
CreateObjectLiteralWithoutAllocationSite for creating literals in
oneshot code instead.

Change-Id: I224b3a30f10361cfe9ff63129b36da8230c5e403
Reviewed-on: https://chromium-review.googlesource.com/1163615
Commit-Queue: Chandan Reddy <chandanreddy@google.com>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55050}
This commit is contained in:
Creddy 2018-08-10 14:41:06 +02:00 committed by Commit Bot
parent b321c95b10
commit ec8700c418
16 changed files with 398 additions and 296 deletions

View File

@ -255,112 +255,113 @@ namespace {
bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
// Use macro to include both inlined and non-inlined version of an intrinsic.
#define INTRINSIC_WHITELIST(V) \
/* Conversions */ \
V(NumberToStringSkipCache) \
V(ToBigInt) \
V(ToInteger) \
V(ToLength) \
V(ToNumber) \
V(ToObject) \
V(ToString) \
/* Type checks */ \
V(IsArray) \
V(IsDate) \
V(IsFunction) \
V(IsJSProxy) \
V(IsJSReceiver) \
V(IsJSWeakMap) \
V(IsJSWeakSet) \
V(IsRegExp) \
V(IsSmi) \
V(IsTypedArray) \
/* Loads */ \
V(LoadLookupSlotForCall) \
V(GetProperty) \
/* Arrays */ \
V(ArraySpeciesConstructor) \
V(EstimateNumberOfElements) \
V(GetArrayKeys) \
V(HasComplexElements) \
V(HasFastPackedElements) \
V(NewArray) \
V(NormalizeElements) \
V(PrepareElementsForSort) \
V(TrySliceSimpleNonFastElements) \
V(TypedArrayGetBuffer) \
/* Errors */ \
V(NewTypeError) \
V(ReThrow) \
V(ThrowCalledNonCallable) \
V(ThrowInvalidStringLength) \
V(ThrowIteratorResultNotAnObject) \
V(ThrowReferenceError) \
V(ThrowSymbolIteratorInvalid) \
/* Strings */ \
V(RegExpInternalReplace) \
V(StringIncludes) \
V(StringIndexOf) \
V(StringReplaceOneCharWithString) \
V(StringSubstring) \
V(StringToNumber) \
V(StringTrim) \
/* BigInts */ \
V(BigIntEqualToBigInt) \
V(BigIntToBoolean) \
V(BigIntToNumber) \
/* Literals */ \
V(CreateArrayLiteral) \
V(CreateObjectLiteral) \
V(CreateRegExpLiteral) \
/* Called from builtins */ \
V(AllocateInNewSpace) \
V(AllocateInTargetSpace) \
V(AllocateSeqOneByteString) \
V(AllocateSeqTwoByteString) \
V(ArrayIncludes_Slow) \
V(ArrayIndexOf) \
V(ArrayIsArray) \
V(ClassOf) \
V(GenerateRandomNumbers) \
V(GetFunctionName) \
V(GetOwnPropertyDescriptor) \
V(GlobalPrint) \
V(HasProperty) \
V(ObjectCreate) \
V(ObjectEntries) \
V(ObjectEntriesSkipFastPath) \
V(ObjectHasOwnProperty) \
V(ObjectValues) \
V(ObjectValuesSkipFastPath) \
V(ObjectGetOwnPropertyNames) \
V(ObjectGetOwnPropertyNamesTryFast) \
V(RegExpInitializeAndCompile) \
V(StackGuard) \
V(StringAdd) \
V(StringCharCodeAt) \
V(StringEqual) \
V(StringIndexOfUnchecked) \
V(StringParseFloat) \
V(StringParseInt) \
V(SymbolDescriptiveString) \
V(ThrowRangeError) \
V(ThrowTypeError) \
V(ToName) \
V(TransitionElementsKind) \
/* Misc. */ \
V(Call) \
V(CompleteInobjectSlackTrackingForMap) \
V(HasInPrototypeChain) \
V(MaxSmi) \
V(NewObject) \
V(SmiLexicographicCompare) \
V(StringMaxLength) \
V(StringToArray) \
/* Test */ \
V(GetOptimizationStatus) \
V(OptimizeFunctionOnNextCall) \
V(OptimizeOsr) \
#define INTRINSIC_WHITELIST(V) \
/* Conversions */ \
V(NumberToStringSkipCache) \
V(ToBigInt) \
V(ToInteger) \
V(ToLength) \
V(ToNumber) \
V(ToObject) \
V(ToString) \
/* Type checks */ \
V(IsArray) \
V(IsDate) \
V(IsFunction) \
V(IsJSProxy) \
V(IsJSReceiver) \
V(IsJSWeakMap) \
V(IsJSWeakSet) \
V(IsRegExp) \
V(IsSmi) \
V(IsTypedArray) \
/* Loads */ \
V(LoadLookupSlotForCall) \
V(GetProperty) \
/* Arrays */ \
V(ArraySpeciesConstructor) \
V(EstimateNumberOfElements) \
V(GetArrayKeys) \
V(HasComplexElements) \
V(HasFastPackedElements) \
V(NewArray) \
V(NormalizeElements) \
V(PrepareElementsForSort) \
V(TrySliceSimpleNonFastElements) \
V(TypedArrayGetBuffer) \
/* Errors */ \
V(NewTypeError) \
V(ReThrow) \
V(ThrowCalledNonCallable) \
V(ThrowInvalidStringLength) \
V(ThrowIteratorResultNotAnObject) \
V(ThrowReferenceError) \
V(ThrowSymbolIteratorInvalid) \
/* Strings */ \
V(RegExpInternalReplace) \
V(StringIncludes) \
V(StringIndexOf) \
V(StringReplaceOneCharWithString) \
V(StringSubstring) \
V(StringToNumber) \
V(StringTrim) \
/* BigInts */ \
V(BigIntEqualToBigInt) \
V(BigIntToBoolean) \
V(BigIntToNumber) \
/* Literals */ \
V(CreateArrayLiteral) \
V(CreateObjectLiteral) \
V(CreateObjectLiteralWithoutAllocationSite) \
V(CreateRegExpLiteral) \
/* Called from builtins */ \
V(AllocateInNewSpace) \
V(AllocateInTargetSpace) \
V(AllocateSeqOneByteString) \
V(AllocateSeqTwoByteString) \
V(ArrayIncludes_Slow) \
V(ArrayIndexOf) \
V(ArrayIsArray) \
V(ClassOf) \
V(GenerateRandomNumbers) \
V(GetFunctionName) \
V(GetOwnPropertyDescriptor) \
V(GlobalPrint) \
V(HasProperty) \
V(ObjectCreate) \
V(ObjectEntries) \
V(ObjectEntriesSkipFastPath) \
V(ObjectHasOwnProperty) \
V(ObjectValues) \
V(ObjectValuesSkipFastPath) \
V(ObjectGetOwnPropertyNames) \
V(ObjectGetOwnPropertyNamesTryFast) \
V(RegExpInitializeAndCompile) \
V(StackGuard) \
V(StringAdd) \
V(StringCharCodeAt) \
V(StringEqual) \
V(StringIndexOfUnchecked) \
V(StringParseFloat) \
V(StringParseInt) \
V(SymbolDescriptiveString) \
V(ThrowRangeError) \
V(ThrowTypeError) \
V(ToName) \
V(TransitionElementsKind) \
/* Misc. */ \
V(Call) \
V(CompleteInobjectSlackTrackingForMap) \
V(HasInPrototypeChain) \
V(MaxSmi) \
V(NewObject) \
V(SmiLexicographicCompare) \
V(StringMaxLength) \
V(StringToArray) \
/* Test */ \
V(GetOptimizationStatus) \
V(OptimizeFunctionOnNextCall) \
V(OptimizeOsr) \
V(UnblockConcurrentRecompilation)
#define CASE(Name) \

View File

@ -316,7 +316,7 @@ DEFINE_BOOL(optimize_for_size, false,
"speed")
// Flag for one shot optimiztions.
DEFINE_BOOL(enable_one_shot_optimization, true,
DEFINE_BOOL(enable_one_shot_optimization, false,
"Enable size optimizations for the code that will "
"only be executed once")

View File

@ -2105,6 +2105,27 @@ void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
expr->flags());
}
void BytecodeGenerator::BuildCreateObjectLiteral(Register literal,
uint8_t flags, size_t entry) {
if (ShouldOptimizeAsOneShot()) {
RegisterList args = register_allocator()->NewRegisterList(2);
builder()
->LoadConstantPoolEntry(entry)
.StoreAccumulatorInRegister(args[0])
.LoadLiteral(Smi::FromInt(flags))
.StoreAccumulatorInRegister(args[1])
.CallRuntime(Runtime::kCreateObjectLiteralWithoutAllocationSite, args)
.StoreAccumulatorInRegister(literal);
} else {
// TODO(cbruni): Directly generate runtime call for literals we cannot
// optimize once the CreateShallowObjectLiteral stub is in sync with the TF
// optimizations.
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
builder()->CreateObjectLiteral(entry, literal_index, flags, literal);
}
}
void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
expr->InitDepthAndFlags();
@ -2155,11 +2176,7 @@ void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
entry = builder()->AllocateDeferredConstantPoolEntry();
object_literals_.push_back(std::make_pair(expr, entry));
}
// TODO(cbruni): Directly generate runtime call for literals we cannot
// optimize once the CreateShallowObjectLiteral stub is in sync with the TF
// optimizations.
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
builder()->CreateObjectLiteral(entry, literal_index, flags, literal);
BuildCreateObjectLiteral(literal, flags, entry);
}
// Store computed values into the literal.

View File

@ -187,6 +187,7 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
ZonePtrList<Expression>* elements,
bool skip_constants);
void BuildCreateObjectLiteral(Register literal, uint8_t flags, size_t entry);
void AllocateTopLevelRegisters();
void VisitArgumentsObject(Variable* variable);
void VisitRestArgumentsArray(Variable* rest);

View File

@ -316,7 +316,7 @@ MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
return copy;
}
struct ObjectBoilerplate {
struct ObjectLiteralHelper {
static Handle<JSObject> Create(Isolate* isolate,
Handle<HeapObject> description, int flags,
PretenureFlag pretenure_flag) {
@ -391,7 +391,7 @@ struct ObjectBoilerplate {
}
};
struct ArrayBoilerplate {
struct ArrayLiteralHelper {
static Handle<JSObject> Create(Isolate* isolate,
Handle<HeapObject> description, int flags,
PretenureFlag pretenure_flag) {
@ -454,20 +454,43 @@ Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
if (description->IsObjectBoilerplateDescription()) {
Handle<ObjectBoilerplateDescription> object_boilerplate_description =
Handle<ObjectBoilerplateDescription>::cast(description);
return ObjectBoilerplate::Create(isolate, object_boilerplate_description,
object_boilerplate_description->flags(),
pretenure_flag);
return ObjectLiteralHelper::Create(isolate, object_boilerplate_description,
object_boilerplate_description->flags(),
pretenure_flag);
} else {
DCHECK(description->IsArrayBoilerplateDescription());
Handle<ArrayBoilerplateDescription> array_boilerplate_description =
Handle<ArrayBoilerplateDescription>::cast(description);
return ArrayBoilerplate::Create(
return ArrayLiteralHelper::Create(
isolate, array_boilerplate_description,
array_boilerplate_description->elements_kind(), pretenure_flag);
}
}
template <typename Boilerplate>
inline DeepCopyHints DecodeCopyHints(int flags) {
DeepCopyHints copy_hints =
(flags & AggregateLiteral::kIsShallow) ? kObjectIsShallow : kNoHints;
if (FLAG_track_double_fields && !FLAG_unbox_double_fields) {
// Make sure we properly clone mutable heap numbers on 32-bit platforms.
copy_hints = kNoHints;
}
return copy_hints;
}
template <typename LiteralHelper>
MaybeHandle<JSObject> CreateLiteralWithoutAllocationSite(
Isolate* isolate, Handle<HeapObject> description, int flags) {
Handle<JSObject> literal =
LiteralHelper::Create(isolate, description, flags, NOT_TENURED);
DeepCopyHints copy_hints = DecodeCopyHints(flags);
if (copy_hints == kNoHints) {
DeprecationUpdateContext update_context(isolate);
RETURN_ON_EXCEPTION(isolate, DeepWalk(literal, &update_context), JSObject);
}
return literal;
}
template <typename LiteralHelper>
MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
Handle<FeedbackVector> vector,
int literals_index,
@ -475,12 +498,7 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
FeedbackSlot literals_slot(FeedbackVector::ToSlot(literals_index));
CHECK(literals_slot.ToInt() < vector->length());
Handle<Object> literal_site(vector->Get(literals_slot)->ToObject(), isolate);
DeepCopyHints copy_hints =
(flags & AggregateLiteral::kIsShallow) ? kObjectIsShallow : kNoHints;
if (FLAG_track_double_fields && !FLAG_unbox_double_fields) {
// Make sure we properly clone mutable heap numbers on 32-bit platforms.
copy_hints = kNoHints;
}
DeepCopyHints copy_hints = DecodeCopyHints(flags);
Handle<AllocationSite> site;
Handle<JSObject> boilerplate;
@ -492,21 +510,13 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
// Eagerly create AllocationSites for literals that contain an Array.
bool needs_initial_allocation_site =
(flags & AggregateLiteral::kNeedsInitialAllocationSite) != 0;
// 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)) {
PreInitializeLiteralSite(vector, literals_slot);
boilerplate =
Boilerplate::Create(isolate, description, flags, NOT_TENURED);
if (copy_hints == kNoHints) {
DeprecationUpdateContext update_context(isolate);
RETURN_ON_EXCEPTION(isolate, DeepWalk(boilerplate, &update_context),
JSObject);
}
return boilerplate;
return CreateLiteralWithoutAllocationSite<LiteralHelper>(
isolate, description, flags);
} else {
boilerplate = Boilerplate::Create(isolate, description, flags, TENURED);
boilerplate = LiteralHelper::Create(isolate, description, flags, TENURED);
}
// Install AllocationSite objects.
AllocationSiteCreationContext creation_context(isolate);
@ -540,8 +550,18 @@ RUNTIME_FUNCTION(Runtime_CreateObjectLiteral) {
CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteral<ObjectBoilerplate>(isolate, vector, literals_index,
description, flags));
isolate, CreateLiteral<ObjectLiteralHelper>(
isolate, vector, literals_index, description, flags));
}
RUNTIME_FUNCTION(Runtime_CreateObjectLiteralWithoutAllocationSite) {
HandleScope scope(isolate);
DCHECK_EQ(2, args.length());
CONVERT_ARG_HANDLE_CHECKED(ObjectBoilerplateDescription, description, 0);
CONVERT_SMI_ARG_CHECKED(flags, 1);
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteralWithoutAllocationSite<ObjectLiteralHelper>(
isolate, description, flags));
}
RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
@ -552,8 +572,8 @@ RUNTIME_FUNCTION(Runtime_CreateArrayLiteral) {
CONVERT_ARG_HANDLE_CHECKED(ArrayBoilerplateDescription, elements, 2);
CONVERT_SMI_ARG_CHECKED(flags, 3);
RETURN_RESULT_OR_FAILURE(
isolate, CreateLiteral<ArrayBoilerplate>(isolate, vector, literals_index,
elements, flags));
isolate, CreateLiteral<ArrayLiteralHelper>(
isolate, vector, literals_index, elements, flags));
}
RUNTIME_FUNCTION(Runtime_CreateRegExpLiteral) {

View File

@ -282,9 +282,10 @@ namespace internal {
F(Typeof, 1, 1) \
F(UnwindAndFindExceptionHandler, 0, 1)
#define FOR_EACH_INTRINSIC_LITERALS(F) \
F(CreateArrayLiteral, 4, 1) \
F(CreateObjectLiteral, 4, 1) \
#define FOR_EACH_INTRINSIC_LITERALS(F) \
F(CreateArrayLiteral, 4, 1) \
F(CreateObjectLiteral, 4, 1) \
F(CreateObjectLiteralWithoutAllocationSite, 2, 1) \
F(CreateRegExpLiteral, 4, 1)
#define FOR_EACH_INTRINSIC_MATHS(F) F(GenerateRandomNumbers, 0, 1)

View File

@ -3678,6 +3678,7 @@ TEST(AllocationSiteCreation) {
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
HandleScope scope(isolate);
i::FLAG_enable_one_shot_optimization = true;
// Array literals.
CheckNumberOfAllocations(heap, "(function f1() { return []; })()", 1, 0);
@ -3727,6 +3728,52 @@ TEST(AllocationSiteCreation) {
// No new AllocationSites created on the second invocation.
CheckNumberOfAllocations(heap, "f9(); ", 0, 0);
// No allocation sites for literals in an iife/top level code even if it has
// array subliterals
CheckNumberOfAllocations(heap,
R"(
(function f10() {
return {a: [1], b: [2]};
})();
)",
0, 0);
CheckNumberOfAllocations(heap,
R"(
l = {
a: 1,
b: {
c: [5],
}
};
)",
0, 0);
// Eagerly create allocation sites for literals within a loop of iife or
// top-level code
CheckNumberOfAllocations(heap,
R"(
(function f11() {
while(true) {
return {a: [1], b: [2]};
}
})();
)",
1, 2);
CheckNumberOfAllocations(heap,
R"(
for (i = 0; i < 1; ++i) {
l = {
a: 1,
b: {
c: [5],
}
};
}
)",
1, 1);
}
TEST(CellsInOptimizedCodeAreWeak) {

View File

@ -385,6 +385,7 @@ void BytecodeExpectationsPrinter::PrintExpectation(
: snippet;
i::FLAG_enable_one_shot_optimization = oneshot_opt_;
i::FLAG_compilation_cache = false;
i::Handle<i::BytecodeArray> bytecode_array;
if (module_) {
CHECK(top_level_ && !wrap_);

View File

@ -33,7 +33,7 @@ class BytecodeExpectationsPrinter final {
wrap_(true),
top_level_(false),
print_callee_(false),
oneshot_opt_(true),
oneshot_opt_(false),
test_function_name_(kDefaultTopFunctionName) {}
void PrintExpectation(std::ostream& stream, // NOLINT

View File

@ -6,6 +6,7 @@
wrap: no
top level: yes
print callee: yes
oneshot opt: yes
---
snippet: "
@ -270,15 +271,18 @@ snippet: "
"
frame size: 6
parameter count: 1
bytecode array length: 115
bytecode array length: 121
bytecodes: [
B(CreateMappedArguments),
B(Star), R(0),
/* 16 E> */ B(StackCheck),
/* 29 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 31 E> */ B(StaGlobal), U8(1), U8(1),
/* 95 S> */ B(LdaGlobal), U8(1), U8(3),
/* 29 S> */ B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaSmi), I8(41),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreateObjectLiteralWithoutAllocationSite), R(2), U8(2),
/* 31 E> */ B(StaGlobal), U8(1), U8(0),
/* 95 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaConstant), U8(2),
B(Star), R(3),
@ -286,9 +290,9 @@ bytecodes: [
/* 101 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(2), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
/* 104 E> */ B(TestLessThan), R(1), U8(5),
/* 104 E> */ B(TestLessThan), R(1), U8(4),
B(JumpIfFalse), U8(28),
/* 121 S> */ B(LdaGlobal), U8(1), U8(3),
/* 121 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
B(Star), R(4),
@ -299,9 +303,9 @@ bytecodes: [
B(Mov), R(1), R(2),
/* 126 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4),
B(Jump), U8(40),
/* 158 S> */ B(LdaGlobal), U8(1), U8(3),
/* 158 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
/* 165 E> */ B(LdaGlobal), U8(1), U8(3),
/* 165 E> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(2),
B(LdaConstant), U8(3),
B(Star), R(4),

View File

@ -6,7 +6,6 @@
wrap: no
top level: yes
print callee: yes
oneshot opt: no
---
snippet: "
@ -55,8 +54,8 @@ snippet: "
(function() {
l = {
'a': 3.3,
'b': 4.4
'a': 4.3,
'b': 3.4
};
if (l.a < 3) {
l.a = 3;

View File

@ -508,9 +508,9 @@ snippet: "
import * as foo from \"bar\"
foo.f(foo, foo.x);
"
frame size: 10
frame size: 8
parameter count: 2
bytecode array length: 103
bytecode array length: 89
bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(1),
B(LdaConstant), U8(1),
@ -537,17 +537,11 @@ bytecodes: [
/* 0 E> */ B(Throw),
B(Ldar), R(4),
/* 46 S> */ B(Return),
/* 27 S> */ B(LdaConstant), U8(4),
B(Star), R(7),
B(Mov), R(1), R(6),
/* 31 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(6), U8(2),
/* 31 S> */ B(LdaNamedProperty), R(1), U8(4), U8(0),
B(Star), R(4),
B(LdaConstant), U8(5),
B(Star), R(9),
B(Mov), R(1), R(8),
/* 42 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(8), U8(2),
/* 42 E> */ B(LdaNamedProperty), R(1), U8(5), U8(2),
B(Star), R(7),
/* 31 E> */ B(CallProperty2), R(4), R(1), R(1), R(7), U8(0),
/* 31 E> */ B(CallProperty2), R(4), R(1), R(1), R(7), U8(4),
B(Star), R(2),
/* 46 S> */ B(Return),
]

View File

@ -5,6 +5,7 @@
---
wrap: no
top level: yes
oneshot opt: yes
---
snippet: "
@ -17,32 +18,35 @@ snippet: "
v = l['a'] + l['b'];
l['b'] = 7;
l['a'] = l['b'];
"
frame size: 7
parameter count: 1
bytecode array length: 122
bytecode array length: 128
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 9 E> */ B(StaGlobal), U8(1), U8(1),
/* 60 S> */ B(LdaGlobal), U8(1), U8(4),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaSmi), I8(41),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreateObjectLiteralWithoutAllocationSite), R(2), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
/* 60 S> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(1),
B(LdaConstant), U8(2),
B(Star), R(3),
B(Mov), R(1), R(2),
/* 65 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(2), U8(2),
B(Star), R(1),
/* 73 E> */ B(LdaGlobal), U8(1), U8(4),
/* 73 E> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(2),
B(LdaConstant), U8(3),
B(Star), R(4),
B(Mov), R(2), R(3),
/* 74 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(3), U8(2),
/* 71 E> */ B(Add), R(1), U8(3),
/* 62 E> */ B(StaGlobal), U8(4), U8(6),
/* 87 S> */ B(LdaGlobal), U8(1), U8(4),
/* 71 E> */ B(Add), R(1), U8(2),
/* 62 E> */ B(StaGlobal), U8(4), U8(5),
/* 87 S> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(1),
B(LdaSmi), I8(7),
B(Star), R(4),
@ -52,9 +56,9 @@ bytecodes: [
B(Star), R(5),
B(Mov), R(1), R(2),
/* 94 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(2), U8(4),
/* 105 S> */ B(LdaGlobal), U8(1), U8(4),
/* 105 S> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(1),
/* 114 E> */ B(LdaGlobal), U8(1), U8(4),
/* 114 E> */ B(LdaGlobal), U8(1), U8(3),
B(Star), R(2),
B(LdaConstant), U8(3),
B(Star), R(4),
@ -70,7 +74,7 @@ bytecodes: [
/* 112 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(3), U8(4),
B(Mov), R(5), R(0),
B(Ldar), R(0),
/* 123 S> */ B(Return),
/* 128 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
@ -93,56 +97,59 @@ snippet: "
l['a'] = l['a'] + l['b'];
l['b'] = l['a'] + l['b'];
}
"
frame size: 4
parameter count: 1
bytecode array length: 114
bytecode array length: 120
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 9 E> */ B(StaGlobal), U8(1), U8(1),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaSmi), I8(41),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreateObjectLiteralWithoutAllocationSite), R(2), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
B(LdaUndefined),
B(Star), R(0),
/* 68 S> */ B(LdaZero),
/* 70 E> */ B(StaGlobal), U8(2), U8(3),
/* 77 S> */ B(LdaGlobal), U8(2), U8(5),
/* 70 E> */ B(StaGlobal), U8(2), U8(2),
/* 77 S> */ B(LdaGlobal), U8(2), U8(4),
B(Star), R(1),
B(LdaSmi), I8(5),
/* 77 E> */ B(TestLessThan), R(1), U8(7),
/* 77 E> */ B(TestLessThan), R(1), U8(6),
B(JumpIfFalse), U8(83),
/* 63 E> */ B(StackCheck),
/* 97 S> */ B(LdaGlobal), U8(1), U8(8),
/* 97 S> */ B(LdaGlobal), U8(1), U8(7),
B(Star), R(1),
/* 106 E> */ B(LdaGlobal), U8(1), U8(8),
/* 106 E> */ B(LdaGlobal), U8(1), U8(7),
B(Star), R(2),
/* 107 E> */ B(LdaNamedProperty), R(2), U8(3), U8(11),
/* 107 E> */ B(LdaNamedProperty), R(2), U8(3), U8(10),
B(Star), R(2),
/* 115 E> */ B(LdaGlobal), U8(1), U8(8),
/* 115 E> */ B(LdaGlobal), U8(1), U8(7),
B(Star), R(3),
/* 116 E> */ B(LdaNamedProperty), R(3), U8(4), U8(13),
/* 113 E> */ B(Add), R(2), U8(10),
/* 104 E> */ B(StaNamedProperty), R(1), U8(3), U8(15),
/* 131 S> */ B(LdaGlobal), U8(1), U8(8),
/* 116 E> */ B(LdaNamedProperty), R(3), U8(4), U8(12),
/* 113 E> */ B(Add), R(2), U8(9),
/* 104 E> */ B(StaNamedProperty), R(1), U8(3), U8(14),
/* 131 S> */ B(LdaGlobal), U8(1), U8(7),
B(Star), R(1),
/* 140 E> */ B(LdaGlobal), U8(1), U8(8),
/* 140 E> */ B(LdaGlobal), U8(1), U8(7),
B(Star), R(2),
/* 141 E> */ B(LdaNamedProperty), R(2), U8(3), U8(11),
/* 141 E> */ B(LdaNamedProperty), R(2), U8(3), U8(10),
B(Star), R(2),
/* 149 E> */ B(LdaGlobal), U8(1), U8(8),
/* 149 E> */ B(LdaGlobal), U8(1), U8(7),
B(Star), R(3),
/* 150 E> */ B(LdaNamedProperty), R(3), U8(4), U8(13),
/* 147 E> */ B(Add), R(2), U8(17),
/* 150 E> */ B(LdaNamedProperty), R(3), U8(4), U8(12),
/* 147 E> */ B(Add), R(2), U8(16),
B(Star), R(2),
/* 138 E> */ B(StaNamedProperty), R(1), U8(4), U8(18),
/* 138 E> */ B(StaNamedProperty), R(1), U8(4), U8(17),
B(Mov), R(2), R(0),
/* 84 S> */ B(LdaGlobal), U8(2), U8(5),
B(Inc), U8(20),
/* 84 E> */ B(StaGlobal), U8(2), U8(3),
/* 84 S> */ B(LdaGlobal), U8(2), U8(4),
B(Inc), U8(19),
/* 84 E> */ B(StaGlobal), U8(2), U8(2),
B(JumpLoop), U8(90), I8(0),
B(Ldar), R(0),
/* 166 S> */ B(Return),
/* 171 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
@ -165,52 +172,55 @@ snippet: "
l['a'] = l['a'] - l['b'];
l['b'] = l['b'] - l['a'];
}
"
frame size: 4
parameter count: 1
bytecode array length: 103
bytecode array length: 109
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 9 E> */ B(StaGlobal), U8(1), U8(1),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaSmi), I8(41),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreateObjectLiteralWithoutAllocationSite), R(2), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
B(LdaUndefined),
B(Star), R(0),
/* 72 S> */ B(LdaGlobal), U8(2), U8(3),
/* 72 S> */ B(LdaGlobal), U8(2), U8(2),
B(Star), R(1),
B(LdaZero),
/* 72 E> */ B(TestGreaterThan), R(1), U8(5),
/* 72 E> */ B(TestGreaterThan), R(1), U8(4),
B(JumpIfFalse), U8(77),
/* 63 E> */ B(StackCheck),
/* 87 S> */ B(LdaGlobal), U8(1), U8(6),
/* 87 S> */ B(LdaGlobal), U8(1), U8(5),
B(Star), R(1),
/* 97 E> */ B(LdaGlobal), U8(1), U8(6),
/* 97 E> */ B(LdaGlobal), U8(1), U8(5),
B(Star), R(2),
/* 98 E> */ B(LdaNamedProperty), R(2), U8(3), U8(9),
/* 98 E> */ B(LdaNamedProperty), R(2), U8(3), U8(8),
B(Star), R(2),
/* 106 E> */ B(LdaGlobal), U8(1), U8(6),
/* 106 E> */ B(LdaGlobal), U8(1), U8(5),
B(Star), R(3),
/* 107 E> */ B(LdaNamedProperty), R(3), U8(4), U8(11),
/* 104 E> */ B(Sub), R(2), U8(8),
/* 95 E> */ B(StaNamedProperty), R(1), U8(3), U8(13),
/* 122 S> */ B(LdaGlobal), U8(1), U8(6),
/* 107 E> */ B(LdaNamedProperty), R(3), U8(4), U8(10),
/* 104 E> */ B(Sub), R(2), U8(7),
/* 95 E> */ B(StaNamedProperty), R(1), U8(3), U8(12),
/* 122 S> */ B(LdaGlobal), U8(1), U8(5),
B(Star), R(1),
/* 132 E> */ B(LdaGlobal), U8(1), U8(6),
/* 132 E> */ B(LdaGlobal), U8(1), U8(5),
B(Star), R(2),
/* 133 E> */ B(LdaNamedProperty), R(2), U8(4), U8(11),
/* 133 E> */ B(LdaNamedProperty), R(2), U8(4), U8(10),
B(Star), R(2),
/* 141 E> */ B(LdaGlobal), U8(1), U8(6),
/* 141 E> */ B(LdaGlobal), U8(1), U8(5),
B(Star), R(3),
/* 142 E> */ B(LdaNamedProperty), R(3), U8(3), U8(9),
/* 139 E> */ B(Sub), R(2), U8(15),
/* 142 E> */ B(LdaNamedProperty), R(3), U8(3), U8(8),
/* 139 E> */ B(Sub), R(2), U8(14),
B(Star), R(2),
/* 130 E> */ B(StaNamedProperty), R(1), U8(4), U8(16),
/* 130 E> */ B(StaNamedProperty), R(1), U8(4), U8(15),
B(Mov), R(2), R(0),
B(Ldar), R(2),
B(JumpLoop), U8(83), I8(0),
B(Ldar), R(0),
/* 158 S> */ B(Return),
/* 163 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
@ -233,42 +243,45 @@ snippet: "
do {
l['a'] = l['b'] - l['a'];
} while (s < 10);
"
frame size: 4
parameter count: 1
bytecode array length: 75
bytecode array length: 81
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 9 E> */ B(StaGlobal), U8(1), U8(1),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaSmi), I8(41),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreateObjectLiteralWithoutAllocationSite), R(2), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
/* 63 S> */ B(LdaSmi), I8(10),
/* 65 E> */ B(StaGlobal), U8(2), U8(3),
/* 65 E> */ B(StaGlobal), U8(2), U8(2),
B(LdaUndefined),
B(Star), R(0),
/* 77 E> */ B(StackCheck),
/* 90 S> */ B(LdaGlobal), U8(1), U8(5),
/* 90 S> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(1),
/* 99 E> */ B(LdaGlobal), U8(1), U8(5),
/* 99 E> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(2),
/* 100 E> */ B(LdaNamedProperty), R(2), U8(3), U8(8),
/* 100 E> */ B(LdaNamedProperty), R(2), U8(3), U8(7),
B(Star), R(2),
/* 108 E> */ B(LdaGlobal), U8(1), U8(5),
/* 108 E> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(3),
/* 109 E> */ B(LdaNamedProperty), R(3), U8(4), U8(10),
/* 106 E> */ B(Sub), R(2), U8(7),
/* 109 E> */ B(LdaNamedProperty), R(3), U8(4), U8(9),
/* 106 E> */ B(Sub), R(2), U8(6),
B(Star), R(2),
/* 97 E> */ B(StaNamedProperty), R(1), U8(4), U8(12),
/* 97 E> */ B(StaNamedProperty), R(1), U8(4), U8(11),
B(Mov), R(2), R(0),
/* 133 S> */ B(LdaGlobal), U8(2), U8(14),
/* 133 S> */ B(LdaGlobal), U8(2), U8(13),
B(Star), R(1),
B(LdaSmi), I8(10),
/* 133 E> */ B(TestLessThan), R(1), U8(16),
/* 133 E> */ B(TestLessThan), R(1), U8(15),
B(JumpIfFalse), U8(5),
B(JumpLoop), U8(50), I8(0),
B(Ldar), R(0),
/* 141 S> */ B(Return),
/* 146 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
@ -284,35 +297,38 @@ handlers: [
snippet: "
l = {
'cc': 3.1,
'dd': 4.2
'c': 1.1,
'd': 2.2
};
if (l['cc'] < 3) {
l['cc'] = 3;
if (l['c'] < 3) {
l['c'] = 3;
} else {
l['dd'] = 3;
l['d'] = 3;
}
"
frame size: 7
parameter count: 1
bytecode array length: 105
bytecode array length: 111
bytecodes: [
/* 0 E> */ B(StackCheck),
/* 7 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 9 E> */ B(StaGlobal), U8(1), U8(1),
/* 65 S> */ B(LdaGlobal), U8(1), U8(3),
/* 7 S> */ B(LdaConstant), U8(0),
B(Star), R(2),
B(LdaSmi), I8(41),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kCreateObjectLiteralWithoutAllocationSite), R(2), U8(2),
/* 9 E> */ B(StaGlobal), U8(1), U8(0),
/* 63 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaConstant), U8(2),
B(Star), R(3),
B(Mov), R(1), R(2),
/* 70 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(2), U8(2),
/* 68 E> */ B(InvokeIntrinsic), U8(Runtime::k_GetProperty), R(2), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
/* 77 E> */ B(TestLessThan), R(1), U8(5),
/* 74 E> */ B(TestLessThan), R(1), U8(4),
B(JumpIfFalse), U8(36),
/* 92 S> */ B(LdaGlobal), U8(1), U8(3),
/* 89 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
B(Star), R(2),
@ -322,11 +338,11 @@ bytecodes: [
B(Star), R(6),
B(Mov), R(1), R(3),
B(Mov), R(2), R(5),
/* 100 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(3), U8(4),
/* 96 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(3), U8(4),
B(Mov), R(5), R(0),
B(Ldar), R(2),
B(Jump), U8(34),
/* 128 S> */ B(LdaGlobal), U8(1), U8(3),
/* 124 S> */ B(LdaGlobal), U8(1), U8(2),
B(Star), R(1),
B(LdaSmi), I8(3),
B(Star), R(2),
@ -336,17 +352,17 @@ bytecodes: [
B(Star), R(6),
B(Mov), R(1), R(3),
B(Mov), R(2), R(5),
/* 136 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(3), U8(4),
/* 131 E> */ B(CallRuntime), U16(Runtime::kSetProperty), R(3), U8(4),
B(Mov), R(5), R(0),
B(Ldar), R(2),
B(Ldar), R(0),
/* 156 S> */ B(Return),
/* 150 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["l"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["cc"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["dd"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["c"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["d"],
]
handlers: [
]

View File

@ -5,20 +5,19 @@
---
wrap: no
top level: yes
oneshot opt: no
---
snippet: "
l = {
'a': 1.1,
'b': 2.2
'aa': 1.1,
'bb': 2.2
};
v = l['a'] + l['b'];
l['b'] = 7;
l['a'] = l['b'];
v = l['aa'] + l['bb'];
l['bb'] = 7;
l['aa'] = l['bb'];
"
frame size: 3
parameter count: 1
@ -28,35 +27,35 @@ bytecodes: [
/* 7 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(41), R(1),
B(Ldar), R(1),
/* 9 E> */ B(StaGlobal), U8(1), U8(1),
/* 64 S> */ B(LdaGlobal), U8(1), U8(4),
/* 66 S> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(1),
/* 69 E> */ B(LdaNamedProperty), R(1), U8(2), U8(6),
/* 71 E> */ B(LdaNamedProperty), R(1), U8(2), U8(6),
B(Star), R(1),
/* 77 E> */ B(LdaGlobal), U8(1), U8(4),
/* 80 E> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(2),
/* 78 E> */ B(LdaNamedProperty), R(2), U8(3), U8(8),
/* 75 E> */ B(Add), R(1), U8(3),
/* 66 E> */ B(StaGlobal), U8(4), U8(10),
/* 91 S> */ B(LdaGlobal), U8(1), U8(4),
/* 81 E> */ B(LdaNamedProperty), R(2), U8(3), U8(8),
/* 78 E> */ B(Add), R(1), U8(3),
/* 68 E> */ B(StaGlobal), U8(4), U8(10),
/* 95 S> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(1),
B(LdaSmi), I8(7),
/* 98 E> */ B(StaNamedProperty), R(1), U8(3), U8(12),
/* 109 S> */ B(LdaGlobal), U8(1), U8(4),
/* 103 E> */ B(StaNamedProperty), R(1), U8(3), U8(12),
/* 114 S> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(1),
/* 118 E> */ B(LdaGlobal), U8(1), U8(4),
/* 124 E> */ B(LdaGlobal), U8(1), U8(4),
B(Star), R(2),
/* 119 E> */ B(LdaNamedProperty), R(2), U8(3), U8(8),
/* 125 E> */ B(LdaNamedProperty), R(2), U8(3), U8(8),
B(Star), R(2),
/* 116 E> */ B(StaNamedProperty), R(1), U8(2), U8(14),
/* 122 E> */ B(StaNamedProperty), R(1), U8(2), U8(14),
B(Mov), R(2), R(0),
B(Ldar), R(0),
/* 127 S> */ B(Return),
/* 139 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,
ONE_BYTE_INTERNALIZED_STRING_TYPE ["l"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["b"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["aa"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["bb"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["v"],
]
handlers: [
@ -66,15 +65,15 @@ handlers: [
snippet: "
l = {
'cc': 1.1,
'dd': 2.2
'cc': 3.1,
'dd': 4.2
};
if (l['cc'] < 3) {
l['cc'] = 3;
} else {
l['dd'] = 3;
}
"
frame size: 3
parameter count: 1
@ -107,7 +106,7 @@ bytecodes: [
B(Mov), R(2), R(0),
B(Ldar), R(2),
B(Ldar), R(0),
/* 156 S> */ B(Return),
/* 155 S> */ B(Return),
]
constant pool: [
OBJECT_BOILERPLATE_DESCRIPTION_TYPE,

View File

@ -43,7 +43,7 @@ class ProgramOptions final {
module_(false),
top_level_(false),
print_callee_(false),
oneshot_opt_(true),
oneshot_opt_(false),
do_expressions_(false),
async_iteration_(false),
public_fields_(false),
@ -332,7 +332,7 @@ void ProgramOptions::PrintHeader(std::ostream& stream) const { // NOLINT
if (module_) stream << "\nmodule: yes";
if (top_level_) stream << "\ntop level: yes";
if (print_callee_) stream << "\nprint callee: yes";
if (!oneshot_opt_) stream << "\noneshot opt: no";
if (oneshot_opt_) stream << "\noneshot opt: yes";
if (do_expressions_) stream << "\ndo expressions: yes";
if (async_iteration_) stream << "\nasync iteration: yes";
if (public_fields_) stream << "\npublic fields: yes";

View File

@ -138,8 +138,9 @@ static inline void ltrim(std::string& str) {
// inplace right trim
static inline void rtrim(std::string& str) {
str.erase(std::find_if(str.begin(), str.end(),
[](unsigned char ch) { return !std::isspace(ch); }),
str.erase(std::find_if(str.rbegin(), str.rend(),
[](unsigned char ch) { return !std::isspace(ch); })
.base(),
str.end());
}
@ -436,6 +437,8 @@ TEST(PropertyLoadStoreOneShot) {
BytecodeExpectationsPrinter printer(CcTest::isolate());
printer.set_wrap(false);
printer.set_top_level(true);
printer.set_oneshot_opt(true);
const char* snippets[] = {
R"(
l = {
@ -502,7 +505,6 @@ TEST(PropertyLoadStoreWithoutOneShot) {
BytecodeExpectationsPrinter printer(CcTest::isolate());
printer.set_wrap(false);
printer.set_top_level(true);
printer.set_oneshot_opt(false);
const char* snippets[] = {
R"(
@ -539,6 +541,7 @@ TEST(IIFEWithOneshotOpt) {
printer.set_wrap(false);
printer.set_top_level(true);
printer.set_print_callee(true);
printer.set_oneshot_opt(true);
const char* snippets[] = {
// No feedback vectors for top-level loads/store named property in an IIFE
@ -614,7 +617,6 @@ TEST(IIFEWithoutOneshotOpt) {
printer.set_wrap(false);
printer.set_top_level(true);
printer.set_print_callee(true);
printer.set_oneshot_opt(false);
const char* snippets[] = {
R"(