Commit bbc89774 authored by Camillo Bruni's avatar Camillo Bruni Committed by Commit Bot

[runtime] Enable double-lazy boilerplate creation again

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