Revision: 22129
Author: [email protected]
Date: Tue Jul 1 15:02:31 2014 UTC
Log: Reland r22082 "Replace HeapNumber as doublebox with an explicit
MutableHeapNumber."
[email protected]
Review URL: https://codereview.chromium.org/334323003
http://code.google.com/p/v8/source/detail?r=22129
Added:
/branches/bleeding_edge/test/mjsunit/migrations.js
Modified:
/branches/bleeding_edge/include/v8.h
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/arm64/macro-assembler-arm64.cc
/branches/bleeding_edge/src/arm64/macro-assembler-arm64.h
/branches/bleeding_edge/src/arm64/stub-cache-arm64.cc
/branches/bleeding_edge/src/deoptimizer.cc
/branches/bleeding_edge/src/factory.cc
/branches/bleeding_edge/src/factory.h
/branches/bleeding_edge/src/heap-snapshot-generator.cc
/branches/bleeding_edge/src/heap.cc
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/hydrogen.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/json-parser.h
/branches/bleeding_edge/src/json-stringifier.h
/branches/bleeding_edge/src/mark-compact.cc
/branches/bleeding_edge/src/mips/macro-assembler-mips.cc
/branches/bleeding_edge/src/mips/macro-assembler-mips.h
/branches/bleeding_edge/src/mips/stub-cache-mips.cc
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects-printer.cc
/branches/bleeding_edge/src/objects-visiting.cc
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
/branches/bleeding_edge/src/runtime.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
/branches/bleeding_edge/src/x87/macro-assembler-x87.cc
/branches/bleeding_edge/src/x87/macro-assembler-x87.h
/branches/bleeding_edge/src/x87/stub-cache-x87.cc
/branches/bleeding_edge/test/cctest/test-heap-profiler.cc
/branches/bleeding_edge/test/mjsunit/mjsunit.status
=======================================
--- /dev/null
+++ /branches/bleeding_edge/test/mjsunit/migrations.js Tue Jul 1 15:02:31
2014 UTC
@@ -0,0 +1,311 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-ayle license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --track-fields --expose-gc
+
+var global = Function('return this')();
+var verbose = 0;
+
+function test(ctor_desc, use_desc, migr_desc) {
+ var n = 5;
+ var objects = [];
+ var results = [];
+
+ if (verbose) {
+ print();
+ print("===========================================================");
+ print("=== " + ctor_desc.name +
+ " | " + use_desc.name + " |--> " + migr_desc.name);
+ print("===========================================================");
+ }
+
+ // Clean ICs and transitions.
+ %NotifyContextDisposed();
+ gc(); gc(); gc();
+
+
+ // create objects
+ if (verbose) {
+ print("-----------------------------");
+ print("--- construct");
+ print();
+ }
+ for (var i = 0; i < n; i++) {
+ objects[i] = ctor_desc.ctor.apply(ctor_desc, ctor_desc.args(i));
+ }
+
+ try {
+ // use them
+ if (verbose) {
+ print("-----------------------------");
+ print("--- use 1");
+ print();
+ }
+ var use = use_desc.use1;
+ for (var i = 0; i < n; i++) {
+ if (i == 3) %OptimizeFunctionOnNextCall(use);
+ results[i] = use(objects[i], i);
+ }
+
+ // trigger migrations
+ if (verbose) {
+ print("-----------------------------");
+ print("--- trigger migration");
+ print();
+ }
+ var migr = migr_desc.migr;
+ for (var i = 0; i < n; i++) {
+ if (i == 3) %OptimizeFunctionOnNextCall(migr);
+ migr(objects[i], i);
+ }
+
+ // use again
+ if (verbose) {
+ print("-----------------------------");
+ print("--- use 2");
+ print();
+ }
+ var use = use_desc.use2 !== undefined ? use_desc.use2 : use_desc.use1;
+ for (var i = 0; i < n; i++) {
+ if (i == 3) %OptimizeFunctionOnNextCall(use);
+ results[i] = use(objects[i], i);
+ if (verbose >= 2) print(results[i]);
+ }
+
+ } catch (e) {
+ if (verbose) print("--- incompatible use: " + e);
+ }
+ return results;
+}
+
+
+var ctors = [
+ {
+ name: "none-to-double",
+ ctor: function(v) { return {a: v}; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "double",
+ ctor: function(v) { var o = {}; o.a = v; return o; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "none-to-smi",
+ ctor: function(v) { return {a: v}; },
+ args: function(i) { return [i]; },
+ },
+ {
+ name: "smi",
+ ctor: function(v) { var o = {}; o.a = v; return o; },
+ args: function(i) { return [i]; },
+ },
+ {
+ name: "none-to-object",
+ ctor: function(v) { return {a: v}; },
+ args: function(i) { return ["s"]; },
+ },
+ {
+ name: "object",
+ ctor: function(v) { var o = {}; o.a = v; return o; },
+ args: function(i) { return ["s"]; },
+ },
+ {
+ name: "{a:, b:, c:}",
+ ctor: function(v1, v2, v3) { return {a: v1, b: v2, c: v3}; },
+ args: function(i) { return [1.5 + i, 1.6, 1.7]; },
+ },
+ {
+ name: "{a..h:}",
+ ctor: function(v) { var o = {}; o.h=o.g=o.f=o.e=o.d=o.c=o.b=o.a=v;
return o; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "1",
+ ctor: function(v) { var o = 1; o.a = v; return o; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "f()",
+ ctor: function(v) { var o = function() { return v;}; o.a = v; return
o; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "f().bind",
+ ctor: function(v) { var o = function(a,b,c) { return a+b+c; }; o =
o.bind(o, v, v+1, v+2.2); return o; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "dictionary elements",
+ ctor: function(v) { var o = []; o[1] = v; o[200000] = v; return o; },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "json",
+ ctor: function(v) { var json = '{"a":' + v + ',"b":' + v + '}'; return
JSON.parse(json); },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "fast accessors",
+ accessor: {
+ get: function() { return this.a_; },
+ set: function(value) {this.a_ = value; },
+ configurable: true,
+ },
+ ctor: function(v) {
+ var o = {a_:v};
+ Object.defineProperty(o, "a", this.accessor);
+ return o;
+ },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "slow accessor",
+ accessor1: { value: this.a_, configurable: true },
+ accessor2: {
+ get: function() { return this.a_; },
+ set: function(value) {this.a_ = value; },
+ configurable: true,
+ },
+ ctor: function(v) {
+ var o = {a_:v};
+ Object.defineProperty(o, "a", this.accessor1);
+ Object.defineProperty(o, "a", this.accessor2);
+ return o;
+ },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "slow",
+ proto: {},
+ ctor: function(v) {
+ var o = {__proto__: this.proto};
+ o.a = v;
+ for (var i = 0; %HasFastProperties(o); i++) o["f"+i] = v;
+ return o;
+ },
+ args: function(i) { return [1.5 + i]; },
+ },
+ {
+ name: "global",
+ ctor: function(v) { return global; },
+ args: function(i) { return [i]; },
+ },
+];
+
+
+
+var uses = [
+ {
+ name: "o.a+1.0",
+ use1: function(o, i) { return o.a + 1.0; },
+ use2: function(o, i) { return o.a + 1.1; },
+ },
+ {
+ name: "o.b+1.0",
+ use1: function(o, i) { return o.b + 1.0; },
+ use2: function(o, i) { return o.b + 1.1; },
+ },
+ {
+ name: "o[1]+1.0",
+ use1: function(o, i) { return o[1] + 1.0; },
+ use2: function(o, i) { return o[1] + 1.1; },
+ },
+ {
+ name: "o[-1]+1.0",
+ use1: function(o, i) { return o[-1] + 1.0; },
+ use2: function(o, i) { return o[-1] + 1.1; },
+ },
+ {
+ name: "()",
+ use1: function(o, i) { return o() + 1.0; },
+ use2: function(o, i) { return o() + 1.1; },
+ },
+];
+
+
+
+var migrations = [
+ {
+ name: "to smi",
+ migr: function(o, i) { if (i == 0) o.a = 1; },
+ },
+ {
+ name: "to double",
+ migr: function(o, i) { if (i == 0) o.a = 1.1; },
+ },
+ {
+ name: "to object",
+ migr: function(o, i) { if (i == 0) o.a = {}; },
+ },
+ {
+ name: "set prototype {}",
+ migr: function(o, i) { o.__proto__ = {}; },
+ },
+ {
+ name: "%FunctionSetPrototype",
+ migr: function(o, i) { %FunctionSetPrototype(o, null); },
+ },
+ {
+ name: "modify prototype",
+ migr: function(o, i) { if (i == 0) o.__proto__.__proto1__ = [,,,5,,,];
},
+ },
+ {
+ name: "freeze prototype",
+ migr: function(o, i) { if (i == 0) Object.freeze(o.__proto__); },
+ },
+ {
+ name: "delete and re-add property",
+ migr: function(o, i) { var v = o.a; delete o.a; o.a = v; },
+ },
+ {
+ name: "modify prototype",
+ migr: function(o, i) { if (i >= 0) o.__proto__ = {}; },
+ },
+ {
+ name: "set property callback",
+ migr: function(o, i) {
+ Object.defineProperty(o, "a", {
+ get: function() { return 1.5 + i; },
+ set: function(value) {},
+ configurable: true,
+ });
+ },
+ },
+ {
+ name: "observe",
+ migr: function(o, i) { Object.observe(o, function(){}); },
+ },
+ {
+ name: "%EnableAccessChecks",
+ migr: function(o, i) {
+ if (typeof (o) !== 'function') %EnableAccessChecks(o);
+ },
+ },
+ {
+ name: "%DisableAccessChecks",
+ migr: function(o, i) {
+ if ((typeof (o) !== 'function') && (o !==
global)) %DisableAccessChecks(o);
+ },
+ },
+ {
+ name: "seal",
+ migr: function(o, i) { Object.seal(o); },
+ },
+ { // Must be the last in the sequence, because after the global object
freeze
+ // the other modifications does not make sence.
+ name: "freeze",
+ migr: function(o, i) { Object.freeze(o); },
+ },
+];
+
+
+
+migrations.forEach(function(migr) {
+ uses.forEach(function(use) {
+ ctors.forEach(function(ctor) {
+ test(ctor, use, migr);
+ });
+ });
+});
=======================================
--- /branches/bleeding_edge/include/v8.h Mon Jun 30 13:35:16 2014 UTC
+++ /branches/bleeding_edge/include/v8.h Tue Jul 1 15:02:31 2014 UTC
@@ -5587,7 +5587,7 @@
static const int kNullValueRootIndex = 7;
static const int kTrueValueRootIndex = 8;
static const int kFalseValueRootIndex = 9;
- static const int kEmptyStringRootIndex = 160;
+ static const int kEmptyStringRootIndex = 161;
// The external allocation limit should be below 256 MB on all
architectures
// to avoid that resource-constrained embedders run low on memory.
@@ -5602,10 +5602,10 @@
static const int kNodeIsIndependentShift = 4;
static const int kNodeIsPartiallyDependentShift = 5;
- static const int kJSObjectType = 0xbb;
+ static const int kJSObjectType = 0xbc;
static const int kFirstNonstringType = 0x80;
static const int kOddballType = 0x83;
- static const int kForeignType = 0x87;
+ static const int kForeignType = 0x88;
static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3;
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Tue Jul 1
15:02:31 2014 UTC
@@ -3274,14 +3274,19 @@
Register scratch2,
Register heap_number_map,
Label* gc_required,
- TaggingMode tagging_mode) {
+ TaggingMode tagging_mode,
+ MutableMode mode) {
// Allocate an object in the heap for the heap number and tag it as a
heap
// object.
Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+ Heap::RootListIndex map_index = mode == MUTABLE
+ ? Heap::kMutableHeapNumberMapRootIndex
+ : Heap::kHeapNumberMapRootIndex;
+ AssertIsRoot(heap_number_map, map_index);
+
// Store heap number map in the allocated object.
- AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
if (tagging_mode == TAG_RESULT) {
str(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
} else {
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Tue Jul 1
15:02:31 2014 UTC
@@ -778,7 +778,8 @@
Register scratch2,
Register heap_number_map,
Label* gc_required,
- TaggingMode tagging_mode = TAG_RESULT);
+ TaggingMode tagging_mode = TAG_RESULT,
+ MutableMode mode = IMMUTABLE);
void AllocateHeapNumberWithValue(Register result,
DwVfpRegister value,
Register scratch1,
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Jul 1 12:12:34
2014 UTC
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Jul 1 15:02:31
2014 UTC
@@ -426,8 +426,9 @@
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
- __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
- __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow);
+ __ LoadRoot(scratch3, Heap::kMutableHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow,
+ TAG_RESULT, MUTABLE);
__ JumpIfNotSmi(value_reg, &heap_number);
__ SmiUntag(scratch1, value_reg);
=======================================
--- /branches/bleeding_edge/src/arm64/macro-assembler-arm64.cc Tue Jul 1
13:50:46 2014 UTC
+++ /branches/bleeding_edge/src/arm64/macro-assembler-arm64.cc Tue Jul 1
15:02:31 2014 UTC
@@ -3570,7 +3570,8 @@
Register scratch1,
Register scratch2,
CPURegister value,
- CPURegister heap_number_map) {
+ CPURegister heap_number_map,
+ MutableMode mode) {
ASSERT(!value.IsValid() || value.Is64Bits());
UseScratchRegisterScope temps(this);
@@ -3579,6 +3580,10 @@
Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
NO_ALLOCATION_FLAGS);
+ Heap::RootListIndex map_index = mode == MUTABLE
+ ? Heap::kMutableHeapNumberMapRootIndex
+ : Heap::kHeapNumberMapRootIndex;
+
// Prepare the heap number map.
if (!heap_number_map.IsValid()) {
// If we have a valid value register, use the same type of register to
store
@@ -3588,7 +3593,7 @@
} else {
heap_number_map = scratch1;
}
- LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
+ LoadRoot(heap_number_map, map_index);
}
if (emit_debug_code()) {
Register map;
@@ -3598,7 +3603,7 @@
} else {
map = Register(heap_number_map);
}
- AssertRegisterIsRoot(map, Heap::kHeapNumberMapRootIndex);
+ AssertRegisterIsRoot(map, map_index);
}
// Store the heap number map and the value in the allocated object.
=======================================
--- /branches/bleeding_edge/src/arm64/macro-assembler-arm64.h Tue Jul 1
13:33:22 2014 UTC
+++ /branches/bleeding_edge/src/arm64/macro-assembler-arm64.h Tue Jul 1
15:02:31 2014 UTC
@@ -1372,7 +1372,8 @@
Register scratch1,
Register scratch2,
CPURegister value = NoFPReg,
- CPURegister heap_number_map = NoReg);
+ CPURegister heap_number_map = NoReg,
+ MutableMode mode = IMMUTABLE);
//
---------------------------------------------------------------------------
// Support functions.
=======================================
--- /branches/bleeding_edge/src/arm64/stub-cache-arm64.cc Tue Jul 1
12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/arm64/stub-cache-arm64.cc Tue Jul 1
15:02:31 2014 UTC
@@ -399,7 +399,8 @@
__ Ldr(temp_double, FieldMemOperand(value_reg,
HeapNumber::kValueOffset));
__ Bind(&do_store);
- __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2,
temp_double);
+ __ AllocateHeapNumber(storage_reg, slow, scratch1, scratch2,
temp_double,
+ NoReg, MUTABLE);
}
// Stub never generated for non-global objects that require access
checks.
=======================================
--- /branches/bleeding_edge/src/deoptimizer.cc Mon Jun 30 13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/deoptimizer.cc Tue Jul 1 15:02:31 2014 UTC
@@ -1813,9 +1813,11 @@
Handle<Map> map = Map::GeneralizeAllFieldRepresentations(
Handle<Map>::cast(MaterializeNextValue()));
switch (map->instance_type()) {
+ case MUTABLE_HEAP_NUMBER_TYPE:
case HEAP_NUMBER_TYPE: {
// Reuse the HeapNumber value directly as it is already properly
- // tagged and skip materializing the HeapNumber explicitly.
+ // tagged and skip materializing the HeapNumber explicitly. Turn
mutable
+ // heap numbers immutable.
Handle<Object> object = MaterializeNextValue();
if (object_index < prev_materialized_count_) {
materialized_objects_->Add(Handle<Object>(
@@ -1877,6 +1879,9 @@
Handle<Object> Deoptimizer::MaterializeNextValue() {
int value_index = materialization_value_index_++;
Handle<Object> value = materialized_values_->at(value_index);
+ if (value->IsMutableHeapNumber()) {
+ HeapNumber::cast(*value)->set_map(isolate_->heap()->heap_number_map());
+ }
if (*value == isolate_->heap()->arguments_marker()) {
value = MaterializeNextHeapObject();
}
@@ -3383,6 +3388,7 @@
// TODO(jarin) this should be unified with the code in
// Deoptimizer::MaterializeNextHeapObject()
switch (map->instance_type()) {
+ case MUTABLE_HEAP_NUMBER_TYPE:
case HEAP_NUMBER_TYPE: {
// Reuse the HeapNumber value directly as it is already properly
// tagged and skip materializing the HeapNumber explicitly.
=======================================
--- /branches/bleeding_edge/src/factory.cc Tue Jul 1 12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/factory.cc Tue Jul 1 15:02:31 2014 UTC
@@ -1008,7 +1008,7 @@
// We need to distinguish the minus zero value and this cannot be
// done after conversion to int. Doing this by comparing bit
// patterns is faster than using fpclassify() et al.
- if (IsMinusZero(value)) return NewHeapNumber(-0.0, pretenure);
+ if (IsMinusZero(value)) return NewHeapNumber(-0.0, IMMUTABLE, pretenure);
int int_value = FastD2I(value);
if (value == int_value && Smi::IsValid(int_value)) {
@@ -1016,15 +1016,15 @@
}
// Materialize the value in the heap.
- return NewHeapNumber(value, pretenure);
+ return NewHeapNumber(value, IMMUTABLE, pretenure);
}
Handle<Object> Factory::NewNumberFromInt(int32_t value,
PretenureFlag pretenure) {
if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate());
- // Bypass NumberFromDouble to avoid various redundant checks.
- return NewHeapNumber(FastI2D(value), pretenure);
+ // Bypass NewNumber to avoid various redundant checks.
+ return NewHeapNumber(FastI2D(value), IMMUTABLE, pretenure);
}
@@ -1034,15 +1034,17 @@
if (int32v >= 0 && Smi::IsValid(int32v)) {
return handle(Smi::FromInt(int32v), isolate());
}
- return NewHeapNumber(FastUI2D(value), pretenure);
+ return NewHeapNumber(FastUI2D(value), IMMUTABLE, pretenure);
}
Handle<HeapNumber> Factory::NewHeapNumber(double value,
+ MutableMode mode,
PretenureFlag pretenure) {
CALL_HEAP_FUNCTION(
isolate(),
- isolate()->heap()->AllocateHeapNumber(value, pretenure), HeapNumber);
+ isolate()->heap()->AllocateHeapNumber(value, mode, pretenure),
+ HeapNumber);
}
=======================================
--- /branches/bleeding_edge/src/factory.h Tue Jul 1 12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/factory.h Tue Jul 1 15:02:31 2014 UTC
@@ -352,9 +352,9 @@
return NewNumber(static_cast<double>(value), pretenure);
}
Handle<HeapNumber> NewHeapNumber(double value,
+ MutableMode mode = IMMUTABLE,
PretenureFlag pretenure = NOT_TENURED);
-
// These objects are used by the api to create env-independent data
// structures in the heap.
inline Handle<JSObject> NewNeanderObject() {
=======================================
--- /branches/bleeding_edge/src/heap-snapshot-generator.cc Tue Jul 1
12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/heap-snapshot-generator.cc Tue Jul 1
15:02:31 2014 UTC
@@ -1641,6 +1641,8 @@
for (int i = 0; i < real_size; i++) {
switch (descs->GetType(i)) {
case FIELD: {
+ Representation r = descs->GetDetails(i).representation();
+ if (r.IsSmi() || r.IsDouble()) break;
int index = descs->GetFieldIndex(i);
Name* k = descs->GetKey(i);
=======================================
--- /branches/bleeding_edge/src/heap.cc Mon Jun 30 13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/heap.cc Tue Jul 1 15:02:31 2014 UTC
@@ -2528,6 +2528,8 @@
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, scope_info)
ALLOCATE_MAP(HEAP_NUMBER_TYPE, HeapNumber::kSize, heap_number)
+ ALLOCATE_MAP(
+ MUTABLE_HEAP_NUMBER_TYPE, HeapNumber::kSize, mutable_heap_number)
ALLOCATE_MAP(SYMBOL_TYPE, Symbol::kSize, symbol)
ALLOCATE_MAP(FOREIGN_TYPE, Foreign::kSize, foreign)
@@ -2652,6 +2654,7 @@
AllocationResult Heap::AllocateHeapNumber(double value,
+ MutableMode mode,
PretenureFlag pretenure) {
// Statically ensure that it is safe to allocate heap numbers in paged
// spaces.
@@ -2665,7 +2668,8 @@
if (!allocation.To(&result)) return allocation;
}
- result->set_map_no_write_barrier(heap_number_map());
+ Map* map = mode == MUTABLE ? mutable_heap_number_map() :
heap_number_map();
+ HeapObject::cast(result)->set_map_no_write_barrier(map);
HeapNumber::cast(result)->set_value(value);
return result;
}
@@ -2771,12 +2775,13 @@
HandleScope scope(isolate());
Factory* factory = isolate()->factory();
- // The -0 value must be set before NumberFromDouble works.
- set_minus_zero_value(*factory->NewHeapNumber(-0.0, TENURED));
+ // The -0 value must be set before NewNumber works.
+ set_minus_zero_value(*factory->NewHeapNumber(-0.0, IMMUTABLE, TENURED));
ASSERT(std::signbit(minus_zero_value()->Number()) != 0);
- set_nan_value(*factory->NewHeapNumber(base::OS::nan_value(), TENURED));
- set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, TENURED));
+ set_nan_value(
+ *factory->NewHeapNumber(base::OS::nan_value(), IMMUTABLE, TENURED));
+ set_infinity_value(*factory->NewHeapNumber(V8_INFINITY, IMMUTABLE,
TENURED));
// The hole has not been created yet, but we want to put something
// predictable in the gaps in the string table, so lets make that Smi
zero.
=======================================
--- /branches/bleeding_edge/src/heap.h Mon Jun 30 13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/heap.h Tue Jul 1 15:02:31 2014 UTC
@@ -42,6 +42,7 @@
V(Map, shared_function_info_map,
SharedFunctionInfoMap) \
V(Map, meta_map,
MetaMap) \
V(Map, heap_number_map,
HeapNumberMap) \
+ V(Map, mutable_heap_number_map,
MutableHeapNumberMap) \
V(Map, native_context_map,
NativeContextMap) \
V(Map, fixed_array_map,
FixedArrayMap) \
V(Map, code_map,
CodeMap) \
@@ -230,6 +231,7 @@
V(shared_function_info_map) \
V(meta_map) \
V(heap_number_map) \
+ V(mutable_heap_number_map) \
V(native_context_map) \
V(fixed_array_map) \
V(code_map) \
@@ -1460,7 +1462,9 @@
// Allocated a HeapNumber from value.
MUST_USE_RESULT AllocationResult AllocateHeapNumber(
- double value, PretenureFlag pretenure = NOT_TENURED);
+ double value,
+ MutableMode mode = IMMUTABLE,
+ PretenureFlag pretenure = NOT_TENURED);
// Allocate a byte array of the specified length
MUST_USE_RESULT AllocationResult AllocateByteArray(
=======================================
--- /branches/bleeding_edge/src/hydrogen.cc Tue Jul 1 14:52:14 2014 UTC
+++ /branches/bleeding_edge/src/hydrogen.cc Tue Jul 1 15:02:31 2014 UTC
@@ -5781,8 +5781,9 @@
HInstruction* heap_number = Add<HAllocate>(heap_number_size,
HType::HeapObject(),
NOT_TENURED,
- HEAP_NUMBER_TYPE);
- AddStoreMapConstant(heap_number,
isolate()->factory()->heap_number_map());
+ MUTABLE_HEAP_NUMBER_TYPE);
+ AddStoreMapConstant(
+ heap_number, isolate()->factory()->mutable_heap_number_map());
Add<HStoreNamedField>(heap_number,
HObjectAccess::ForHeapNumberValue(),
value);
instr = New<HStoreNamedField>(checked_object->ActualValue(),
@@ -10950,11 +10951,14 @@
// 2) we can just use the mode of the parent object for pretenuring
HInstruction* double_box =
Add<HAllocate>(heap_number_constant, HType::HeapObject(),
- pretenure_flag, HEAP_NUMBER_TYPE);
+ pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
AddStoreMapConstant(double_box,
- isolate()->factory()->heap_number_map());
- Add<HStoreNamedField>(double_box,
HObjectAccess::ForHeapNumberValue(),
- Add<HConstant>(value));
+ isolate()->factory()->mutable_heap_number_map());
+ // Unwrap the mutable heap number from the boilerplate.
+ HValue* double_value =
+ Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
+ Add<HStoreNamedField>(
+ double_box, HObjectAccess::ForHeapNumberValue(), double_value);
value_instruction = double_box;
} else if (representation.IsSmi()) {
value_instruction = value->IsUninitialized()
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Tue Jul 1
15:02:31 2014 UTC
@@ -1683,14 +1683,18 @@
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
- Label* gc_required) {
+ Label* gc_required,
+ MutableMode mode) {
// Allocate heap number in new space.
Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
TAG_OBJECT);
+ Handle<Map> map = mode == MUTABLE
+ ? isolate()->factory()->mutable_heap_number_map()
+ : isolate()->factory()->heap_number_map();
+
// Set the map.
- mov(FieldOperand(result, HeapObject::kMapOffset),
- Immediate(isolate()->factory()->heap_number_map()));
+ mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
}
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Jun 30
10:19:31 2014 UTC
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Tue Jul 1
15:02:31 2014 UTC
@@ -638,7 +638,8 @@
void AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
- Label* gc_required);
+ Label* gc_required,
+ MutableMode mode = IMMUTABLE);
// Allocate a sequential string. All the header fields of the string
object
// are initialized.
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Jul 1 12:12:34
2014 UTC
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Jul 1 15:02:31
2014 UTC
@@ -523,7 +523,7 @@
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
- __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow);
+ __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE);
__ JumpIfNotSmi(value_reg, &heap_number);
__ SmiUntag(value_reg);
=======================================
--- /branches/bleeding_edge/src/json-parser.h Mon Jun 30 13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/json-parser.h Tue Jul 1 15:02:31 2014 UTC
@@ -387,11 +387,9 @@
Representation expected_representation =
details.representation();
if (value->FitsRepresentation(expected_representation)) {
- // If the target representation is double and the value is
already
- // double, use the existing box.
- if (value->IsSmi() && expected_representation.IsDouble()) {
- value = factory()->NewHeapNumber(
- Handle<Smi>::cast(value)->value());
+ if (expected_representation.IsDouble()) {
+ value = Object::NewStorageFor(isolate(), value,
+ expected_representation);
} else if (expected_representation.IsHeapObject() &&
!target->instance_descriptors()->GetFieldType(
descriptor)->NowContains(value)) {
=======================================
--- /branches/bleeding_edge/src/json-stringifier.h Mon Jun 30 10:19:31 2014
UTC
+++ /branches/bleeding_edge/src/json-stringifier.h Tue Jul 1 15:02:31 2014
UTC
@@ -407,6 +407,7 @@
switch (HeapObject::cast(*object)->map()->instance_type()) {
case HEAP_NUMBER_TYPE:
+ case MUTABLE_HEAP_NUMBER_TYPE:
if (deferred_string_key) SerializeDeferredKey(comma, key);
return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
case ODDBALL_TYPE:
=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Mon Jun 30 13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/mark-compact.cc Tue Jul 1 15:02:31 2014 UTC
@@ -292,6 +292,7 @@
case CODE_TYPE:
case FIXED_DOUBLE_ARRAY_TYPE:
case HEAP_NUMBER_TYPE:
+ case MUTABLE_HEAP_NUMBER_TYPE:
case INTERCEPTOR_INFO_TYPE:
case ODDBALL_TYPE:
case SCRIPT_TYPE:
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Tue Jul 1
15:02:31 2014 UTC
@@ -3274,14 +3274,19 @@
Register scratch2,
Register heap_number_map,
Label* need_gc,
- TaggingMode tagging_mode) {
+ TaggingMode tagging_mode,
+ MutableMode mode) {
// Allocate an object in the heap for the heap number and tag it as a
heap
// object.
Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
+ Heap::RootListIndex map_index = mode == MUTABLE
+ ? Heap::kMutableHeapNumberMapRootIndex
+ : Heap::kHeapNumberMapRootIndex;
+ AssertIsRoot(heap_number_map, map_index);
+
// Store heap number map in the allocated object.
- AssertIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
if (tagging_mode == TAG_RESULT) {
sw(heap_number_map, FieldMemOperand(result, HeapObject::kMapOffset));
} else {
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.h Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/mips/macro-assembler-mips.h Tue Jul 1
15:02:31 2014 UTC
@@ -546,7 +546,8 @@
Register scratch2,
Register heap_number_map,
Label* gc_required,
- TaggingMode tagging_mode = TAG_RESULT);
+ TaggingMode tagging_mode = TAG_RESULT,
+ MutableMode mode = IMMUTABLE);
void AllocateHeapNumberWithValue(Register result,
FPURegister value,
Register scratch1,
=======================================
--- /branches/bleeding_edge/src/mips/stub-cache-mips.cc Mon Jun 30 10:19:31
2014 UTC
+++ /branches/bleeding_edge/src/mips/stub-cache-mips.cc Tue Jul 1 15:02:31
2014 UTC
@@ -413,8 +413,9 @@
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
- __ LoadRoot(scratch3, Heap::kHeapNumberMapRootIndex);
- __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow);
+ __ LoadRoot(scratch3, Heap::kMutableHeapNumberMapRootIndex);
+ __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow,
+ TAG_RESULT, MUTABLE);
__ JumpIfNotSmi(value_reg, &heap_number);
__ SmiUntag(scratch1, value_reg);
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Mon Jun 30 10:19:31 2014
UTC
+++ /branches/bleeding_edge/src/objects-debug.cc Tue Jul 1 15:02:31 2014
UTC
@@ -54,6 +54,7 @@
Map::cast(this)->MapVerify();
break;
case HEAP_NUMBER_TYPE:
+ case MUTABLE_HEAP_NUMBER_TYPE:
HeapNumber::cast(this)->HeapNumberVerify();
break;
case FIXED_ARRAY_TYPE:
@@ -205,7 +206,7 @@
void HeapNumber::HeapNumberVerify() {
- CHECK(IsHeapNumber());
+ CHECK(IsHeapNumber() || IsMutableHeapNumber());
}
@@ -263,7 +264,7 @@
Representation r = descriptors->GetDetails(i).representation();
FieldIndex index = FieldIndex::ForDescriptor(map(), i);
Object* value = RawFastPropertyAt(index);
- if (r.IsDouble()) ASSERT(value->IsHeapNumber());
+ if (r.IsDouble()) ASSERT(value->IsMutableHeapNumber());
if (value->IsUninitialized()) continue;
if (r.IsSmi()) ASSERT(value->IsSmi());
if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Tue Jul 1 12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Tue Jul 1 15:02:31 2014 UTC
@@ -165,6 +165,7 @@
TYPE_CHECKER(HeapNumber, HEAP_NUMBER_TYPE)
+TYPE_CHECKER(MutableHeapNumber, MUTABLE_HEAP_NUMBER_TYPE)
TYPE_CHECKER(Symbol, SYMBOL_TYPE)
@@ -277,10 +278,27 @@
return handle(Smi::FromInt(0), isolate);
}
if (!representation.IsDouble()) return object;
+ double value;
if (object->IsUninitialized()) {
- return isolate->factory()->NewHeapNumber(0);
+ value = 0;
+ } else if (object->IsMutableHeapNumber()) {
+ value = HeapNumber::cast(*object)->value();
+ } else {
+ value = object->Number();
+ }
+ return isolate->factory()->NewHeapNumber(value, MUTABLE);
+}
+
+
+Handle<Object> Object::WrapForRead(Isolate* isolate,
+ Handle<Object> object,
+ Representation representation) {
+ ASSERT(!object->IsUninitialized());
+ if (!representation.IsDouble()) {
+ ASSERT(object->FitsRepresentation(representation));
+ return object;
}
- return isolate->factory()->NewHeapNumber(object->Number());
+ return
isolate->factory()->NewHeapNumber(HeapNumber::cast(*object)->value());
}
@@ -3079,7 +3097,6 @@
CAST_ACCESSOR(Foreign)
CAST_ACCESSOR(FreeSpace)
CAST_ACCESSOR(GlobalObject)
-CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(JSArray)
CAST_ACCESSOR(JSArrayBuffer)
@@ -5949,6 +5966,18 @@
ACCESSORS(JSValue, value, Object, kValueOffset)
+HeapNumber* HeapNumber::cast(Object* object) {
+ SLOW_ASSERT(object->IsHeapNumber() || object->IsMutableHeapNumber());
+ return reinterpret_cast<HeapNumber*>(object);
+}
+
+
+const HeapNumber* HeapNumber::cast(const Object* object) {
+ SLOW_ASSERT(object->IsHeapNumber() || object->IsMutableHeapNumber());
+ return reinterpret_cast<const HeapNumber*>(object);
+}
+
+
ACCESSORS(JSDate, value, Object, kValueOffset)
ACCESSORS(JSDate, cache_stamp, Object, kCacheStampOffset)
ACCESSORS(JSDate, year, Object, kYearOffset)
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Mon Jun 30 10:19:31 2014
UTC
+++ /branches/bleeding_edge/src/objects-printer.cc Tue Jul 1 15:02:31 2014
UTC
@@ -64,6 +64,11 @@
case HEAP_NUMBER_TYPE:
HeapNumber::cast(this)->HeapNumberPrint(out);
break;
+ case MUTABLE_HEAP_NUMBER_TYPE:
+ PrintF(out, "<mutable ");
+ HeapNumber::cast(this)->HeapNumberPrint(out);
+ PrintF(out, ">");
+ break;
case FIXED_DOUBLE_ARRAY_TYPE:
FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(out);
break;
=======================================
--- /branches/bleeding_edge/src/objects-visiting.cc Mon Jun 30 10:19:31
2014 UTC
+++ /branches/bleeding_edge/src/objects-visiting.cc Tue Jul 1 15:02:31
2014 UTC
@@ -148,6 +148,7 @@
return kVisitJSFunction;
case HEAP_NUMBER_TYPE:
+ case MUTABLE_HEAP_NUMBER_TYPE:
#define EXTERNAL_ARRAY_CASE(Type, type, TYPE, ctype,
size) \
case EXTERNAL_##TYPE##_ARRAY_TYPE:
=======================================
--- /branches/bleeding_edge/src/objects.cc Mon Jun 30 13:48:57 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Tue Jul 1 15:02:31 2014 UTC
@@ -1540,6 +1540,11 @@
HeapNumber::cast(this)->HeapNumberPrint(accumulator);
accumulator->Put('>');
break;
+ case MUTABLE_HEAP_NUMBER_TYPE:
+ accumulator->Add("<MutableNumber: ");
+ HeapNumber::cast(this)->HeapNumberPrint(accumulator);
+ accumulator->Put('>');
+ break;
case JS_PROXY_TYPE:
accumulator->Add("<JSProxy>");
break;
@@ -1665,6 +1670,7 @@
break;
case HEAP_NUMBER_TYPE:
+ case MUTABLE_HEAP_NUMBER_TYPE:
case FILLER_TYPE:
case BYTE_ARRAY_TYPE:
case FREE_SPACE_TYPE:
@@ -1706,7 +1712,7 @@
void HeapNumber::HeapNumberPrint(FILE* out) {
- PrintF(out, "%.16g", Number());
+ PrintF(out, "%.16g", value());
}
@@ -1718,7 +1724,7 @@
// print that using vsnprintf (which may truncate but never allocate if
// there is no more space in the buffer).
EmbeddedVector<char, 100> buffer;
- SNPrintF(buffer, "%.16g", Number());
+ SNPrintF(buffer, "%.16g", value());
accumulator->Add("%s", buffer.start());
}
@@ -2070,8 +2076,8 @@
DescriptorArray* new_desc = target->instance_descriptors();
int limit = NumberOfOwnDescriptors();
for (int i = 0; i < limit; i++) {
- if (new_desc->GetDetails(i).representation().IsDouble() &&
- !old_desc->GetDetails(i).representation().IsDouble()) {
+ if (new_desc->GetDetails(i).representation().IsDouble() !=
+ old_desc->GetDetails(i).representation().IsDouble()) {
return true;
}
}
@@ -2168,7 +2174,7 @@
PropertyDetails details = new_map->GetLastDescriptorDetails();
Handle<Object> value;
if (details.representation().IsDouble()) {
- value = isolate->factory()->NewHeapNumber(0);
+ value = isolate->factory()->NewHeapNumber(0, MUTABLE);
} else {
value = isolate->factory()->uninitialized_value();
}
@@ -2216,6 +2222,9 @@
value = handle(Smi::FromInt(0), isolate);
}
value = Object::NewStorageFor(isolate, value,
details.representation());
+ } else if (old_details.representation().IsDouble() &&
+ !details.representation().IsDouble()) {
+ value = Object::WrapForRead(isolate, value,
old_details.representation());
}
ASSERT(!(details.representation().IsDouble() && value->IsSmi()));
int target_index = new_descriptors->GetFieldIndex(i) - inobject;
@@ -2228,7 +2237,7 @@
if (details.type() != FIELD) continue;
Handle<Object> value;
if (details.representation().IsDouble()) {
- value = isolate->factory()->NewHeapNumber(0);
+ value = isolate->factory()->NewHeapNumber(0, MUTABLE);
} else {
value = isolate->factory()->uninitialized_value();
}
@@ -3975,6 +3984,7 @@
// Nothing more to be done.
if (value->IsUninitialized()) return;
HeapNumber* box = HeapNumber::cast(RawFastPropertyAt(index));
+ ASSERT(box->IsMutableHeapNumber());
box->set_value(value->Number());
} else {
FastPropertyAtPut(index, value);
@@ -4644,6 +4654,11 @@
FieldIndex index = FieldIndex::ForDescriptor(*map, i);
Handle<Object> value(
object->RawFastPropertyAt(index), isolate);
+ if (details.representation().IsDouble()) {
+ ASSERT(value->IsMutableHeapNumber());
+ Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
+ value = isolate->factory()->NewHeapNumber(old->value());
+ }
PropertyDetails d =
PropertyDetails(details.attributes(), NORMAL, i + 1);
dictionary = NameDictionary::Add(dictionary, key, value, d);
@@ -5811,7 +5826,7 @@
FieldIndex index) {
Isolate* isolate = object->GetIsolate();
Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
- return Object::NewStorageFor(isolate, raw_value, representation);
+ return Object::WrapForRead(isolate, raw_value, representation);
}
@@ -7002,7 +7017,7 @@
Object* property =
RawFastPropertyAt(FieldIndex::ForDescriptor(map(), i));
if (descs->GetDetails(i).representation().IsDouble()) {
- ASSERT(property->IsHeapNumber());
+ ASSERT(property->IsMutableHeapNumber());
if (value->IsNumber() && property->Number() == value->Number()) {
return descs->GetKey(i);
}
=======================================
--- /branches/bleeding_edge/src/objects.h Tue Jul 1 12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Tue Jul 1 15:02:31 2014 UTC
@@ -168,6 +168,12 @@
};
+enum MutableMode {
+ MUTABLE,
+ IMMUTABLE
+};
+
+
static const int kGrowICDelta = STORE_AND_GROW_NO_TRANSITION -
STANDARD_STORE;
STATIC_ASSERT(STANDARD_STORE == 0);
@@ -352,6 +358,7 @@
V(PROPERTY_CELL_TYPE)
\
\
V(HEAP_NUMBER_TYPE)
\
+
V(MUTABLE_HEAP_NUMBER_TYPE)
\
V(FOREIGN_TYPE)
\
V(BYTE_ARRAY_TYPE)
\
V(FREE_SPACE_TYPE)
\
@@ -680,6 +687,7 @@
// "Data", objects that cannot contain non-map-word pointers to heap
// objects.
HEAP_NUMBER_TYPE,
+ MUTABLE_HEAP_NUMBER_TYPE,
FOREIGN_TYPE,
BYTE_ARRAY_TYPE,
FREE_SPACE_TYPE,
@@ -900,6 +908,7 @@
#define HEAP_OBJECT_TYPE_LIST(V) \
V(HeapNumber) \
+ V(MutableHeapNumber) \
V(Name) \
V(UniqueName) \
V(String) \
@@ -1427,7 +1436,7 @@
} else if (FLAG_track_fields && representation.IsSmi()) {
return IsSmi();
} else if (FLAG_track_double_fields && representation.IsDouble()) {
- return IsNumber();
+ return IsMutableHeapNumber() || IsNumber();
} else if (FLAG_track_heap_object_fields &&
representation.IsHeapObject()) {
return IsHeapObject();
}
@@ -1440,6 +1449,10 @@
Handle<Object> object,
Representation
representation);
+ inline static Handle<Object> WrapForRead(Isolate* isolate,
+ Handle<Object> object,
+ Representation representation);
+
// Returns true if the object is of the correct type to be used as a
// implementation of a JSObject's elements.
inline bool HasValidElements();
=======================================
--- /branches/bleeding_edge/src/runtime.cc Tue Jul 1 12:12:34 2014 UTC
+++ /branches/bleeding_edge/src/runtime.cc Tue Jul 1 15:02:31 2014 UTC
@@ -14542,8 +14542,8 @@
object->properties()->length());
}
Handle<Object> raw_value(object->RawFastPropertyAt(field_index),
isolate);
- RUNTIME_ASSERT(raw_value->IsNumber() || raw_value->IsUninitialized());
- return *Object::NewStorageFor(isolate, raw_value,
Representation::Double());
+ RUNTIME_ASSERT(raw_value->IsMutableHeapNumber());
+ return *Object::WrapForRead(isolate, raw_value,
Representation::Double());
}
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Tue Jul 1
15:02:31 2014 UTC
@@ -4593,12 +4593,17 @@
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch,
- Label* gc_required) {
+ Label* gc_required,
+ MutableMode mode) {
// Allocate heap number in new space.
Allocate(HeapNumber::kSize, result, scratch, no_reg, gc_required,
TAG_OBJECT);
+ Heap::RootListIndex map_index = mode == MUTABLE
+ ? Heap::kMutableHeapNumberMapRootIndex
+ : Heap::kHeapNumberMapRootIndex;
+
// Set the map.
- LoadRoot(kScratchRegister, Heap::kHeapNumberMapRootIndex);
+ LoadRoot(kScratchRegister, map_index);
movp(FieldOperand(result, HeapObject::kMapOffset), kScratchRegister);
}
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Jun 30
10:19:31 2014 UTC
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue Jul 1
15:02:31 2014 UTC
@@ -1186,7 +1186,8 @@
// space is full.
void AllocateHeapNumber(Register result,
Register scratch,
- Label* gc_required);
+ Label* gc_required,
+ MutableMode mode = IMMUTABLE);
// Allocate a sequential string. All the header fields of the string
object
// are initialized.
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Jul 1 12:12:34
2014 UTC
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Tue Jul 1 15:02:31
2014 UTC
@@ -489,7 +489,7 @@
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
- __ AllocateHeapNumber(storage_reg, scratch1, slow);
+ __ AllocateHeapNumber(storage_reg, scratch1, slow, MUTABLE);
__ JumpIfNotSmi(value_reg, &heap_number);
__ SmiToInteger32(scratch1, value_reg);
=======================================
--- /branches/bleeding_edge/src/x87/macro-assembler-x87.cc Mon Jun 30
13:25:46 2014 UTC
+++ /branches/bleeding_edge/src/x87/macro-assembler-x87.cc Tue Jul 1
15:02:31 2014 UTC
@@ -1576,14 +1576,18 @@
void MacroAssembler::AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
- Label* gc_required) {
+ Label* gc_required,
+ MutableMode mode) {
// Allocate heap number in new space.
Allocate(HeapNumber::kSize, result, scratch1, scratch2, gc_required,
TAG_OBJECT);
+ Handle<Map> map = mode == MUTABLE
+ ? isolate()->factory()->mutable_heap_number_map()
+ : isolate()->factory()->heap_number_map();
+
// Set the map.
- mov(FieldOperand(result, HeapObject::kMapOffset),
- Immediate(isolate()->factory()->heap_number_map()));
+ mov(FieldOperand(result, HeapObject::kMapOffset), Immediate(map));
}
=======================================
--- /branches/bleeding_edge/src/x87/macro-assembler-x87.h Mon Jun 30
10:19:31 2014 UTC
+++ /branches/bleeding_edge/src/x87/macro-assembler-x87.h Tue Jul 1
15:02:31 2014 UTC
@@ -617,7 +617,8 @@
void AllocateHeapNumber(Register result,
Register scratch1,
Register scratch2,
- Label* gc_required);
+ Label* gc_required,
+ MutableMode mode = IMMUTABLE);
// Allocate a sequential string. All the header fields of the string
object
// are initialized.
=======================================
--- /branches/bleeding_edge/src/x87/stub-cache-x87.cc Tue Jul 1 13:34:18
2014 UTC
+++ /branches/bleeding_edge/src/x87/stub-cache-x87.cc Tue Jul 1 15:02:31
2014 UTC
@@ -523,7 +523,7 @@
}
} else if (representation.IsDouble()) {
Label do_store, heap_number;
- __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow);
+ __ AllocateHeapNumber(storage_reg, scratch1, scratch2, slow, MUTABLE);
__ JumpIfNotSmi(value_reg, &heap_number);
__ SmiUntag(value_reg);
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Tue Jul 1
12:12:34 2014 UTC
+++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Tue Jul 1
15:02:31 2014 UTC
@@ -1688,7 +1688,7 @@
v8::HandleScope scope(env->GetIsolate());
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
- CompileRun("a = { s_prop: \'value\', n_prop: 0.1 };");
+ CompileRun("a = { s_prop: \'value\', n_prop: \'value2\' };");
const v8::HeapSnapshot* snapshot =
heap_profiler->TakeHeapSnapshot(v8_str("value"));
CHECK(ValidateSnapshot(snapshot));
@@ -1709,10 +1709,9 @@
CHECK(js_s_prop == heap_profiler->FindObjectById(s_prop->GetId()));
const v8::HeapGraphNode* n_prop =
GetProperty(obj, v8::HeapGraphEdge::kProperty, "n_prop");
- v8::Local<v8::Number> js_n_prop =
- js_obj->Get(v8_str("n_prop")).As<v8::Number>();
- CHECK(js_n_prop->NumberValue() ==
- heap_profiler->FindObjectById(n_prop->GetId())->NumberValue());
+ v8::Local<v8::String> js_n_prop =
+ js_obj->Get(v8_str("n_prop")).As<v8::String>();
+ CHECK(js_n_prop == heap_profiler->FindObjectById(n_prop->GetId()));
}
=======================================
--- /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Jul 1 08:32:47
2014 UTC
+++ /branches/bleeding_edge/test/mjsunit/mjsunit.status Tue Jul 1 15:02:31
2014 UTC
@@ -87,6 +87,7 @@
##############################################################################
# Skip long running tests that time out in debug mode.
'generated-transition-stub': [PASS, ['mode == debug', SKIP]],
+ 'migrations': [PASS, ['mode == debug', SLOW]],
##############################################################################
# This test sets the umask on a per-process basis and hence cannot be
--
--
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.