[runtime] Enable double-lazy boilerplate creation again
This mostly reverts commit c503b80595
but fixes
an issue where literals would always be pretenured on first instantiation.
As a cleanup we pass in a PretenureFlag instead of using the FeedbackVector as
indicator.
Bug: v8:6211
Change-Id: Id328552620e33f5083519bcba1e24396d162d516
Reviewed-on: https://chromium-review.googlesource.com/555670
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46342}
This commit is contained in:
parent
eeeae375b9
commit
bbc89774a6
@ -46,6 +46,7 @@ void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT
|
||||
os << map()->instance_type();
|
||||
}
|
||||
os << "]";
|
||||
if (GetHeap()->InOldSpace(this)) os << " in OldSpace";
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,8 +30,8 @@ void PreInitializeLiteralSite(Handle<FeedbackVector> vector,
|
||||
}
|
||||
|
||||
Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
|
||||
Handle<FeedbackVector> vector,
|
||||
Handle<FixedArray> compile_time_value);
|
||||
Handle<FixedArray> compile_time_value,
|
||||
PretenureFlag pretenure_flag);
|
||||
|
||||
enum DeepCopyHints { kNoHints = 0, kObjectIsShallow = 1 };
|
||||
|
||||
@ -207,6 +207,25 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
||||
return copy;
|
||||
}
|
||||
|
||||
class DeprecationUpdateContext {
|
||||
public:
|
||||
explicit DeprecationUpdateContext(Isolate* isolate) { isolate_ = isolate; }
|
||||
Isolate* isolate() { return isolate_; }
|
||||
bool ShouldCreateMemento(Handle<JSObject> object) { return false; }
|
||||
inline void ExitScope(Handle<AllocationSite> scope_site,
|
||||
Handle<JSObject> object) {}
|
||||
Handle<AllocationSite> EnterNewScope() { return Handle<AllocationSite>(); }
|
||||
Handle<AllocationSite> current() {
|
||||
UNREACHABLE();
|
||||
return Handle<AllocationSite>();
|
||||
}
|
||||
|
||||
static const bool kCopying = false;
|
||||
|
||||
private:
|
||||
Isolate* isolate_;
|
||||
};
|
||||
|
||||
// AllocationSiteCreationContext aids in the creation of AllocationSites to
|
||||
// accompany object literals.
|
||||
class AllocationSiteCreationContext : public AllocationSiteContext {
|
||||
@ -258,6 +277,15 @@ class AllocationSiteCreationContext : public AllocationSiteContext {
|
||||
static const bool kCopying = false;
|
||||
};
|
||||
|
||||
MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
|
||||
DeprecationUpdateContext* site_context) {
|
||||
JSObjectWalkVisitor<DeprecationUpdateContext> v(site_context, kNoHints);
|
||||
MaybeHandle<JSObject> result = v.StructureWalk(object);
|
||||
Handle<JSObject> for_assert;
|
||||
DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
|
||||
return result;
|
||||
}
|
||||
|
||||
MaybeHandle<JSObject> DeepWalk(Handle<JSObject> object,
|
||||
AllocationSiteCreationContext* site_context) {
|
||||
JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, kNoHints);
|
||||
@ -279,8 +307,8 @@ MaybeHandle<JSObject> DeepCopy(Handle<JSObject> object,
|
||||
|
||||
struct ObjectBoilerplate {
|
||||
static Handle<JSObject> Create(Isolate* isolate,
|
||||
Handle<FeedbackVector> vector,
|
||||
Handle<HeapObject> description, int flags) {
|
||||
Handle<HeapObject> description, int flags,
|
||||
PretenureFlag pretenure_flag) {
|
||||
Handle<Context> native_context = isolate->native_context();
|
||||
Handle<BoilerplateDescription> boilerplate_description =
|
||||
Handle<BoilerplateDescription>::cast(description);
|
||||
@ -302,9 +330,6 @@ struct ObjectBoilerplate {
|
||||
: isolate->factory()->ObjectLiteralMapFromCache(
|
||||
native_context, number_of_properties);
|
||||
|
||||
PretenureFlag pretenure_flag =
|
||||
isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
|
||||
|
||||
Handle<JSObject> boilerplate =
|
||||
map->is_dictionary_map()
|
||||
? isolate->factory()->NewSlowJSObjectFromMap(
|
||||
@ -324,7 +349,8 @@ struct ObjectBoilerplate {
|
||||
// The value contains the CompileTimeValue with the boilerplate
|
||||
// properties of a simple object or array literal.
|
||||
Handle<FixedArray> compile_time_value = Handle<FixedArray>::cast(value);
|
||||
value = InnerCreateBoilerplate(isolate, vector, compile_time_value);
|
||||
value =
|
||||
InnerCreateBoilerplate(isolate, compile_time_value, pretenure_flag);
|
||||
}
|
||||
uint32_t element_index = 0;
|
||||
if (key->ToArrayIndex(&element_index)) {
|
||||
@ -356,8 +382,8 @@ struct ObjectBoilerplate {
|
||||
|
||||
struct ArrayBoilerplate {
|
||||
static Handle<JSObject> Create(Isolate* isolate,
|
||||
Handle<FeedbackVector> vector,
|
||||
Handle<HeapObject> description, int flags) {
|
||||
Handle<HeapObject> description, int flags,
|
||||
PretenureFlag pretenure_flag) {
|
||||
Handle<ConstantElementsPair> elements =
|
||||
Handle<ConstantElementsPair>::cast(description);
|
||||
// Create the JSArray.
|
||||
@ -397,16 +423,14 @@ struct ArrayBoilerplate {
|
||||
// array literal.
|
||||
Handle<FixedArray> compile_time_value(
|
||||
FixedArray::cast(fixed_array_values->get(i)));
|
||||
Handle<Object> result =
|
||||
InnerCreateBoilerplate(isolate, vector, compile_time_value);
|
||||
Handle<Object> result = InnerCreateBoilerplate(
|
||||
isolate, compile_time_value, pretenure_flag);
|
||||
fixed_array_values_copy->set(i, *result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
PretenureFlag pretenure_flag =
|
||||
isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
|
||||
return isolate->factory()->NewJSArrayWithElements(
|
||||
copied_elements_values, constant_elements_kind,
|
||||
copied_elements_values->length(), pretenure_flag);
|
||||
@ -414,15 +438,15 @@ struct ArrayBoilerplate {
|
||||
};
|
||||
|
||||
Handle<Object> InnerCreateBoilerplate(Isolate* isolate,
|
||||
Handle<FeedbackVector> vector,
|
||||
Handle<FixedArray> compile_time_value) {
|
||||
Handle<FixedArray> compile_time_value,
|
||||
PretenureFlag pretenure_flag) {
|
||||
Handle<HeapObject> elements =
|
||||
CompileTimeValue::GetElements(compile_time_value);
|
||||
int flags = CompileTimeValue::GetLiteralTypeFlags(compile_time_value);
|
||||
if (flags == CompileTimeValue::kArrayLiteralFlag) {
|
||||
return ArrayBoilerplate::Create(isolate, vector, elements, flags);
|
||||
return ArrayBoilerplate::Create(isolate, elements, flags, pretenure_flag);
|
||||
}
|
||||
return ObjectBoilerplate::Create(isolate, vector, elements, flags);
|
||||
return ObjectBoilerplate::Create(isolate, elements, flags, pretenure_flag);
|
||||
}
|
||||
|
||||
template <typename Boilerplate>
|
||||
@ -453,9 +477,22 @@ MaybeHandle<JSObject> CreateLiteral(Isolate* isolate,
|
||||
Handle<JSObject>(JSObject::cast(site->transition_info()), isolate);
|
||||
} else {
|
||||
// Instantiate a JSArray or JSObject literal from the given {description}.
|
||||
boilerplate = Boilerplate::Create(isolate, vector, description, flags);
|
||||
// TODO(cbruni): enable pre-initialized state for boilerplates after
|
||||
// investigating regressions.
|
||||
if (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;
|
||||
} else {
|
||||
PretenureFlag pretenure_flag =
|
||||
isolate->heap()->InNewSpace(*vector) ? NOT_TENURED : TENURED;
|
||||
boilerplate =
|
||||
Boilerplate::Create(isolate, description, flags, pretenure_flag);
|
||||
}
|
||||
// Install AllocationSite objects.
|
||||
AllocationSiteCreationContext creation_context(isolate);
|
||||
site = creation_context.EnterNewScope();
|
||||
|
@ -165,6 +165,12 @@ function fastliteralcase_smiholey(index, value) {
|
||||
obj = fastliteralcase_smiholey(5, 1);
|
||||
assertKind(elements_kind.fast_smi_only, obj);
|
||||
assertHoley(obj);
|
||||
|
||||
// We only start tracking tranistion with the second instantiation.
|
||||
obj = fastliteralcase_smiholey(5, 1);
|
||||
assertKind(elements_kind.fast_smi_only, obj);
|
||||
assertHoley(obj);
|
||||
|
||||
obj = fastliteralcase_smiholey(0, 1);
|
||||
assertKind(elements_kind.fast_smi_only, obj);
|
||||
assertHoley(obj);
|
||||
@ -262,27 +268,70 @@ assertKind(elements_kind.fast, obj);
|
||||
// Case: array constructor calls with out of date feedback.
|
||||
// The boilerplate should incorporate all feedback, but the input array
|
||||
// should be minimally transitioned based on immediate need.
|
||||
(function() {
|
||||
function foo(i) {
|
||||
// We have two cases, one for literals one for constructed arrays.
|
||||
var a = (i == 0)
|
||||
? [1, 2, 3]
|
||||
: new Array(1, 2, 3);
|
||||
return a;
|
||||
(function TestLiteralTransition() {
|
||||
function literal() {
|
||||
return [1, 2, 3];
|
||||
}
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
a = foo(i);
|
||||
b = foo(i);
|
||||
b[5] = 1; // boilerplate goes holey
|
||||
assertHoley(foo(i));
|
||||
a[0] = 3.5; // boilerplate goes holey double
|
||||
assertKind(elements_kind.fast_double, a);
|
||||
assertNotHoley(a);
|
||||
c = foo(i);
|
||||
assertKind(elements_kind.fast_double, c);
|
||||
assertHoley(c);
|
||||
var a = literal(); // No boilerplate created yet.
|
||||
var b = literal(); // Created boilerplate here.
|
||||
var c = literal(); // Created copy from boilerplate.
|
||||
// Boilerplate goes holey smi.
|
||||
b[5] = 1;
|
||||
assertKind(elements_kind.fast_smi_only, a);
|
||||
assertKind(elements_kind.fast_smi_only, b);
|
||||
assertKind(elements_kind.fast_smi_only, c);
|
||||
assertHoley(literal());
|
||||
|
||||
// {a} has been created before tracking was active and thus doesn't affect
|
||||
// the boilerplate.
|
||||
a[0] = 3.5;
|
||||
assertKind(elements_kind.fast_double, a);
|
||||
assertNotHoley(a);
|
||||
// Check that modifying {a} didn't change the boilerplate.
|
||||
var d = literal();
|
||||
assertKind(elements_kind.fast_smi_only, d);
|
||||
assertHoley(d);
|
||||
|
||||
// Boilerplate goes from holey smi to holey double
|
||||
c[0] = 3.5;
|
||||
assertKind(elements_kind.fast_double, c);
|
||||
assertNotHoley(c);
|
||||
|
||||
var e = literal();
|
||||
assertKind(elements_kind.fast_double, e);
|
||||
assertHoley(e);
|
||||
})();
|
||||
|
||||
(function TestConstructedArrayTransition() {
|
||||
// Allocation site tracking is on from the first instantiation for constructor
|
||||
// calls.
|
||||
function array() {
|
||||
return new Array(1, 2, 3);
|
||||
}
|
||||
var a = array();
|
||||
var b = array();
|
||||
// Transition kind goes to smi holey.
|
||||
b[5] = 1;
|
||||
assertKind(elements_kind.fast_smi_only, a);
|
||||
assertNotHoley(a);
|
||||
assertHoley(b);
|
||||
assertKind(elements_kind.fast_smi_only, b);
|
||||
assertHoley(array());
|
||||
// Confirm that modifying {b} did change the transition kind.
|
||||
var d = array();
|
||||
assertKind(elements_kind.fast_smi_only, d);
|
||||
assertHoley(d);
|
||||
|
||||
// Sets the transition kind to double.
|
||||
a[0] = 3.5;
|
||||
assertKind(elements_kind.fast_double, a);
|
||||
assertNotHoley(a);
|
||||
|
||||
// Confirm that we get the general kind holey + double.
|
||||
var e = array();
|
||||
assertKind(elements_kind.fast_double, e);
|
||||
assertHoley(e);
|
||||
})();
|
||||
|
||||
function newarraycase_onearg(len, value) {
|
||||
@ -375,15 +424,35 @@ gc();
|
||||
return literal;
|
||||
}
|
||||
|
||||
obj = get_nested_literal();
|
||||
var obj = get_nested_literal();
|
||||
assertKind(elements_kind.fast, obj);
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[2]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[2][0] = "hello";
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast, obj[2]);
|
||||
|
||||
// We start tracking the allocation site from the second instantiation on.
|
||||
obj = get_nested_literal();
|
||||
assertKind(elements_kind.fast, obj);
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[2]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[2][0] = "hello";
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast, obj[2]);
|
||||
|
||||
obj = get_nested_literal();
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast, obj[2]);
|
||||
|
||||
|
||||
// A more complex nested literal case.
|
||||
function get_deep_nested_literal() {
|
||||
var literal = [[1], [[2], "hello"], 3, [4]];
|
||||
@ -391,6 +460,15 @@ gc();
|
||||
}
|
||||
|
||||
obj = get_deep_nested_literal();
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1][0]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[1][0][0] = "goodbye";
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast, obj[1][0]);
|
||||
|
||||
obj = get_deep_nested_literal();
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1][0]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[1][0][0] = "goodbye";
|
||||
@ -424,6 +502,12 @@ gc();
|
||||
assertKind(elements_kind.fast_smi_only, obj.array);
|
||||
obj.array[1] = 3.5;
|
||||
assertKind(elements_kind.fast_double, obj.array);
|
||||
|
||||
obj = get_object_literal();
|
||||
assertKind(elements_kind.fast_smi_only, obj.array);
|
||||
obj.array[1] = 3.5;
|
||||
assertKind(elements_kind.fast_double, obj.array);
|
||||
|
||||
obj = get_object_literal();
|
||||
assertKind(elements_kind.fast_double, obj.array);
|
||||
|
||||
@ -440,6 +524,13 @@ gc();
|
||||
assertKind(elements_kind.fast_smi_only, obj.array[1]);
|
||||
obj.array[1][0] = 3.5;
|
||||
assertKind(elements_kind.fast_double, obj.array[1]);
|
||||
|
||||
obj = get_nested_object_literal();
|
||||
assertKind(elements_kind.fast, obj.array);
|
||||
assertKind(elements_kind.fast_smi_only, obj.array[1]);
|
||||
obj.array[1][0] = 3.5;
|
||||
assertKind(elements_kind.fast_double, obj.array[1]);
|
||||
|
||||
obj = get_nested_object_literal();
|
||||
assertKind(elements_kind.fast_double, obj.array[1]);
|
||||
|
||||
@ -456,8 +547,26 @@ gc();
|
||||
|
||||
obj = get_nested_literal();
|
||||
assertKind(elements_kind.fast, obj);
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[2]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[2][0] = "hello";
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast, obj[2]);
|
||||
|
||||
obj = get_nested_literal();
|
||||
assertKind(elements_kind.fast, obj);
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[2]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[2][0] = "hello";
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
assertKind(elements_kind.fast, obj[2]);
|
||||
|
||||
obj = get_nested_literal();
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1]);
|
||||
@ -470,6 +579,15 @@ gc();
|
||||
}
|
||||
|
||||
obj = get_deep_nested_literal();
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1][0]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[1][0][0] = "goodbye";
|
||||
assertKind(elements_kind.fast_double, obj[0]);
|
||||
assertKind(elements_kind.fast, obj[1][0]);
|
||||
|
||||
obj = get_deep_nested_literal();
|
||||
assertKind(elements_kind.fast_smi_only, obj[0]);
|
||||
assertKind(elements_kind.fast_smi_only, obj[1][0]);
|
||||
obj[0][0] = 3.5;
|
||||
obj[1][0][0] = "goodbye";
|
||||
|
@ -69,7 +69,7 @@ get_literal(3);
|
||||
// It's important to store a from before we crankshaft get_literal, because
|
||||
// mementos won't be created from crankshafted code at all.
|
||||
a = get_literal(3);
|
||||
%OptimizeFunctionOnNextCall(get_literal);
|
||||
%OptimizeFunctionOnNextCall(get_literal);
|
||||
get_literal(3);
|
||||
assertOptimized(get_literal);
|
||||
assertTrue(%HasFastSmiElements(a));
|
||||
@ -86,7 +86,7 @@ assertUnoptimized(get_literal);
|
||||
|
||||
// Optimize again
|
||||
get_literal(3);
|
||||
%OptimizeFunctionOnNextCall(get_literal);
|
||||
%OptimizeFunctionOnNextCall(get_literal);
|
||||
b = get_literal(3);
|
||||
assertTrue(%HasFastDoubleElements(b));
|
||||
assertOptimized(get_literal);
|
||||
@ -99,9 +99,20 @@ assertOptimized(get_literal);
|
||||
return [a, b, c];
|
||||
}
|
||||
|
||||
a = bar(1, 2, 3);
|
||||
var a = bar(1, 2, 3);
|
||||
assertKind(elements_kind.fast_smi_only, a);
|
||||
a[0] = 3.5;
|
||||
a[1] = 'hi';
|
||||
b = bar(1, 2, 3);
|
||||
assertKind(elements_kind.fast, a);
|
||||
|
||||
// We only start tracking transition information with the second
|
||||
// instantiation.
|
||||
var b = bar(1, 2, 3);
|
||||
assertKind(elements_kind.fast_smi_only, b);
|
||||
b[0] = 3.5;
|
||||
b[1] = 'hi';
|
||||
assertKind(elements_kind.fast, b);
|
||||
|
||||
var c = bar(1, 2, 3);
|
||||
assertKind(elements_kind.fast, c);
|
||||
})();
|
||||
|
@ -113,11 +113,15 @@
|
||||
assertEquals(3, l.y.z)
|
||||
}
|
||||
|
||||
f(); f(); f();
|
||||
f();
|
||||
f();
|
||||
f();
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
f(); f();
|
||||
f();
|
||||
f();
|
||||
%OptimizeFunctionOnNextCall(f);
|
||||
f(); f();
|
||||
f();
|
||||
f();
|
||||
})();
|
||||
|
||||
|
||||
|
@ -57,8 +57,7 @@ function testBasicPrototype() {
|
||||
assertEquals(Object.getPrototypeOf(obj), Object.prototype);
|
||||
assertEquals(Object.getPrototypeOf(obj.b), Object.prototype);
|
||||
};
|
||||
testBasicPrototype();
|
||||
testBasicPrototype();
|
||||
runTest(testBasicPrototype);
|
||||
|
||||
function testDynamicValue() {
|
||||
var z = 24;
|
||||
@ -74,10 +73,9 @@ function testDynamicValue() {
|
||||
assertEquals(24, obj2.b.y);
|
||||
assertEquals('Zebra', obj2.c);
|
||||
}
|
||||
testDynamicValue();
|
||||
testDynamicValue();
|
||||
runTest(testDynamicValue);
|
||||
|
||||
(function testMultipleInstatiations() {
|
||||
function testMultipleInstatiations() {
|
||||
var arr = [];
|
||||
for (var i = 0; i < 2; i++) {
|
||||
arr[i] = {
|
||||
@ -90,7 +88,8 @@ testDynamicValue();
|
||||
arr[0].b.x = 2;
|
||||
assertEquals(2, arr[0].b.x);
|
||||
assertEquals(12, arr[1].b.x);
|
||||
})();
|
||||
}
|
||||
runTest(testMultipleInstatiations);
|
||||
|
||||
function testSparseElements() {
|
||||
let sa1 = {
|
||||
@ -254,8 +253,7 @@ function TestSimpleElements() {
|
||||
o[0] = 0;
|
||||
assertEquals({0:0, 1:"one", 2:"two"}, o);
|
||||
}
|
||||
TestSimpleElements();
|
||||
TestSimpleElements();
|
||||
runTest(TestSimpleElements);
|
||||
|
||||
function TestNumericNames() {
|
||||
var o = {
|
||||
@ -279,8 +277,7 @@ function TestNumericNames() {
|
||||
%HeapObjectVerify(o);
|
||||
assertEquals(['1.2', '1.3'], Object.keys(o));
|
||||
}
|
||||
TestNumericNames();
|
||||
TestNumericNames();
|
||||
runTest(TestNumericNames);
|
||||
|
||||
function TestDictionaryElements() {
|
||||
let o = {1024: true};
|
||||
@ -301,10 +298,7 @@ function TestDictionaryElements() {
|
||||
o2[1024] = "test";
|
||||
assertEquals(["test"], Object.values(o2));
|
||||
}
|
||||
TestDictionaryElements();
|
||||
TestDictionaryElements();
|
||||
%OptimizeFunctionOnNextCall(TestDictionaryElements);
|
||||
TestDictionaryElements();
|
||||
runTest(TestDictionaryElements);
|
||||
|
||||
function TestLiteralElementsKind() {
|
||||
let o = {0:0, 1:1, 2:2};
|
||||
@ -330,10 +324,7 @@ function TestLiteralElementsKind() {
|
||||
|
||||
assertTrue(%HasDictionaryElements({0xFFFFFF:true}));
|
||||
}
|
||||
TestLiteralElementsKind();
|
||||
TestLiteralElementsKind();
|
||||
%OptimizeFunctionOnNextCall(TestLiteralElementsKind);
|
||||
TestLiteralElementsKind();
|
||||
runTest(TestLiteralElementsKind);
|
||||
|
||||
function TestNonNumberElementValues() {
|
||||
var o = {
|
||||
@ -388,11 +379,7 @@ function TestNonNumberElementValues() {
|
||||
%HeapObjectVerify(o4);
|
||||
assertEquals(['1', '2', '3', '4', 'a', 'b'], Object.keys(o4));
|
||||
}
|
||||
TestNonNumberElementValues();
|
||||
TestNonNumberElementValues();
|
||||
TestNonNumberElementValues();
|
||||
%OptimizeFunctionOnNextCall(TestNonNumberElementValues);
|
||||
TestNonNumberElementValues();
|
||||
runTest(TestNonNumberElementValues);
|
||||
|
||||
|
||||
function numericGetters() {
|
||||
@ -419,8 +406,7 @@ function numericGetters() {
|
||||
get 1.30() {}
|
||||
});
|
||||
}
|
||||
numericGetters();
|
||||
numericGetters();
|
||||
runTest(numericGetters);
|
||||
|
||||
function numericSetters() {
|
||||
function TestNumericNamesSetter(expectedKeys, object) {
|
||||
@ -446,9 +432,7 @@ function numericSetters() {
|
||||
set 1.30(_) {; }
|
||||
});
|
||||
};
|
||||
|
||||
numericSetters();
|
||||
numericSetters();
|
||||
runTest(numericSetters);
|
||||
|
||||
function TestProxyWithDefinitionInObjectLiteral() {
|
||||
// Trap for set should not be used if the definition
|
||||
@ -464,14 +448,12 @@ function TestProxyWithDefinitionInObjectLiteral() {
|
||||
p[prop] = 'my value';
|
||||
assertEquals(undefined, p[prop]);
|
||||
|
||||
|
||||
var l = new Proxy({[prop]: 'my value'}, handler);
|
||||
assertEquals('my value', l[prop]);
|
||||
};
|
||||
TestProxyWithDefinitionInObjectLiteral();
|
||||
TestProxyWithDefinitionInObjectLiteral();
|
||||
runTest(TestProxyWithDefinitionInObjectLiteral);
|
||||
|
||||
(function TestLiteralWithNullProto() {
|
||||
function TestLiteralWithNullProto() {
|
||||
// Assume dictionary usage for simple null prototype literal objects,
|
||||
// this is equivalent to Object.create(null). Note that on the first call
|
||||
// the literal boilerplate is initialized, and from then on we use a the
|
||||
@ -498,7 +480,8 @@ TestProxyWithDefinitionInObjectLiteral();
|
||||
testDictModeNullProtoLiteral(() => ({a:1, b:2, __proto__:null}));
|
||||
testDictModeNullProtoLiteral(() => ({["a"]: 1, __proto__: null}));
|
||||
testDictModeNullProtoLiteral(() => ({a: Object, __proto__: null}));
|
||||
})();
|
||||
}
|
||||
runTest(TestLiteralWithNullProto);
|
||||
|
||||
function testNestedNullProtoLiteral() {
|
||||
let obj;
|
||||
@ -524,8 +507,7 @@ function testNestedNullProtoLiteral() {
|
||||
obj.foo.bar = "barValue2";
|
||||
assertEquals("barValue2", obj.foo.bar);
|
||||
}
|
||||
testNestedNullProtoLiteral();
|
||||
testNestedNullProtoLiteral();
|
||||
runTest(testNestedNullProtoLiteral);
|
||||
|
||||
|
||||
function TestSlowLiteralOptimized() {
|
||||
@ -549,10 +531,9 @@ function TestSlowLiteralOptimized() {
|
||||
obj.bar = "barValue2";
|
||||
assertEquals("barValue2", obj.bar);
|
||||
};
|
||||
TestSlowLiteralOptimized();
|
||||
TestSlowLiteralOptimized();
|
||||
runTest(TestSlowLiteralOptimized);
|
||||
|
||||
(function TestLargeDictionaryLiteral() {
|
||||
function TestLargeDictionaryLiteral() {
|
||||
// Create potential large-space object literal.
|
||||
function createObject() {
|
||||
// This literal has least kMaxRegularHeapObjectSize / 64 number of
|
||||
@ -1568,7 +1549,8 @@ TestSlowLiteralOptimized();
|
||||
assertFalse(%HasFastProperties(object2));
|
||||
assertEquals(Object.getPrototypeOf(object2), null);
|
||||
assertEquals(keys, Object.keys(object2));
|
||||
})();
|
||||
}
|
||||
runTest(TestLargeDictionaryLiteral);
|
||||
|
||||
|
||||
(function TestPrototypeInObjectLiteral() {
|
||||
@ -1592,3 +1574,21 @@ TestSlowLiteralOptimized();
|
||||
|
||||
delete Object.prototype.c;
|
||||
})();
|
||||
|
||||
|
||||
(function testNewLiteralObjectSpace() {
|
||||
// The first-time literals are created they should reside in new-space.
|
||||
assertTrue(%InNewSpace([]));
|
||||
assertTrue(%InNewSpace({}));
|
||||
let result = [ [0], [1], [2], [3]];
|
||||
assertTrue(%InNewSpace(result));
|
||||
for (let i = 0; i < result.length; i++) {
|
||||
assertTrue(%InNewSpace(result[i]));
|
||||
}
|
||||
result = {a:{x:{}}, b:{x:{}}, c:{x:{}}};
|
||||
assertTrue(%InNewSpace(result));
|
||||
for (let key in result) {
|
||||
assertTrue(%InNewSpace(result[key]));
|
||||
assertTrue(%InNewSpace(result[key].x));
|
||||
}
|
||||
})();
|
||||
|
@ -29,11 +29,12 @@ function literals_sharing_test(warmup, optimize) {
|
||||
|
||||
|
||||
function test() {
|
||||
var warmup = true;
|
||||
for (var i = 0; i < 3; i++) {
|
||||
// We only start tracking allocation information with the second
|
||||
// instantiation.
|
||||
var warmup = i < 2;
|
||||
print("iter: " + i + ", warmup: "+ warmup);
|
||||
literals_sharing_test(warmup, false);
|
||||
warmup = false;
|
||||
}
|
||||
print("iter: " + i + ", opt: true");
|
||||
literals_sharing_test(warmup, true);
|
||||
|
Loading…
Reference in New Issue
Block a user