Reviewers: Hannes Payer,
Description:
Version 4.4.63.11 (cherry-pick)
Merged 5fca3947cf52f5ff2c5d094281a38347eb9df68f
Hydrogen object literals: always initialize in-object properties
BUG=chromium:500497
LOG=N
[email protected]
Please review this at https://codereview.chromium.org/1219863002/
Base URL: https://chromium.googlesource.com/v8/[email protected]
Affected files (+63, -16 lines):
M include/v8-version.h
M src/hydrogen.h
M src/hydrogen.cc
M src/runtime/runtime-test.cc
A test/mjsunit/regress/regress-crbug-500497.js
Index: include/v8-version.h
diff --git a/include/v8-version.h b/include/v8-version.h
index
d33768cbc78ceb24ad2073e578bf006f8f30ce84..e2c07ba803faecbd392778db8a087feb41c7c8fc
100644
--- a/include/v8-version.h
+++ b/include/v8-version.h
@@ -11,7 +11,7 @@
#define V8_MAJOR_VERSION 4
#define V8_MINOR_VERSION 4
#define V8_BUILD_NUMBER 63
-#define V8_PATCH_LEVEL 10
+#define V8_PATCH_LEVEL 11
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index
f226730a2b7ecff126703c6d9b0a214a7c2bb946..a1b06482078471d937ca46e7efb70323e06bc325
100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -9662,15 +9662,7 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew*
expr) {
HObjectAccess::ForMapAndOffset(initial_map,
JSObject::kElementsOffset),
empty_fixed_array);
- if (initial_map->inobject_properties() != 0) {
- HConstant* undefined = graph()->GetConstantUndefined();
- for (int i = 0; i < initial_map->inobject_properties(); i++) {
- int property_offset = initial_map->GetInObjectPropertyOffset(i);
- Add<HStoreNamedField>(receiver,
- HObjectAccess::ForMapAndOffset(initial_map, property_offset),
- undefined);
- }
- }
+ BuildInitializeInobjectProperties(receiver, initial_map);
}
// Replace the constructor function with a newly allocated receiver
using
@@ -9713,6 +9705,20 @@ void HOptimizedGraphBuilder::VisitCallNew(CallNew*
expr) {
}
+void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
+ HValue* receiver, Handle<Map> initial_map) {
+ if (initial_map->inobject_properties() != 0) {
+ HConstant* undefined = graph()->GetConstantUndefined();
+ for (int i = 0; i < initial_map->inobject_properties(); i++) {
+ int property_offset = initial_map->GetInObjectPropertyOffset(i);
+ Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
+ initial_map, property_offset),
+ undefined);
+ }
+ }
+}
+
+
HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
HAllocate* result =
BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
@@ -11282,13 +11288,13 @@ HInstruction*
HOptimizedGraphBuilder::BuildFastLiteral(
Handle<JSObject> boilerplate_object,
AllocationSiteUsageContext* site_context) {
NoObservableSideEffectsScope no_effects(this);
- InstanceType instance_type = boilerplate_object->map()->instance_type();
+ Handle<Map> initial_map(boilerplate_object->map());
+ InstanceType instance_type = initial_map->instance_type();
DCHECK(instance_type == JS_ARRAY_TYPE || instance_type ==
JS_OBJECT_TYPE);
HType type = instance_type == JS_ARRAY_TYPE
? HType::JSArray() : HType::JSObject();
- HValue* object_size_constant = Add<HConstant>(
- boilerplate_object->map()->instance_size());
+ HValue* object_size_constant =
Add<HConstant>(initial_map->instance_size());
PretenureFlag pretenure_flag = NOT_TENURED;
Handle<AllocationSite> current_site(*site_context->current(), isolate());
@@ -11313,6 +11319,11 @@ HInstruction*
HOptimizedGraphBuilder::BuildFastLiteral(
BuildEmitObjectHeader(boilerplate_object, object);
+ // Similarly to the elements pointer, there is no guarantee that all
+ // property allocations can get folded, so pre-initialize all in-object
+ // properties to a safe value.
+ BuildInitializeInobjectProperties(object, initial_map);
+
Handle<FixedArrayBase> elements(boilerplate_object->elements());
int elements_size = (elements->length() > 0 &&
elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
@@ -11351,8 +11362,8 @@ HInstruction*
HOptimizedGraphBuilder::BuildFastLiteral(
}
// Copy in-object properties.
- if (boilerplate_object->map()->NumberOfFields() != 0 ||
- boilerplate_object->map()->unused_property_fields() > 0) {
+ if (initial_map->NumberOfFields() != 0 ||
+ initial_map->unused_property_fields() > 0) {
BuildEmitInObjectProperties(boilerplate_object, object, site_context,
pretenure_flag);
}
Index: src/hydrogen.h
diff --git a/src/hydrogen.h b/src/hydrogen.h
index
0feef24e6b91f82032ac01d6abb30e22cdec533c..eabcff4b7d0d65dc35b40cc88d70efb83b25025b
100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -2506,6 +2506,9 @@ class HOptimizedGraphBuilder : public HGraphBuilder,
public AstVisitor {
void BuildInlinedCallArray(Expression* expression, int argument_count,
Handle<AllocationSite> site);
+ void BuildInitializeInobjectProperties(HValue* receiver,
+ Handle<Map> initial_map);
+
class PropertyAccessInfo {
public:
PropertyAccessInfo(HOptimizedGraphBuilder* builder,
Index: src/runtime/runtime-test.cc
diff --git a/src/runtime/runtime-test.cc b/src/runtime/runtime-test.cc
index
ddf2e9d6b46a6c7b6b848ae9754f293ef27381f2..f590f81a2d87b236b5e88eb80f5c681065e936c0
100644
--- a/src/runtime/runtime-test.cc
+++ b/src/runtime/runtime-test.cc
@@ -179,7 +179,7 @@ RUNTIME_FUNCTION(Runtime_GetOptimizationStatus) {
base::OS::Sleep(base::TimeDelta::FromMilliseconds(50));
}
}
- if (FLAG_always_opt) {
+ if (FLAG_always_opt || FLAG_prepare_always_opt) {
// With --always-opt, optimization status expectations might not
// match up, so just return a sentinel.
return Smi::FromInt(3); // 3 == "always".
Index: test/mjsunit/regress/regress-crbug-500497.js
diff --git a/test/mjsunit/regress/regress-crbug-500497.js
b/test/mjsunit/regress/regress-crbug-500497.js
new file mode 100644
index
0000000000000000000000000000000000000000..9117440c2c843fe0b37ee68f5cd059e2b7314d1c
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-500497.js
@@ -0,0 +1,33 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// New space must be at max capacity to trigger pretenuring decision.
+// Flags: --allow-natives-syntax --verify-heap --max-semi-space-size=1
+
+var global = []; // Used to keep some objects alive.
+
+function Ctor() {
+ var result = {a: {}, b: {}, c: {}, d: {}, e: {}, f: {}, g: {}};
+ return result;
+}
+
+for (var i = 0; i < 120; i++) {
+ // Make the "a" property long-lived, while everything else is
short-lived.
+ global.push(Ctor().a);
+ (function FillNewSpace() { new Array(10000); })();
+}
+
+// The bad situation is only triggered if Ctor wasn't optimized too early.
+assertUnoptimized(Ctor);
+// Optimized code for Ctor will pretenure the "a" property, so it will have
+// three allocations:
+// #1 Allocate the "result" object in new-space.
+// #2 Allocate the object stored in the "a" property in old-space.
+// #3 Allocate the objects for the "b" through "g" properties in new-space.
+%OptimizeFunctionOnNextCall(Ctor);
+for (var i = 0; i < 10000; i++) {
+ // At least one of these calls will run out of new space. The bug is
+ // triggered when it is allocation #3 that triggers GC.
+ Ctor();
+}
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.