Revision: 23253
Author: [email protected]
Date: Thu Aug 21 00:04:56 2014 UTC
Log: Version 3.29.10 (based on bleeding_edge revision r23214)
ES6: Make sure we do not store -0 as the key in Map/Set (issue 3515).
Remove removed flags from tests.
Expose well-known Symbols to C++ API (Chromium issue 341423).
Implement ES6 Array.of() (issue 3427).
Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=23253
Added:
/trunk/test/mjsunit/deopt-global-accessor.js
/trunk/test/mjsunit/harmony/array-of.js
Modified:
/trunk/BUILD.gn
/trunk/ChangeLog
/trunk/include/v8.h
/trunk/src/api.cc
/trunk/src/arm64/lithium-codegen-arm64.cc
/trunk/src/arm64/lithium-codegen-arm64.h
/trunk/src/ast.cc
/trunk/src/ast.h
/trunk/src/collection.js
/trunk/src/compiler/arm/code-generator-arm.cc
/trunk/src/compiler/arm/instruction-selector-arm.cc
/trunk/src/compiler/arm64/code-generator-arm64.cc
/trunk/src/compiler/change-lowering.cc
/trunk/src/compiler/ia32/code-generator-ia32.cc
/trunk/src/compiler/instruction-codes.h
/trunk/src/compiler/instruction-selector.cc
/trunk/src/compiler/machine-node-factory.h
/trunk/src/compiler/machine-operator.h
/trunk/src/compiler/opcodes.h
/trunk/src/compiler/x64/code-generator-x64.cc
/trunk/src/harmony-array.js
/trunk/src/heap/gc-tracer.cc
/trunk/src/heap/gc-tracer.h
/trunk/src/heap/heap.h
/trunk/src/hydrogen.cc
/trunk/src/hydrogen.h
/trunk/src/lookup-inl.h
/trunk/src/lookup.cc
/trunk/src/lookup.h
/trunk/src/objects.cc
/trunk/src/objects.h
/trunk/src/parser.cc
/trunk/src/runtime.cc
/trunk/src/runtime.h
/trunk/src/stub-cache.cc
/trunk/src/stub-cache.h
/trunk/src/v8natives.js
/trunk/src/version.cc
/trunk/test/cctest/cctest.status
/trunk/test/cctest/compiler/test-run-machops.cc
/trunk/test/cctest/test-api.cc
/trunk/test/compiler-unittests/change-lowering-unittest.cc
/trunk/test/compiler-unittests/graph-unittest.cc
/trunk/test/compiler-unittests/graph-unittest.h
/trunk/test/compiler-unittests/instruction-selector-unittest.cc
/trunk/test/compiler-unittests/machine-operator-unittest.cc
/trunk/test/mjsunit/es6/collections.js
/trunk/test/mjsunit/es6/unscopables.js
/trunk/test/mjsunit/harmony/proxies-with-unscopables.js
/trunk/tools/generate-runtime-tests.py
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/deopt-global-accessor.js Thu Aug 21 00:04:56 2014
UTC
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+// Flags: --allow-natives-syntax
+
+x = 1;
+x = 2;
+x = 3;
+
+function f() {
+ return x;
+}
+
+f();
+f();
+f();
+%OptimizeFunctionOnNextCall(f);
+f();
+
+Object.defineProperty(this, "x", {get:function() { return 100; }});
+
+assertEquals(100, f());
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/harmony/array-of.js Thu Aug 21 00:04:56 2014 UTC
@@ -0,0 +1,164 @@
+// Copyright 2014 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.
+
+// Based on Mozilla Array.of() tests at
http://dxr.mozilla.org/mozilla-central/source/js/src/jit-test/tests/collections
+
+// Flags: --harmony-arrays
+
+
+
+// Array.of makes real arrays.
+
+function check(a) {
+ assertEquals(Object.getPrototypeOf(a), Array.prototype);
+ assertEquals(Array.isArray(a), true);
+ a[9] = 9;
+ assertEquals(a.length, 10);
+}
+
+
+check(Array.of());
+check(Array.of(0));
+check(Array.of(0, 1, 2));
+var f = Array.of;
+check(f());
+
+
+// Array.of basics
+
+var a = Array.of();
+
+assertEquals(a.length, 0);
+a = Array.of(undefined, null, 3.14, []);
+assertEquals(a, [undefined, null, 3.14, []]);
+a = [];
+for (var i = 0; i < 1000; i++)
+ a[i] = i;
+assertEquals(Array.of.apply(null, a), a);
+
+
+// Array.of does not leave holes
+
+assertEquals(Array.of(undefined), [undefined]);
+assertEquals(Array.of(undefined, undefined), [undefined, undefined]);
+assertEquals(Array.of.apply(null, [,,undefined]), [undefined, undefined,
undefined]);
+assertEquals(Array.of.apply(null, Array(4)), [undefined, undefined,
undefined, undefined]);
+
+
+// Array.of can be transplanted to other classes.
+
+var hits = 0;
+function Bag() {
+ hits++;
+}
+Bag.of = Array.of;
+
+hits = 0;
+var actual = Bag.of("zero", "one");
+assertEquals(hits, 1);
+
+hits = 0;
+var expected = new Bag;
+expected[0] = "zero";
+expected[1] = "one";
+expected.length = 2;
+assertEquals(areSame(actual, expected), true);
+
+hits = 0;
+actual = Array.of.call(Bag, "zero", "one");
+assertEquals(hits, 1);
+assertEquals(areSame(actual, expected), true);
+
+function areSame(object, array) {
+ var result = object.length == array.length;
+ for (var i = 0; i < object.length; i++) {
+ result = result && object[i] == array[i];
+ }
+ return result;
+}
+
+
+// Array.of does not trigger prototype setters.
+// (It defines elements rather than assigning to them.)
+
+var status = "pass";
+Object.defineProperty(Array.prototype, "0", {set: function(v) {status
= "FAIL 1"}});
+assertEquals(Array.of(1)[0], 1);
+assertEquals(status, "pass");
+
+Object.defineProperty(Bag.prototype, "0", {set: function(v) {status
= "FAIL 2"}});
+assertEquals(Bag.of(1)[0], 1);
+assertEquals(status, "pass");
+
+
+// Array.of passes the number of arguments to the constructor it calls.
+
+var hits = 0;
+
+function Herd(n) {
+ assertEquals(arguments.length, 1);
+ assertEquals(n, 5);
+ hits++;
+}
+
+Herd.of = Array.of;
+Herd.of("sheep", "cattle", "elephants", "whales", "seals");
+assertEquals(hits, 1);
+
+
+// Array.of calls a "length" setter if one is present.
+
+var hits = 0;
+var lastObj = null, lastVal = undefined;
+function setter(v) {
+ hits++;
+ lastObj = this;
+ lastVal = v;
+}
+
+// when the setter is on the new object
+function Pack() {
+ Object.defineProperty(this, "length", {set: setter});
+}
+Pack.of = Array.of;
+var pack = Pack.of("wolves", "cards", "cigarettes", "lies");
+assertEquals(lastObj, pack);
+assertEquals(lastVal, 4);
+
+// when the setter is on the new object's prototype
+function Bevy() {}
+Object.defineProperty(Bevy.prototype, "length", {set: setter});
+Bevy.of = Array.of;
+var bevy = Bevy.of("quail");
+assertEquals(lastObj, bevy);
+assertEquals(lastVal, 1);
+
+
+// Array.of does a strict assignment to the new object's .length.
+// The assignment is strict even if the code we're calling from is not
strict.
+
+function Empty() {}
+Empty.of = Array.of;
+Object.defineProperty(Empty.prototype, "length", {get: function() { return
0; }});
+
+var nothing = new Empty;
+nothing.length = 2; // no exception; this is not a strict mode assignment
+
+assertThrows(function() { Empty.of(); }, TypeError);
+
+
+// Check superficial features of Array.of.
+
+var desc = Object.getOwnPropertyDescriptor(Array, "of");
+
+assertEquals(desc.configurable, true);
+assertEquals(desc.enumerable, false);
+assertEquals(desc.writable, true);
+assertEquals(Array.of.length, 0);
+assertThrows(function() { new Array.of() }, TypeError); // not a
constructor
+
+// When the this-value passed in is not a constructor, the result is an
array.
+[undefined, null, false, "cow"].forEach(function(val) {
+ assertEquals(Array.isArray(Array.of(val)), true);
+});
=======================================
--- /trunk/BUILD.gn Wed Aug 20 13:33:20 2014 UTC
+++ /trunk/BUILD.gn Thu Aug 21 00:04:56 2014 UTC
@@ -509,8 +509,6 @@
"src/compiler/machine-operator-reducer.cc",
"src/compiler/machine-operator-reducer.h",
"src/compiler/machine-operator.h",
- "src/compiler/machine-type.cc",
- "src/compiler/machine-type.h",
"src/compiler/node-aux-data-inl.h",
"src/compiler/node-aux-data.h",
"src/compiler/node-cache.cc",
=======================================
--- /trunk/ChangeLog Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/ChangeLog Thu Aug 21 00:04:56 2014 UTC
@@ -1,3 +1,16 @@
+2014-08-21: Version 3.29.10
+
+ ES6: Make sure we do not store -0 as the key in Map/Set (issue
3515).
+
+ Remove removed flags from tests.
+
+ Expose well-known Symbols to C++ API (Chromium issue 341423).
+
+ Implement ES6 Array.of() (issue 3427).
+
+ Performance and stability improvements on all platforms.
+
+
2014-08-20: Version 3.29.9
Correctly handle holes when concat()ing double arrays (Chromium
issue
=======================================
--- /trunk/include/v8.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/include/v8.h Thu Aug 21 00:04:56 2014 UTC
@@ -1960,7 +1960,12 @@
// registry that is not accessible by (and cannot clash with) JavaScript
code.
static Local<Symbol> ForApi(Isolate *isolate, Local<String> name);
+ // Well-known symbols
+ static Local<Symbol> GetIterator(Isolate* isolate);
+ static Local<Symbol> GetUnscopables(Isolate* isolate);
+
V8_INLINE static Symbol* Cast(v8::Value* obj);
+
private:
Symbol();
static void CheckCast(v8::Value* obj);
=======================================
--- /trunk/src/api.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/api.cc Thu Aug 21 00:04:56 2014 UTC
@@ -3564,24 +3564,12 @@
}
-static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
- i::Handle<i::JSObject> receiver,
- i::Handle<i::String> name,
- i::LookupResult* lookup) {
- if (!lookup->IsProperty()) {
- // No real property was found.
- return Local<Value>();
- }
-
- // If the property being looked up is a callback, it can throw
- // an exception.
- EXCEPTION_PREAMBLE(isolate);
- i::LookupIterator it(receiver, name,
- i::Handle<i::JSReceiver>(lookup->holder(), isolate),
- i::LookupIterator::CHECK_DERIVED_SKIP_INTERCEPTOR);
+static Local<Value> GetPropertyByLookup(i::LookupIterator* it) {
+ // If the property being looked up is a callback, it can throw an
exception.
+ EXCEPTION_PREAMBLE(it->isolate());
i::Handle<i::Object> result;
- has_pending_exception = !i::Object::GetProperty(&it).ToHandle(&result);
- EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
+ has_pending_exception = !i::Object::GetProperty(it).ToHandle(&result);
+ EXCEPTION_BAILOUT_CHECK(it->isolate(), Local<Value>());
return Utils::ToLocal(result);
}
@@ -3596,9 +3584,11 @@
ENTER_V8(isolate);
i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
- i::LookupResult lookup(isolate);
- self_obj->LookupRealNamedPropertyInPrototypes(key_obj, &lookup);
- return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
+ i::PrototypeIterator iter(isolate, self_obj);
+ if (iter.IsAtEnd()) return Local<Value>();
+ i::LookupIterator it(i::PrototypeIterator::GetCurrent(iter), key_obj,
+ i::LookupIterator::CHECK_DERIVED_PROPERTY);
+ return GetPropertyByLookup(&it);
}
@@ -3609,9 +3599,9 @@
ENTER_V8(isolate);
i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
- i::LookupResult lookup(isolate);
- self_obj->LookupRealNamedProperty(key_obj, &lookup);
- return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
+ i::LookupIterator it(self_obj, key_obj,
+ i::LookupIterator::CHECK_DERIVED_PROPERTY);
+ return GetPropertyByLookup(&it);
}
@@ -4065,15 +4055,14 @@
i::Handle<i::String> property_name =
isolate->factory()->InternalizeOneByteString(
STATIC_ASCII_VECTOR("displayName"));
- i::LookupResult lookup(isolate);
- func->LookupRealNamedProperty(property_name, &lookup);
- if (lookup.IsFound()) {
- i::Object* value = lookup.GetLazyValue();
- if (value && value->IsString()) {
- i::String* name = i::String::cast(value);
- if (name->length() > 0) return
Utils::ToLocal(i::Handle<i::String>(name));
- }
+
+ i::Handle<i::Object> value =
+ i::JSObject::GetDataProperty(func, property_name);
+ if (value->IsString()) {
+ i::Handle<i::String> name = i::Handle<i::String>::cast(value);
+ if (name->length() > 0) return Utils::ToLocal(name);
}
+
return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
}
@@ -6152,43 +6141,57 @@
}
-Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
- i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
- i::Handle<i::String> i_name = Utils::OpenHandle(*name);
- i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
- i::Handle<i::String> part = i_isolate->factory()->for_string();
+static i::Handle<i::Symbol> SymbolFor(i::Isolate* isolate,
+ i::Handle<i::String> name,
+ i::Handle<i::String> part) {
+ i::Handle<i::JSObject> registry = isolate->GetSymbolRegistry();
i::Handle<i::JSObject> symbols =
i::Handle<i::JSObject>::cast(
i::Object::GetPropertyOrElement(registry,
part).ToHandleChecked());
i::Handle<i::Object> symbol =
- i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
+ i::Object::GetPropertyOrElement(symbols, name).ToHandleChecked();
if (!symbol->IsSymbol()) {
DCHECK(symbol->IsUndefined());
- symbol = i_isolate->factory()->NewSymbol();
- i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
- i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert();
+ symbol = isolate->factory()->NewSymbol();
+ i::Handle<i::Symbol>::cast(symbol)->set_name(*name);
+ i::JSObject::SetProperty(symbols, name, symbol, i::STRICT).Assert();
}
- return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
+ return i::Handle<i::Symbol>::cast(symbol);
+}
+
+
+Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ i::Handle<i::String> i_name = Utils::OpenHandle(*name);
+ i::Handle<i::String> part = i_isolate->factory()->for_string();
+ return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
}
Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
i::Handle<i::String> i_name = Utils::OpenHandle(*name);
- i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
i::Handle<i::String> part = i_isolate->factory()->for_api_string();
- i::Handle<i::JSObject> symbols =
- i::Handle<i::JSObject>::cast(
- i::Object::GetPropertyOrElement(registry,
part).ToHandleChecked());
- i::Handle<i::Object> symbol =
- i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
- if (!symbol->IsSymbol()) {
- DCHECK(symbol->IsUndefined());
- symbol = i_isolate->factory()->NewSymbol();
- i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
- i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert();
- }
- return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
+ return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
+}
+
+
+static Local<Symbol> GetWellKnownSymbol(Isolate* isolate, const char*
name) {
+ i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
+ i::Handle<i::String> i_name =
+ Utils::OpenHandle(*String::NewFromUtf8(isolate, name));
+ i::Handle<i::String> part = i_isolate->factory()->for_intern_string();
+ return Utils::ToLocal(SymbolFor(i_isolate, i_name, part));
+}
+
+
+Local<Symbol> v8::Symbol::GetIterator(Isolate* isolate) {
+ return GetWellKnownSymbol(isolate, "Symbol.iterator");
+}
+
+
+Local<Symbol> v8::Symbol::GetUnscopables(Isolate* isolate) {
+ return GetWellKnownSymbol(isolate, "Symbol.unscopables");
}
=======================================
--- /trunk/src/arm64/lithium-codegen-arm64.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/arm64/lithium-codegen-arm64.cc Thu Aug 21 00:04:56 2014 UTC
@@ -1226,17 +1226,7 @@
}
-Operand LCodeGen::ToOperand32I(LOperand* op) {
- return ToOperand32(op, SIGNED_INT32);
-}
-
-
-Operand LCodeGen::ToOperand32U(LOperand* op) {
- return ToOperand32(op, UNSIGNED_INT32);
-}
-
-
-Operand LCodeGen::ToOperand32(LOperand* op, IntegerSignedness signedness) {
+Operand LCodeGen::ToOperand32(LOperand* op) {
DCHECK(op != NULL);
if (op->IsRegister()) {
return Operand(ToRegister32(op));
@@ -1245,10 +1235,7 @@
HConstant* constant = chunk()->LookupConstant(const_op);
Representation r = chunk_->LookupLiteralRepresentation(const_op);
if (r.IsInteger32()) {
- DCHECK(constant->HasInteger32Value());
- return (signedness == SIGNED_INT32)
- ? Operand(constant->Integer32Value())
- : Operand(static_cast<uint32_t>(constant->Integer32Value()));
+ return Operand(constant->Integer32Value());
} else {
// Other constants not implemented.
Abort(kToOperand32UnsupportedImmediate);
@@ -1314,12 +1301,10 @@
}
-template<class LI>
-Operand LCodeGen::ToShiftedRightOperand32(LOperand* right, LI* shift_info,
- IntegerSignedness signedness) {
+template <class LI>
+Operand LCodeGen::ToShiftedRightOperand32(LOperand* right, LI* shift_info)
{
if (shift_info->shift() == NO_SHIFT) {
- return (signedness == SIGNED_INT32) ? ToOperand32I(right)
- : ToOperand32U(right);
+ return ToOperand32(right);
} else {
return Operand(
ToRegister32(right),
@@ -1501,7 +1486,7 @@
}
} else {
Register length = ToRegister32(instr->length());
- Operand index = ToOperand32I(instr->index());
+ Operand index = ToOperand32(instr->index());
__ Sub(result.W(), length, index);
__ Add(result.W(), result.W(), 1);
__ Ldr(result, MemOperand(arguments, result, UXTW, kPointerSizeLog2));
@@ -1525,7 +1510,7 @@
bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
Register result = ToRegister32(instr->result());
Register left = ToRegister32(instr->left());
- Operand right = ToShiftedRightOperand32I(instr->right(), instr);
+ Operand right = ToShiftedRightOperand32(instr->right(), instr);
if (can_overflow) {
__ Adds(result, left, right);
@@ -1804,7 +1789,7 @@
void LCodeGen::DoBitI(LBitI* instr) {
Register result = ToRegister32(instr->result());
Register left = ToRegister32(instr->left());
- Operand right = ToShiftedRightOperand32U(instr->right(), instr);
+ Operand right = ToShiftedRightOperand32(instr->right(), instr);
switch (instr->op()) {
case Token::BIT_AND: __ And(result, left, right); break;
@@ -1838,13 +1823,13 @@
DCHECK(instr->hydrogen()->index()->representation().IsInteger32());
DCHECK(instr->hydrogen()->length()->representation().IsInteger32());
if (instr->index()->IsConstantOperand()) {
- Operand index = ToOperand32I(instr->index());
+ Operand index = ToOperand32(instr->index());
Register length = ToRegister32(instr->length());
__ Cmp(length, index);
cond = CommuteCondition(cond);
} else {
Register index = ToRegister32(instr->index());
- Operand length = ToOperand32I(instr->length());
+ Operand length = ToOperand32(instr->length());
__ Cmp(index, length);
}
if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
@@ -2486,16 +2471,12 @@
} else {
if (instr->hydrogen_value()->representation().IsInteger32()) {
if (right->IsConstantOperand()) {
- EmitCompareAndBranch(instr,
- cond,
- ToRegister32(left),
- ToOperand32I(right));
+ EmitCompareAndBranch(instr, cond, ToRegister32(left),
+ ToOperand32(right));
} else {
// Commute the operands and the condition.
- EmitCompareAndBranch(instr,
- CommuteCondition(cond),
- ToRegister32(right),
- ToOperand32I(left));
+ EmitCompareAndBranch(instr, CommuteCondition(cond),
+ ToRegister32(right), ToOperand32(left));
}
} else {
DCHECK(instr->hydrogen_value()->representation().IsSmi());
@@ -3017,7 +2998,7 @@
Register result = ToRegister(instr->result());
Register base = ToRegister(instr->base_object());
if (instr->offset()->IsConstantOperand()) {
- __ Add(result, base, ToOperand32I(instr->offset()));
+ __ Add(result, base, ToOperand32(instr->offset()));
} else {
__ Add(result, base, Operand(ToRegister32(instr->offset()), SXTW));
}
@@ -4220,7 +4201,7 @@
if (instr->hydrogen()->representation().IsInteger32()) {
Register result = ToRegister32(instr->result());
Register left = ToRegister32(instr->left());
- Operand right = ToOperand32I(instr->right());
+ Operand right = ToOperand32(instr->right());
__ Cmp(left, right);
__ Csel(result, left, right, (op == HMathMinMax::kMathMax) ? ge : le);
@@ -5571,7 +5552,7 @@
bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
Register result = ToRegister32(instr->result());
Register left = ToRegister32(instr->left());
- Operand right = ToShiftedRightOperand32I(instr->right(), instr);
+ Operand right = ToShiftedRightOperand32(instr->right(), instr);
if (can_overflow) {
__ Subs(result, left, right);
=======================================
--- /trunk/src/arm64/lithium-codegen-arm64.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/arm64/lithium-codegen-arm64.h Thu Aug 21 00:04:56 2014 UTC
@@ -83,31 +83,17 @@
enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 };
// Support for converting LOperands to assembler types.
- // LOperand must be a register.
Register ToRegister(LOperand* op) const;
Register ToRegister32(LOperand* op) const;
Operand ToOperand(LOperand* op);
- Operand ToOperand32I(LOperand* op);
- Operand ToOperand32U(LOperand* op);
+ Operand ToOperand32(LOperand* op);
enum StackMode { kMustUseFramePointer, kCanUseStackPointer };
MemOperand ToMemOperand(LOperand* op,
StackMode stack_mode = kCanUseStackPointer)
const;
Handle<Object> ToHandle(LConstantOperand* op) const;
- template<class LI>
- Operand ToShiftedRightOperand32I(LOperand* right,
- LI* shift_info) {
- return ToShiftedRightOperand32(right, shift_info, SIGNED_INT32);
- }
- template<class LI>
- Operand ToShiftedRightOperand32U(LOperand* right,
- LI* shift_info) {
- return ToShiftedRightOperand32(right, shift_info, UNSIGNED_INT32);
- }
- template<class LI>
- Operand ToShiftedRightOperand32(LOperand* right,
- LI* shift_info,
- IntegerSignedness signedness);
+ template <class LI>
+ Operand ToShiftedRightOperand32(LOperand* right, LI* shift_info);
int JSShiftAmountFromLConstant(LOperand* constant) {
return ToInteger32(LConstantOperand::cast(constant)) & 0x1f;
@@ -158,8 +144,6 @@
Register object,
Register index);
- Operand ToOperand32(LOperand* op, IntegerSignedness signedness);
-
static Condition TokenToCondition(Token::Value op, bool is_unsigned);
void EmitGoto(int block);
void DoGap(LGap* instr);
=======================================
--- /trunk/src/ast.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/ast.cc Thu Aug 21 00:04:56 2014 UTC
@@ -590,18 +590,16 @@
bool Call::ComputeGlobalTarget(Handle<GlobalObject> global,
- LookupResult* lookup) {
+ LookupIterator* it) {
target_ = Handle<JSFunction>::null();
cell_ = Handle<Cell>::null();
- DCHECK(lookup->IsFound() &&
- lookup->type() == NORMAL &&
- lookup->holder() == *global);
- cell_ = Handle<Cell>(global->GetPropertyCell(lookup));
+ DCHECK(it->IsFound() &&
it->GetHolder<JSObject>().is_identical_to(global));
+ cell_ = it->GetPropertyCell();
if (cell_->value()->IsJSFunction()) {
Handle<JSFunction> candidate(JSFunction::cast(cell_->value()));
// If the function is in new space we assume it's more likely to
// change and thus prefer the general IC code.
- if (!lookup->isolate()->heap()->InNewSpace(*candidate)) {
+ if (!it->isolate()->heap()->InNewSpace(*candidate)) {
target_ = candidate;
return true;
}
=======================================
--- /trunk/src/ast.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/ast.h Thu Aug 21 00:04:56 2014 UTC
@@ -1799,7 +1799,7 @@
void set_allocation_site(Handle<AllocationSite> site) {
allocation_site_ = site;
}
- bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupResult*
lookup);
+ bool ComputeGlobalTarget(Handle<GlobalObject> global, LookupIterator*
it);
BailoutId ReturnId() const { return return_id_; }
=======================================
--- /trunk/src/collection.js Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/collection.js Thu Aug 21 00:04:56 2014 UTC
@@ -49,6 +49,13 @@
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.add', this]);
}
+ // Normalize -0 to +0 as required by the spec.
+ // Even though we use SameValueZero as the comparison for the keys we
don't
+ // want to ever store -0 as the key since the key is directly exposed
when
+ // doing iteration.
+ if (key === 0) {
+ key = 0;
+ }
return %SetAdd(this, key);
}
@@ -186,6 +193,13 @@
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.set', this]);
}
+ // Normalize -0 to +0 as required by the spec.
+ // Even though we use SameValueZero as the comparison for the keys we
don't
+ // want to ever store -0 as the key since the key is directly exposed
when
+ // doing iteration.
+ if (key === 0) {
+ key = 0;
+ }
return %MapSet(this, key, value);
}
=======================================
--- /trunk/src/compiler/arm/code-generator-arm.cc Wed Aug 20 00:06:26 2014
UTC
+++ /trunk/src/compiler/arm/code-generator-arm.cc Thu Aug 21 00:04:56 2014
UTC
@@ -158,6 +158,10 @@
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
+ case kArchTruncateDoubleToI:
+ __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
i.OutputSBit());
=======================================
--- /trunk/src/compiler/arm/instruction-selector-arm.cc Wed Aug 20 00:06:26
2014 UTC
+++ /trunk/src/compiler/arm/instruction-selector-arm.cc Thu Aug 21 00:04:56
2014 UTC
@@ -74,6 +74,7 @@
case kArchNop:
case kArchRet:
case kArchDeoptimize:
+ case kArchTruncateDoubleToI:
case kArmMul:
case kArmMla:
case kArmMls:
=======================================
--- /trunk/src/compiler/arm64/code-generator-arm64.cc Wed Aug 20 00:06:26
2014 UTC
+++ /trunk/src/compiler/arm64/code-generator-arm64.cc Thu Aug 21 00:04:56
2014 UTC
@@ -149,6 +149,9 @@
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
break;
}
+ case kArchTruncateDoubleToI:
+ __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
+ break;
case kArm64Add:
__ Add(i.OutputRegister(), i.InputRegister(0), i.InputOperand(1));
break;
=======================================
--- /trunk/src/compiler/change-lowering.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/change-lowering.cc Thu Aug 21 00:04:56 2014 UTC
@@ -124,7 +124,7 @@
Node* load = graph()->NewNode(
machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(),
graph()->NewNode(common()->ControlEffect(), if_true));
- Node* change = graph()->NewNode(machine()->ChangeFloat64ToInt32(), load);
+ Node* change = graph()->NewNode(machine()->TruncateFloat64ToInt32(),
load);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* integer =
=======================================
--- /trunk/src/compiler/ia32/code-generator-ia32.cc Wed Aug 20 00:06:26
2014 UTC
+++ /trunk/src/compiler/ia32/code-generator-ia32.cc Thu Aug 21 00:04:56
2014 UTC
@@ -129,6 +129,9 @@
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
break;
}
+ case kArchTruncateDoubleToI:
+ __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
+ break;
case kIA32Add:
if (HasImmediateInput(instr, 1)) {
__ add(i.InputOperand(0), i.InputImmediate(1));
=======================================
--- /trunk/src/compiler/instruction-codes.h Mon Aug 4 06:49:33 2014 UTC
+++ /trunk/src/compiler/instruction-codes.h Thu Aug 21 00:04:56 2014 UTC
@@ -33,6 +33,7 @@
V(ArchJmp) \
V(ArchNop) \
V(ArchRet) \
+ V(ArchTruncateDoubleToI) \
TARGET_ARCH_OPCODE_LIST(V)
enum ArchOpcode {
=======================================
--- /trunk/src/compiler/instruction-selector.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/instruction-selector.cc Thu Aug 21 00:04:56 2014 UTC
@@ -587,6 +587,8 @@
return VisitChangeInt32ToInt64(node);
case IrOpcode::kChangeUint32ToUint64:
return VisitChangeUint32ToUint64(node);
+ case IrOpcode::kTruncateFloat64ToInt32:
+ return VisitTruncateFloat64ToInt32(node);
case IrOpcode::kTruncateInt64ToInt32:
return VisitTruncateInt64ToInt32(node);
case IrOpcode::kFloat64Add:
@@ -688,6 +690,13 @@
FlagsContinuation cont(kSignedLessThanOrEqual, node);
VisitWord64Compare(node, &cont);
}
+
+
+void InstructionSelector::VisitTruncateFloat64ToInt32(Node* node) {
+ OperandGenerator g(this);
+ Emit(kArchTruncateDoubleToI, g.DefineAsRegister(node),
+ g.UseDoubleRegister(node->InputAt(0)));
+}
void InstructionSelector::VisitFloat64Equal(Node* node) {
=======================================
--- /trunk/src/compiler/machine-node-factory.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/machine-node-factory.h Thu Aug 21 00:04:56 2014 UTC
@@ -358,6 +358,9 @@
Node* ChangeUint32ToUint64(Node* a) {
return NEW_NODE_1(MACHINE()->ChangeUint32ToUint64(), a);
}
+ Node* TruncateFloat64ToInt32(Node* a) {
+ return NEW_NODE_1(MACHINE()->TruncateFloat64ToInt32(), a);
+ }
Node* TruncateInt64ToInt32(Node* a) {
return NEW_NODE_1(MACHINE()->TruncateInt64ToInt32(), a);
}
=======================================
--- /trunk/src/compiler/machine-operator.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/machine-operator.h Thu Aug 21 00:04:56 2014 UTC
@@ -133,6 +133,9 @@
// Sign/zero extend int32/uint32 to int64/uint64.
Operator* ChangeInt32ToInt64() { UNOP(ChangeInt32ToInt64); }
Operator* ChangeUint32ToUint64() { UNOP(ChangeUint32ToUint64); }
+
+ // Truncate double to int32 using JavaScript semantics.
+ Operator* TruncateFloat64ToInt32() { UNOP(TruncateFloat64ToInt32); }
// Truncate the high order bits and convert the remaining bits to int32.
Operator* TruncateInt64ToInt32() { UNOP(TruncateInt64ToInt32); }
=======================================
--- /trunk/src/compiler/opcodes.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/compiler/opcodes.h Thu Aug 21 00:04:56 2014 UTC
@@ -159,61 +159,62 @@
V(StoreElement)
// Opcodes for Machine-level operators.
-#define MACHINE_OP_LIST(V) \
- V(Load) \
- V(Store) \
- V(Word32And) \
- V(Word32Or) \
- V(Word32Xor) \
- V(Word32Shl) \
- V(Word32Shr) \
- V(Word32Sar) \
- V(Word32Ror) \
- V(Word32Equal) \
- V(Word64And) \
- V(Word64Or) \
- V(Word64Xor) \
- V(Word64Shl) \
- V(Word64Shr) \
- V(Word64Sar) \
- V(Word64Ror) \
- V(Word64Equal) \
- V(Int32Add) \
- V(Int32AddWithOverflow) \
- V(Int32Sub) \
- V(Int32SubWithOverflow) \
- V(Int32Mul) \
- V(Int32Div) \
- V(Int32UDiv) \
- V(Int32Mod) \
- V(Int32UMod) \
- V(Int32LessThan) \
- V(Int32LessThanOrEqual) \
- V(Uint32LessThan) \
- V(Uint32LessThanOrEqual) \
- V(Int64Add) \
- V(Int64Sub) \
- V(Int64Mul) \
- V(Int64Div) \
- V(Int64UDiv) \
- V(Int64Mod) \
- V(Int64UMod) \
- V(Int64LessThan) \
- V(Int64LessThanOrEqual) \
- V(ChangeInt32ToFloat64) \
- V(ChangeUint32ToFloat64) \
- V(ChangeFloat64ToInt32) \
- V(ChangeFloat64ToUint32) \
- V(ChangeInt32ToInt64) \
- V(ChangeUint32ToUint64) \
- V(TruncateInt64ToInt32) \
- V(Float64Add) \
- V(Float64Sub) \
- V(Float64Mul) \
- V(Float64Div) \
- V(Float64Mod) \
- V(Float64Equal) \
- V(Float64LessThan) \
+#define MACHINE_OP_LIST(V) \
+ V(Load) \
+ V(Store) \
+ V(Word32And) \
+ V(Word32Or) \
+ V(Word32Xor) \
+ V(Word32Shl) \
+ V(Word32Shr) \
+ V(Word32Sar) \
+ V(Word32Ror) \
+ V(Word32Equal) \
+ V(Word64And) \
+ V(Word64Or) \
+ V(Word64Xor) \
+ V(Word64Shl) \
+ V(Word64Shr) \
+ V(Word64Sar) \
+ V(Word64Ror) \
+ V(Word64Equal) \
+ V(Int32Add) \
+ V(Int32AddWithOverflow) \
+ V(Int32Sub) \
+ V(Int32SubWithOverflow) \
+ V(Int32Mul) \
+ V(Int32Div) \
+ V(Int32UDiv) \
+ V(Int32Mod) \
+ V(Int32UMod) \
+ V(Int32LessThan) \
+ V(Int32LessThanOrEqual) \
+ V(Uint32LessThan) \
+ V(Uint32LessThanOrEqual) \
+ V(Int64Add) \
+ V(Int64Sub) \
+ V(Int64Mul) \
+ V(Int64Div) \
+ V(Int64UDiv) \
+ V(Int64Mod) \
+ V(Int64UMod) \
+ V(Int64LessThan) \
+ V(Int64LessThanOrEqual) \
+ V(ChangeInt32ToFloat64) \
+ V(ChangeUint32ToFloat64) \
+ V(ChangeFloat64ToInt32) \
+ V(ChangeFloat64ToUint32) \
+ V(ChangeInt32ToInt64) \
+ V(ChangeUint32ToUint64) \
+ V(TruncateFloat64ToInt32) \
+ V(TruncateInt64ToInt32) \
+ V(Float64Add) \
+ V(Float64Sub) \
+ V(Float64Mul) \
+ V(Float64Div) \
+ V(Float64Mod) \
+ V(Float64Equal) \
+ V(Float64LessThan) \
V(Float64LessThanOrEqual)
#define VALUE_OP_LIST(V) \
=======================================
--- /trunk/src/compiler/x64/code-generator-x64.cc Wed Aug 20 00:06:26 2014
UTC
+++ /trunk/src/compiler/x64/code-generator-x64.cc Thu Aug 21 00:04:56 2014
UTC
@@ -222,6 +222,9 @@
__ call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
break;
}
+ case kArchTruncateDoubleToI:
+ __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
+ break;
case kX64Add32:
ASSEMBLE_BINOP(addl);
break;
=======================================
--- /trunk/src/harmony-array.js Thu May 1 00:05:11 2014 UTC
+++ /trunk/src/harmony-array.js Thu Aug 21 00:04:56 2014 UTC
@@ -122,12 +122,30 @@
array[i] = value;
return array;
}
+
+// ES6, draft 05-22-14, section 22.1.2.3
+function ArrayOf() {
+ var length = %_ArgumentsLength();
+ var constructor = this;
+ // TODO: Implement IsConstructor (ES6 section 7.2.5)
+ var array = IS_SPEC_FUNCTION(constructor) ? new constructor(length) : [];
+ for (var i = 0; i < length; i++) {
+ %AddElement(array, i, %_Arguments(i), NONE);
+ }
+ array.length = length;
+ return array;
+}
// -------------------------------------------------------------------
function HarmonyArrayExtendArrayPrototype() {
%CheckIsBootstrapping();
+ // Set up non-enumerable functions on the Array object.
+ InstallFunctions($Array, DONT_ENUM, $Array(
+ "of", ArrayOf
+ ));
+
// Set up the non-enumerable functions on the Array prototype object.
InstallFunctions($Array.prototype, DONT_ENUM, $Array(
"find", ArrayFind,
=======================================
--- /trunk/src/heap/gc-tracer.cc Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/heap/gc-tracer.cc Thu Aug 21 00:04:56 2014 UTC
@@ -103,6 +103,8 @@
current_.start_object_size = heap_->SizeOfObjects();
current_.start_memory_size =
heap_->isolate()->memory_allocator()->Size();
current_.start_holes_size = CountTotalHolesSize(heap_);
+ current_.new_space_object_size =
+ heap_->new_space()->top() - heap_->new_space()->bottom();
current_.cumulative_incremental_marking_steps =
cumulative_incremental_marking_steps_;
@@ -296,6 +298,8 @@
if (current_.type == Event::SCAVENGER) {
PrintF("steps_count=%d ", current_.incremental_marking_steps);
PrintF("steps_took=%.1f ", current_.incremental_marking_duration);
+ PrintF("scavenge_throughput=%" V8_PTR_PREFIX "d ",
+ ScavengeSpeedInBytesPerMillisecond());
} else {
PrintF("steps_count=%d ", current_.incremental_marking_steps);
PrintF("steps_took=%.1f ", current_.incremental_marking_duration);
@@ -393,6 +397,22 @@
durations += iter->pure_incremental_marking_duration;
++iter;
}
+
+ if (durations == 0.0) return 0;
+
+ return static_cast<intptr_t>(bytes / durations);
+}
+
+
+intptr_t GCTracer::ScavengeSpeedInBytesPerMillisecond() const {
+ intptr_t bytes = 0;
+ double durations = 0.0;
+ EventBuffer::const_iterator iter = scavenger_events_.begin();
+ while (iter != scavenger_events_.end()) {
+ bytes += iter->new_space_object_size;
+ durations += iter->end_time - iter->start_time;
+ ++iter;
+ }
if (durations == 0.0) return 0;
=======================================
--- /trunk/src/heap/gc-tracer.h Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/heap/gc-tracer.h Thu Aug 21 00:04:56 2014 UTC
@@ -171,6 +171,9 @@
// after the current GC.
intptr_t end_holes_size;
+ // Size of new space objects in constructor.
+ intptr_t new_space_object_size;
+
// Number of incremental marking steps since creation of tracer.
// (value at start of event)
int cumulative_incremental_marking_steps;
@@ -280,10 +283,14 @@
// Returns 0 if no incremental marking round has been completed.
double MaxIncrementalMarkingDuration() const;
- // Compute the average incremental marking speed in bytes/second.
Returns 0 if
- // no events have been recorded.
+ // Compute the average incremental marking speed in bytes/millisecond.
+ // Returns 0 if no events have been recorded.
intptr_t IncrementalMarkingSpeedInBytesPerMillisecond() const;
+ // Compute the average scavenge speed in bytes/millisecond.
+ // Returns 0 if no events have been recorded.
+ intptr_t ScavengeSpeedInBytesPerMillisecond() const;
+
private:
// Print one detailed trace line in name=value format.
// TODO(ernstm): Move to Heap.
=======================================
--- /trunk/src/heap/heap.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/heap/heap.h Thu Aug 21 00:04:56 2014 UTC
@@ -294,6 +294,7 @@
V(Symbol_string, "Symbol") \
V(for_string, "for") \
V(for_api_string, "for_api") \
+ V(for_intern_string, "for_intern") \
V(private_api_string, "private_api") \
V(private_intern_string, "private_intern") \
V(Date_string, "Date") \
=======================================
--- /trunk/src/hydrogen.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/hydrogen.cc Thu Aug 21 00:04:56 2014 UTC
@@ -5286,16 +5286,14 @@
HOptimizedGraphBuilder::GlobalPropertyAccess
- HOptimizedGraphBuilder::LookupGlobalProperty(
- Variable* var, LookupResult* lookup, PropertyAccessType
access_type) {
+HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var,
LookupIterator* it,
+ PropertyAccessType
access_type) {
+ DCHECK_EQ(*var->name(), *it->name());
if (var->is_this() || !current_info()->has_global_object()) {
return kUseGeneric;
}
- Handle<GlobalObject> global(current_info()->global_object());
- global->Lookup(var->name(), lookup);
- if (!lookup->IsNormal() ||
- (access_type == STORE && lookup->IsReadOnly()) ||
- lookup->holder() != *global) {
+ if (!it->HasProperty() || it->property_kind() != LookupIterator::DATA ||
+ (access_type == STORE && it->IsReadOnly())) {
return kUseGeneric;
}
@@ -5340,8 +5338,10 @@
return ast_context()->ReturnInstruction(instr, expr->id());
}
- LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup,
LOAD);
+ Handle<GlobalObject> global(current_info()->global_object());
+ LookupIterator it(global, variable->name(),
+ LookupIterator::CHECK_PROPERTY);
+ GlobalPropertyAccess type = LookupGlobalProperty(variable, &it,
LOAD);
if (type == kUseCell &&
current_info()->global_object()->IsAccessCheckNeeded()) {
@@ -5349,8 +5349,7 @@
}
if (type == kUseCell) {
- Handle<GlobalObject> global(current_info()->global_object());
- Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
+ Handle<PropertyCell> cell = it.GetPropertyCell();
if (cell->type()->IsConstant()) {
PropertyCell::AddDependentCompilationInfo(cell, top_info());
Handle<Object> constant_object =
cell->type()->AsConstant()->Value();
@@ -5362,7 +5361,7 @@
return ast_context()->ReturnInstruction(constant, expr->id());
} else {
HLoadGlobalCell* instr =
- New<HLoadGlobalCell>(cell, lookup.GetPropertyDetails());
+ New<HLoadGlobalCell>(cell, it.property_details());
return ast_context()->ReturnInstruction(instr, expr->id());
}
} else {
@@ -6458,11 +6457,11 @@
Variable* var,
HValue* value,
BailoutId ast_id) {
- LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, STORE);
+ Handle<GlobalObject> global(current_info()->global_object());
+ LookupIterator it(global, var->name(), LookupIterator::CHECK_PROPERTY);
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
if (type == kUseCell) {
- Handle<GlobalObject> global(current_info()->global_object());
- Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
+ Handle<PropertyCell> cell = it.GetPropertyCell();
if (cell->type()->IsConstant()) {
Handle<Object> constant = cell->type()->AsConstant()->Value();
if (value->IsConstant()) {
@@ -6487,7 +6486,7 @@
}
}
HInstruction* instr =
- Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails());
+ Add<HStoreGlobalCell>(value, cell, it.property_details());
if (instr->HasObservableSideEffects()) {
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
}
@@ -9051,12 +9050,13 @@
// If there is a global property cell for the name at compile time
and
// access check is not enabled we assume that the function will not
change
// and generate optimized code for calling the function.
- LookupResult lookup(isolate());
- GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, LOAD);
+ Handle<GlobalObject> global(current_info()->global_object());
+ LookupIterator it(global, var->name(),
LookupIterator::CHECK_PROPERTY);
+ GlobalPropertyAccess type = LookupGlobalProperty(var, &it, LOAD);
if (type == kUseCell &&
!current_info()->global_object()->IsAccessCheckNeeded()) {
Handle<GlobalObject> global(current_info()->global_object());
- known_global_function = expr->ComputeGlobalTarget(global, &lookup);
+ known_global_function = expr->ComputeGlobalTarget(global, &it);
}
if (known_global_function) {
Add<HCheckValue>(function, expr->target());
=======================================
--- /trunk/src/hydrogen.h Tue Aug 5 00:05:55 2014 UTC
+++ /trunk/src/hydrogen.h Thu Aug 21 00:04:56 2014 UTC
@@ -2327,8 +2327,7 @@
kUseCell,
kUseGeneric
};
- GlobalPropertyAccess LookupGlobalProperty(Variable* var,
- LookupResult* lookup,
+ GlobalPropertyAccess LookupGlobalProperty(Variable* var, LookupIterator*
it,
PropertyAccessType
access_type);
void EnsureArgumentsArePushedForAccess();
=======================================
--- /trunk/src/lookup-inl.h Wed Aug 6 00:06:29 2014 UTC
+++ /trunk/src/lookup-inl.h Thu Aug 21 00:04:56 2014 UTC
@@ -29,6 +29,7 @@
LookupIterator::State LookupIterator::LookupInHolder(Map* map) {
+ STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY);
DisallowHeapAllocation no_gc;
switch (state_) {
case NOT_FOUND:
=======================================
--- /trunk/src/lookup.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/lookup.cc Thu Aug 21 00:04:56 2014 UTC
@@ -5,6 +5,7 @@
#include "src/v8.h"
#include "src/bootstrapper.h"
+#include "src/deoptimizer.h"
#include "src/lookup.h"
#include "src/lookup-inl.h"
@@ -107,6 +108,14 @@
has_property_ = true;
return true;
}
+
+
+void LookupIterator::ReloadPropertyInformation() {
+ state_ = BEFORE_PROPERTY;
+ state_ = LookupInHolder(*holder_map_);
+ DCHECK(IsFound());
+ HasProperty();
+}
void LookupIterator::PrepareForDataProperty(Handle<Object> value) {
@@ -116,13 +125,7 @@
holder_map_ =
Map::PrepareForDataProperty(holder_map_, descriptor_number(), value);
JSObject::MigrateToMap(GetHolder<JSObject>(), holder_map_);
- // Reload property information.
- if (holder_map_->is_dictionary_map()) {
- property_encoding_ = DICTIONARY;
- } else {
- property_encoding_ = DESCRIPTOR;
- }
- CHECK(HasProperty());
+ ReloadPropertyInformation();
}
@@ -137,17 +140,12 @@
JSObject::MigrateToMap(holder, holder_map_);
}
- // Reload property information and update the descriptor if in dictionary
- // mode.
if (holder_map_->is_dictionary_map()) {
- property_encoding_ = DICTIONARY;
PropertyDetails details(attributes, NORMAL, 0);
JSObject::SetNormalizedProperty(holder, name(), value, details);
- } else {
- property_encoding_ = DESCRIPTOR;
}
- CHECK(HasProperty());
+ ReloadPropertyInformation();
}
@@ -172,12 +170,62 @@
value, attributes,
store_mode);
JSObject::MigrateToMap(receiver, holder_map_);
- // Reload the information.
- state_ = NOT_FOUND;
- configuration_ = CHECK_PROPERTY;
- state_ = LookupInHolder(*holder_map_);
- DCHECK(IsFound());
- HasProperty();
+ ReloadPropertyInformation();
+}
+
+
+void LookupIterator::TransitionToAccessorProperty(
+ AccessorComponent component, Handle<Object> accessor,
+ PropertyAttributes attributes) {
+ DCHECK(!accessor->IsNull());
+ // Can only be called when the receiver is a JSObject. JSProxy has to be
+ // handled via a trap. Adding properties to primitive values is not
+ // observable.
+ Handle<JSObject> receiver = Handle<JSObject>::cast(GetReceiver());
+
+ if (receiver->IsJSGlobalProxy()) {
+ PrototypeIterator iter(isolate(), receiver);
+ receiver =
+ Handle<JSGlobalObject>::cast(PrototypeIterator::GetCurrent(iter));
+ }
+
+ maybe_holder_ = receiver;
+ holder_map_ = Map::TransitionToAccessorProperty(
+ handle(receiver->map()), name_, component, accessor, attributes);
+ JSObject::MigrateToMap(receiver, holder_map_);
+
+ ReloadPropertyInformation();
+
+ if (!holder_map_->is_dictionary_map()) return;
+
+ // We have to deoptimize since accesses to data properties may have been
+ // inlined without a corresponding map-check.
+ if (holder_map_->IsGlobalObjectMap()) {
+ Deoptimizer::DeoptimizeGlobalObject(*receiver);
+ }
+
+ // Install the accessor into the dictionary-mode object.
+ PropertyDetails details(attributes, CALLBACKS, 0);
+ Handle<AccessorPair> pair;
+ if (IsFound() && HasProperty() && property_kind() == ACCESSOR &&
+ GetAccessors()->IsAccessorPair()) {
+ pair = Handle<AccessorPair>::cast(GetAccessors());
+ // If the component and attributes are identical, nothing has to be
done.
+ if (pair->get(component) == *accessor) {
+ if (property_details().attributes() == attributes) return;
+ } else {
+ pair = AccessorPair::Copy(pair);
+ pair->set(component, *accessor);
+ }
+ } else {
+ pair = isolate()->factory()->NewAccessorPair();
+ pair->set(component, *accessor);
+ }
+ JSObject::SetNormalizedProperty(receiver, name_, pair, details);
+
+ JSObject::ReoptimizeIfPrototype(receiver);
+ holder_map_ = handle(receiver->map());
+ ReloadPropertyInformation();
}
=======================================
--- /trunk/src/lookup.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/lookup.h Thu Aug 21 00:04:56 2014 UTC
@@ -31,11 +31,14 @@
};
enum State {
+ ACCESS_CHECK,
+ INTERCEPTOR,
+ JSPROXY,
NOT_FOUND,
PROPERTY,
- INTERCEPTOR,
- ACCESS_CHECK,
- JSPROXY
+ // Set state_ to BEFORE_PROPERTY to ensure that the next lookup will
be a
+ // PROPERTY lookup.
+ BEFORE_PROPERTY = INTERCEPTOR
};
enum PropertyKind {
@@ -100,6 +103,10 @@
bool IsFound() const { return state_ != NOT_FOUND; }
void Next();
+ void NotFound() {
+ has_property_ = false;
+ state_ = NOT_FOUND;
+ }
Heap* heap() const { return isolate_->heap(); }
Factory* factory() const { return isolate_->factory(); }
@@ -130,6 +137,9 @@
Object::StoreFromKeyed store_mode);
void ReconfigureDataProperty(Handle<Object> value,
PropertyAttributes attributes);
+ void TransitionToAccessorProperty(AccessorComponent component,
+ Handle<Object> accessor,
+ PropertyAttributes attributes);
PropertyKind property_kind() const {
DCHECK(has_property_);
return property_kind_;
@@ -162,6 +172,7 @@
MUST_USE_RESULT inline JSReceiver* NextHolder(Map* map);
inline State LookupInHolder(Map* map);
Handle<Object> FetchValue() const;
+ void ReloadPropertyInformation();
bool IsBootstrapping() const;
=======================================
--- /trunk/src/objects.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/objects.cc Thu Aug 21 00:04:56 2014 UTC
@@ -138,6 +138,34 @@
}
return it->factory()->undefined_value();
}
+
+
+Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
+ Handle<Name> key) {
+ LookupIterator it(object, key, LookupIterator::CHECK_DERIVED_PROPERTY);
+ for (; it.IsFound(); it.Next()) {
+ switch (it.state()) {
+ case LookupIterator::NOT_FOUND:
+ case LookupIterator::ACCESS_CHECK:
+ case LookupIterator::INTERCEPTOR:
+ UNREACHABLE();
+ case LookupIterator::JSPROXY:
+ return it.isolate()->factory()->undefined_value();
+ case LookupIterator::PROPERTY:
+ if (!it.HasProperty()) continue;
+ switch (it.property_kind()) {
+ case LookupIterator::DATA:
+ return it.GetDataValue();
+ case LookupIterator::ACCESSOR:
+ // TODO(verwaest): For now this doesn't call into
+ // ExecutableAccessorInfo, since clients don't need it. Update
once
+ // relevant.
+ return it.isolate()->factory()->undefined_value();
+ }
+ }
+ }
+ return it.isolate()->factory()->undefined_value();
+}
bool Object::ToInt32(int32_t* value) {
@@ -628,22 +656,6 @@
DCHECK(!value->IsPropertyCell() && !value->IsCell());
return value;
}
-
-
-Handle<Object> JSObject::GetNormalizedProperty(Handle<JSObject> object,
- const LookupResult* result)
{
- DCHECK(!object->HasFastProperties());
- Isolate* isolate = object->GetIsolate();
- Handle<Object> value(
- object->property_dictionary()->ValueAt(result->GetDictionaryEntry()),
- isolate);
- if (object->IsGlobalObject()) {
- value = handle(Handle<PropertyCell>::cast(value)->value(), isolate);
- DCHECK(!value->IsTheHole());
- }
- DCHECK(!value->IsPropertyCell() && !value->IsCell());
- return value;
-}
void JSObject::SetNormalizedProperty(Handle<JSObject> object,
@@ -3417,37 +3429,6 @@
result->NotFound();
}
-
-
-void JSObject::LookupRealNamedProperty(Handle<Name> name,
- LookupResult* result) {
- DisallowHeapAllocation no_gc;
- LookupOwnRealNamedProperty(name, result);
- if (result->IsFound()) return;
-
- LookupRealNamedPropertyInPrototypes(name, result);
-}
-
-
-void JSObject::LookupRealNamedPropertyInPrototypes(Handle<Name> name,
- LookupResult* result) {
- if (name->IsOwn()) {
- result->NotFound();
- return;
- }
-
- DisallowHeapAllocation no_gc;
- Isolate* isolate = GetIsolate();
- for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd();
iter.Advance()) {
- if (iter.GetCurrent()->IsJSProxy()) {
- return result->HandlerResult(JSProxy::cast(iter.GetCurrent()));
- }
- JSObject::cast(iter.GetCurrent())->LookupOwnRealNamedProperty(name,
result);
- DCHECK(!(result->IsFound() && result->type() == INTERCEPTOR));
- if (result->IsFound()) return;
- }
- result->NotFound();
-}
Maybe<bool> JSProxy::HasPropertyWithHandler(Handle<JSProxy> proxy,
@@ -5669,41 +5650,6 @@
DCHECK(!copy.ToHandle(&for_assert) |
| !for_assert.is_identical_to(object));
return copy;
}
-
-
-Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object,
- Handle<Name> key) {
- Isolate* isolate = object->GetIsolate();
- LookupResult lookup(isolate);
- {
- DisallowHeapAllocation no_allocation;
- object->LookupRealNamedProperty(key, &lookup);
- }
- Handle<Object> result = isolate->factory()->undefined_value();
- if (lookup.IsFound() && !lookup.IsTransition()) {
- switch (lookup.type()) {
- case NORMAL:
- result = GetNormalizedProperty(
- Handle<JSObject>(lookup.holder(), isolate), &lookup);
- break;
- case FIELD:
- result = FastPropertyAt(Handle<JSObject>(lookup.holder(), isolate),
- lookup.representation(),
- lookup.GetFieldIndex());
- break;
- case CONSTANT:
- result = Handle<Object>(lookup.GetConstant(), isolate);
- break;
- case CALLBACKS:
- case HANDLER:
- case INTERCEPTOR:
- break;
- case NONEXISTENT:
- UNREACHABLE();
- }
- }
- return result;
-}
// Tests for the fast common case for property enumeration:
@@ -6154,51 +6100,6 @@
SetElementCallback(object, index, accessors, attributes);
}
-
-
-Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject>
object,
- Handle<Name> name) {
- Isolate* isolate = object->GetIsolate();
- LookupResult result(isolate);
- object->LookupOwnRealNamedProperty(name, &result);
- if (result.IsPropertyCallbacks()) {
- // Note that the result can actually have IsDontDelete() == true when
we
- // e.g. have to fall back to the slow case while adding a setter after
- // successfully reusing a map transition for a getter. Nevertheless,
this is
- // OK, because the assertion only holds for the whole addition of both
- // accessors, not for the addition of each part. See first comment in
- // DefinePropertyAccessor below.
- Object* obj = result.GetCallbackObject();
- if (obj->IsAccessorPair()) {
- return AccessorPair::Copy(handle(AccessorPair::cast(obj), isolate));
- }
- }
- return isolate->factory()->NewAccessorPair();
-}
-
-
-void JSObject::DefinePropertyAccessor(Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> getter,
- Handle<Object> setter,
- PropertyAttributes attributes) {
- // We could assert that the property is configurable here, but we would
need
- // to do a lookup, which seems to be a bit of overkill.
- bool only_attribute_changes = getter->IsNull() && setter->IsNull();
- if (object->HasFastProperties() && !only_attribute_changes &&
- (object->map()->NumberOfOwnDescriptors() <=
kMaxNumberOfDescriptors)) {
- bool getterOk = getter->IsNull() ||
- DefineFastAccessor(object, name, ACCESSOR_GETTER, getter,
attributes);
- bool setterOk = !getterOk || setter->IsNull() ||
- DefineFastAccessor(object, name, ACCESSOR_SETTER, setter,
attributes);
- if (getterOk && setterOk) return;
- }
-
- Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name);
- accessors->SetComponents(*getter, *setter);
-
- SetPropertyCallback(object, name, accessors, attributes);
-}
bool Map::DictionaryElementsInPrototypeChainOnly() {
@@ -6359,7 +6260,19 @@
if (is_element) {
DefineElementAccessor(object, index, getter, setter, attributes);
} else {
- DefinePropertyAccessor(object, name, getter, setter, attributes);
+ DCHECK(getter->IsSpecFunction() || getter->IsUndefined() ||
+ getter->IsNull());
+ DCHECK(setter->IsSpecFunction() || setter->IsUndefined() ||
+ setter->IsNull());
+ // At least one of the accessors needs to be a new value.
+ DCHECK(!getter->IsNull() || !setter->IsNull());
+ LookupIterator it(object, name, LookupIterator::CHECK_PROPERTY);
+ if (!getter->IsNull()) {
+ it.TransitionToAccessorProperty(ACCESSOR_GETTER, getter, attributes);
+ }
+ if (!setter->IsNull()) {
+ it.TransitionToAccessorProperty(ACCESSOR_SETTER, setter, attributes);
+ }
}
if (is_observed) {
@@ -6370,111 +6283,6 @@
return isolate->factory()->undefined_value();
}
-
-static bool TryAccessorTransition(Handle<JSObject> self,
- Handle<Map> transitioned_map,
- int target_descriptor,
- AccessorComponent component,
- Handle<Object> accessor,
- PropertyAttributes attributes) {
- DescriptorArray* descs = transitioned_map->instance_descriptors();
- PropertyDetails details = descs->GetDetails(target_descriptor);
-
- // If the transition target was not callbacks, fall back to the slow
case.
- if (details.type() != CALLBACKS) return false;
- Object* descriptor = descs->GetCallbacksObject(target_descriptor);
- if (!descriptor->IsAccessorPair()) return false;
-
- Object* target_accessor = AccessorPair::cast(descriptor)->get(component);
- PropertyAttributes target_attributes = details.attributes();
-
- // Reuse transition if adding same accessor with same attributes.
- if (target_accessor == *accessor && target_attributes == attributes) {
- JSObject::MigrateToMap(self, transitioned_map);
- return true;
- }
-
- // If either not the same accessor, or not the same attributes, fall
back to
- // the slow case.
- return false;
-}
-
-
-bool JSObject::DefineFastAccessor(Handle<JSObject> object,
- Handle<Name> name,
- AccessorComponent component,
- Handle<Object> accessor,
- PropertyAttributes attributes) {
- DCHECK(accessor->IsSpecFunction() || accessor->IsUndefined());
- Isolate* isolate = object->GetIsolate();
- LookupResult result(isolate);
- object->LookupOwn(name, &result);
-
- if (result.IsFound() && !result.IsPropertyCallbacks()) {
- return false;
- }
-
- // Return success if the same accessor with the same attributes already
exist.
- AccessorPair* source_accessors = NULL;
- if (result.IsPropertyCallbacks()) {
- Object* callback_value = result.GetCallbackObject();
- if (callback_value->IsAccessorPair()) {
- source_accessors = AccessorPair::cast(callback_value);
- Object* entry = source_accessors->get(component);
- if (entry == *accessor && result.GetAttributes() == attributes) {
- return true;
- }
- } else {
- return false;
- }
-
- int descriptor_number = result.GetDescriptorIndex();
-
- object->map()->LookupTransition(*object, *name, &result);
-
- if (result.IsFound()) {
- Handle<Map> target(result.GetTransitionTarget());
- DCHECK(target->NumberOfOwnDescriptors() ==
- object->map()->NumberOfOwnDescriptors());
- // This works since descriptors are sorted in order of addition.
- DCHECK(Name::Equals(
- handle(object->map()->instance_descriptors()->GetKey(
- descriptor_number)),
- name));
- return TryAccessorTransition(object, target, descriptor_number,
- component, accessor, attributes);
- }
- } else {
- // If not, lookup a transition.
- object->map()->LookupTransition(*object, *name, &result);
-
- // If there is a transition, try to follow it.
- if (result.IsFound()) {
- Handle<Map> target(result.GetTransitionTarget());
- int descriptor_number = target->LastAdded();
- DCHECK(Name::Equals(name,
-
handle(target->instance_descriptors()->GetKey(descriptor_number))));
- return TryAccessorTransition(object, target, descriptor_number,
- component, accessor, attributes);
- }
- }
-
- // If there is no transition yet, add a transition to the a new accessor
pair
- // containing the accessor. Allocate a new pair if there were no source
- // accessors. Otherwise, copy the pair and modify the accessor.
- Handle<AccessorPair> accessors = source_accessors != NULL
- ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors))
- : isolate->factory()->NewAccessorPair();
- accessors->set(component, *accessor);
-
- CallbacksDescriptor new_accessors_desc(name, accessors, attributes);
- Handle<Map> new_map = Map::CopyInsertDescriptor(
- handle(object->map()), &new_accessors_desc, INSERT_TRANSITION);
-
- JSObject::MigrateToMap(object, new_map);
- return true;
-}
-
MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
Handle<AccessorInfo> info) {
@@ -7114,6 +6922,101 @@
return CopyGeneralizeAllRepresentations(map, descriptor, FORCE_FIELD,
attributes, "attributes
mismatch");
}
+
+
+Handle<Map> Map::TransitionToAccessorProperty(Handle<Map> map,
+ Handle<Name> name,
+ AccessorComponent component,
+ Handle<Object> accessor,
+ PropertyAttributes
attributes) {
+ Isolate* isolate = name->GetIsolate();
+
+ // Dictionary maps can always have additional data properties.
+ if (map->is_dictionary_map()) {
+ // For global objects, property cells are inlined. We need to change
the
+ // map.
+ if (map->IsGlobalObjectMap()) return Copy(map);
+ return map;
+ }
+
+ // Migrate to the newest map before transitioning to the new property.
+ if (map->is_deprecated()) map = Update(map);
+
+ PropertyNormalizationMode mode = map->is_prototype_map()
+ ? KEEP_INOBJECT_PROPERTIES
+ : CLEAR_INOBJECT_PROPERTIES;
+
+ int index = map->SearchTransition(*name);
+ if (index != TransitionArray::kNotFound) {
+ Handle<Map> transition(map->GetTransition(index));
+ DescriptorArray* descriptors = transition->instance_descriptors();
+ // Fast path, assume that we're modifying the last added descriptor.
+ int descriptor = transition->LastAdded();
+ if (descriptors->GetKey(descriptor) != *name) {
+ // If not, search for the descriptor.
+ descriptor = descriptors->SearchWithCache(*name, *transition);
+ }
+
+ if (descriptors->GetDetails(descriptor).type() != CALLBACKS) {
+ return Map::Normalize(map, mode);
+ }
+
+ // TODO(verwaest): Handle attributes better.
+ if (descriptors->GetDetails(descriptor).attributes() != attributes) {
+ return Map::Normalize(map, mode);
+ }
+
+ Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
+ if (!maybe_pair->IsAccessorPair()) {
+ return Map::Normalize(map, mode);
+ }
+
+ Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
+ if (pair->get(component) != *accessor) {
+ return Map::Normalize(map, mode);
+ }
+
+ return transition;
+ }
+
+ Handle<AccessorPair> pair;
+ DescriptorArray* old_descriptors = map->instance_descriptors();
+ int descriptor = old_descriptors->SearchWithCache(*name, *map);
+ if (descriptor != DescriptorArray::kNotFound) {
+ PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
+ if (old_details.type() != CALLBACKS) {
+ return Map::Normalize(map, mode);
+ }
+
+ if (old_details.attributes() != attributes) {
+ return Map::Normalize(map, mode);
+ }
+
+ Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor),
isolate);
+ if (!maybe_pair->IsAccessorPair()) {
+ return Map::Normalize(map, mode);
+ }
+
+ Object* current =
Handle<AccessorPair>::cast(maybe_pair)->get(component);
+ if (current == *accessor) return map;
+
+ if (!current->IsTheHole()) {
+ return Map::Normalize(map, mode);
+ }
+
+ pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
+ } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
+ map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
+ return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES);
+ } else {
+ pair = isolate->factory()->NewAccessorPair();
+ }
+
+ pair->set(component, *accessor);
+ TransitionFlag flag = INSERT_TRANSITION;
+ CallbacksDescriptor new_desc(name, pair, attributes);
+ return Map::CopyInsertDescriptor(map, &new_desc, flag);
+}
Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
=======================================
--- /trunk/src/objects.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/objects.h Thu Aug 21 00:04:56 2014 UTC
@@ -2157,8 +2157,6 @@
// Retrieve a value in a normalized object given a lookup result.
// Handles the special representation of JS global objects.
Object* GetNormalizedProperty(const LookupResult* result);
- static Handle<Object> GetNormalizedProperty(Handle<JSObject> object,
- const LookupResult* result);
// Sets the property value in a normalized object given (key, value,
details).
// Handles the special representation of JS global objects.
@@ -2376,9 +2374,6 @@
// The following lookup functions skip interceptors.
void LookupOwnRealNamedProperty(Handle<Name> name, LookupResult* result);
- void LookupRealNamedProperty(Handle<Name> name, LookupResult* result);
- void LookupRealNamedPropertyInPrototypes(Handle<Name> name,
- LookupResult* result);
// Returns the number of properties on this object filtering out
properties
// with the specified attributes (ignoring interceptors).
@@ -2729,22 +2724,6 @@
Handle<Object> getter,
Handle<Object> setter,
PropertyAttributes attributes);
- static Handle<AccessorPair> CreateAccessorPairFor(Handle<JSObject>
object,
- Handle<Name> name);
- static void DefinePropertyAccessor(Handle<JSObject> object,
- Handle<Name> name,
- Handle<Object> getter,
- Handle<Object> setter,
- PropertyAttributes attributes);
-
- // Try to define a single accessor paying attention to map transitions.
- // Returns false if this was not possible and we have to use the slow
case.
- static bool DefineFastAccessor(Handle<JSObject> object,
- Handle<Name> name,
- AccessorComponent component,
- Handle<Object> accessor,
- PropertyAttributes attributes);
-
// Return the hash table backing store or the inline stored identity
hash,
// whatever is found.
@@ -6467,6 +6446,9 @@
Handle<Object> value,
PropertyAttributes
attributes,
StoreFromKeyed store_mode);
+ static Handle<Map> TransitionToAccessorProperty(
+ Handle<Map> map, Handle<Name> name, AccessorComponent component,
+ Handle<Object> accessor, PropertyAttributes attributes);
static Handle<Map> ReconfigureDataProperty(Handle<Map> map, int
descriptor,
PropertyAttributes
attributes);
=======================================
--- /trunk/src/parser.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/parser.cc Thu Aug 21 00:04:56 2014 UTC
@@ -3749,6 +3749,7 @@
reusable_preparser_->set_allow_arrow_functions(allow_arrow_functions());
reusable_preparser_->set_allow_harmony_numeric_literals(
allow_harmony_numeric_literals());
+ reusable_preparser_->set_allow_classes(allow_classes());
}
PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(strict_mode(),
=======================================
--- /trunk/src/runtime.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/runtime.cc Thu Aug 21 00:04:56 2014 UTC
@@ -4948,7 +4948,7 @@
// Transform getter or setter into something DefineAccessor can handle.
static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
Handle<Object>
component) {
- if (component->IsUndefined()) return isolate->factory()->null_value();
+ if (component->IsUndefined()) return
isolate->factory()->undefined_value();
Handle<FunctionTemplateInfo> info =
Handle<FunctionTemplateInfo>::cast(component);
return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
@@ -5352,6 +5352,33 @@
Runtime::SetObjectProperty(isolate, object, key, value,
strict_mode));
return *result;
}
+
+
+// Adds an element to an array.
+// This is used to create an indexed data property into an array.
+RUNTIME_FUNCTION(Runtime_AddElement) {
+ HandleScope scope(isolate);
+ RUNTIME_ASSERT(args.length() == 4);
+
+ CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
+ CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
+ CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
+ CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
+ RUNTIME_ASSERT(
+ (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) ==
0);
+ // Compute attributes.
+ PropertyAttributes attributes =
+ static_cast<PropertyAttributes>(unchecked_attributes);
+
+ uint32_t index = 0;
+ key->ToArrayIndex(&index);
+
+ Handle<Object> result;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, result, JSObject::SetElement(object, index, value,
attributes,
+ SLOPPY, false,
DEFINE_PROPERTY));
+ return *result;
+}
RUNTIME_FUNCTION(Runtime_TransitionElementsKind) {
@@ -10851,61 +10878,56 @@
}
-static Handle<Object> DebugLookupResultValue(Isolate* isolate,
- Handle<Object> receiver,
- Handle<Name> name,
- LookupResult* result,
+static Handle<Object> DebugLookupResultValue(LookupIterator* it,
bool* has_caught = NULL) {
- Handle<Object> value = isolate->factory()->undefined_value();
- if (!result->IsFound()) return value;
- switch (result->type()) {
- case NORMAL:
- return JSObject::GetNormalizedProperty(handle(result->holder(),
isolate),
- result);
- case FIELD:
- return JSObject::FastPropertyAt(handle(result->holder(), isolate),
- result->representation(),
- result->GetFieldIndex());
- case CONSTANT:
- return handle(result->GetConstant(), isolate);
- case CALLBACKS: {
- Handle<Object> structure(result->GetCallbackObject(), isolate);
- DCHECK(!structure->IsForeign());
- if (structure->IsAccessorInfo()) {
- MaybeHandle<Object> obj = JSObject::GetPropertyWithAccessor(
- receiver, name, handle(result->holder(), isolate), structure);
- if (!obj.ToHandle(&value)) {
- value = handle(isolate->pending_exception(), isolate);
- isolate->clear_pending_exception();
- if (has_caught != NULL) *has_caught = true;
- return value;
+ for (; it->IsFound(); it->Next()) {
+ switch (it->state()) {
+ case LookupIterator::NOT_FOUND:
+ UNREACHABLE();
+ case LookupIterator::ACCESS_CHECK:
+ // Ignore access checks.
+ break;
+ case LookupIterator::INTERCEPTOR:
+ case LookupIterator::JSPROXY:
+ return it->isolate()->factory()->undefined_value();
+ case LookupIterator::PROPERTY:
+ if (!it->HasProperty()) continue;
+ switch (it->property_kind()) {
+ case LookupIterator::ACCESSOR: {
+ Handle<Object> accessors = it->GetAccessors();
+ if (!accessors->IsAccessorInfo()) {
+ return it->isolate()->factory()->undefined_value();
+ }
+ MaybeHandle<Object> maybe_result =
+ JSObject::GetPropertyWithAccessor(it->GetReceiver(),
it->name(),
+
it->GetHolder<JSObject>(),
+ accessors);
+ Handle<Object> result;
+ if (!maybe_result.ToHandle(&result)) {
+ result =
+ handle(it->isolate()->pending_exception(),
it->isolate());
+ it->isolate()->clear_pending_exception();
+ if (has_caught != NULL) *has_caught = true;
+ }
+ return result;
+ }
+ case LookupIterator::DATA:
+ return it->GetDataValue();
}
- }
- break;
}
- case INTERCEPTOR:
- case HANDLER:
- break;
- case NONEXISTENT:
- UNREACHABLE();
- break;
}
- return value;
+
+ return it->isolate()->factory()->undefined_value();
}
-// Get debugger related details for an object property.
-// args[0]: object holding property
-// args[1]: name of the property
-//
-// The array returned contains the following information:
+// Get debugger related details for an object property, in the following
format:
// 0: Property value
// 1: Property details
// 2: Property value is exception
// 3: Getter function if defined
// 4: Setter function if defined
-// Items 2-4 are only filled if the property has either a getter or a
setter
-// defined through __defineGetter__ and/or __defineSetter__.
+// Items 2-4 are only filled if the property has either a getter or a
setter.
RUNTIME_FUNCTION(Runtime_DebugGetPropertyDetails) {
HandleScope scope(isolate);
@@ -10940,53 +10962,36 @@
return *isolate->factory()->NewJSArrayWithElements(details);
}
- // Find the number of objects making up this.
- int length = OwnPrototypeChainLength(*obj);
-
- // Try own lookup on each of the objects.
- PrototypeIterator iter(isolate, obj,
PrototypeIterator::START_AT_RECEIVER);
- for (int i = 0; i < length; i++) {
- DCHECK(!iter.IsAtEnd());
- Handle<JSObject> jsproto =
- Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
- LookupResult result(isolate);
- jsproto->LookupOwn(name, &result);
- if (result.IsFound()) {
- // LookupResult is not GC safe as it holds raw object pointers.
- // GC can happen later in this code so put the required fields into
- // local variables using handles when required for later use.
- Handle<Object> result_callback_obj;
- if (result.IsPropertyCallbacks()) {
- result_callback_obj = Handle<Object>(result.GetCallbackObject(),
- isolate);
- }
-
-
- bool has_caught = false;
- Handle<Object> value = DebugLookupResultValue(
- isolate, obj, name, &result, &has_caught);
+ LookupIterator it(obj, name, LookupIterator::CHECK_HIDDEN);
+ bool has_caught = false;
+ Handle<Object> value = DebugLookupResultValue(&it, &has_caught);
+ if (!it.IsFound()) return isolate->heap()->undefined_value();
- // If the callback object is a fixed array then it contains
JavaScript
- // getter and/or setter.
- bool has_js_accessors = result.IsPropertyCallbacks() &&
- result_callback_obj->IsAccessorPair();
- Handle<FixedArray> details =
- isolate->factory()->NewFixedArray(has_js_accessors ? 5 : 2);
- details->set(0, *value);
- details->set(1, result.GetPropertyDetails().AsSmi());
- if (has_js_accessors) {
- AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
- details->set(2, isolate->heap()->ToBoolean(has_caught));
- details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
- details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
- }
+ Handle<Object> maybe_pair;
+ if (it.state() == LookupIterator::PROPERTY &&
+ it.property_kind() == LookupIterator::ACCESSOR) {
+ maybe_pair = it.GetAccessors();
+ }
- return *isolate->factory()->NewJSArrayWithElements(details);
- }
- iter.Advance();
+ // If the callback object is a fixed array then it contains JavaScript
+ // getter and/or setter.
+ bool has_js_accessors = !maybe_pair.is_null() &&
maybe_pair->IsAccessorPair();
+ Handle<FixedArray> details =
+ isolate->factory()->NewFixedArray(has_js_accessors ? 5 : 2);
+ details->set(0, *value);
+ // TODO(verwaest): Get rid of this random way of handling interceptors.
+ PropertyDetails d = it.state() == LookupIterator::INTERCEPTOR
+ ? PropertyDetails(NONE, INTERCEPTOR, 0)
+ : it.property_details();
+ details->set(1, d.AsSmi());
+ if (has_js_accessors) {
+ AccessorPair* accessors = AccessorPair::cast(*maybe_pair);
+ details->set(2, isolate->heap()->ToBoolean(has_caught));
+ details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
+ details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
}
- return isolate->heap()->undefined_value();
+ return *isolate->factory()->NewJSArrayWithElements(details);
}
@@ -10998,9 +11003,8 @@
CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
- LookupResult result(isolate);
- obj->Lookup(name, &result);
- return *DebugLookupResultValue(isolate, obj, name, &result);
+ LookupIterator it(obj, name, LookupIterator::CHECK_DERIVED);
+ return *DebugLookupResultValue(&it);
}
=======================================
--- /trunk/src/runtime.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/runtime.h Thu Aug 21 00:04:56 2014 UTC
@@ -233,6 +233,7 @@
F(AddNamedProperty, 4, 1) \
F(AddPropertyForTemplate, 4, 1) \
F(SetProperty, 4, 1) \
+ F(AddElement, 4, 1) \
F(DefineApiAccessorProperty, 5, 1) \
F(DefineDataPropertyUnchecked, 4, 1) \
F(DefineAccessorPropertyUnchecked, 5, 1) \
=======================================
--- /trunk/src/stub-cache.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/stub-cache.cc Thu Aug 21 00:04:56 2014 UTC
@@ -1191,18 +1191,6 @@
MacroAssembler* masm) {
KeyedStoreIC::GenerateSlow(masm);
}
-
-
-CallOptimization::CallOptimization(LookupResult* lookup) {
- if (lookup->IsFound() &&
- lookup->IsCacheable() &&
- lookup->IsConstantFunction()) {
- // We only optimize constant function calls.
- Initialize(Handle<JSFunction>(lookup->GetConstantFunction()));
- } else {
- Initialize(Handle<JSFunction>::null());
- }
-}
CallOptimization::CallOptimization(Handle<JSFunction> function) {
=======================================
--- /trunk/src/stub-cache.h Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/src/stub-cache.h Thu Aug 21 00:04:56 2014 UTC
@@ -626,8 +626,6 @@
// Holds information about possible function call optimizations.
class CallOptimization BASE_EMBEDDED {
public:
- explicit CallOptimization(LookupResult* lookup);
-
explicit CallOptimization(Handle<JSFunction> function);
bool is_constant_call() const {
=======================================
--- /trunk/src/v8natives.js Tue Aug 12 06:42:13 2014 UTC
+++ /trunk/src/v8natives.js Thu Aug 21 00:04:56 2014 UTC
@@ -840,8 +840,18 @@
// property.
// Step 12 - updating an existing accessor property with an accessor
// descriptor.
- var getter = desc.hasGetter() ? desc.getGet() : null;
- var setter = desc.hasSetter() ? desc.getSet() : null;
+ var getter = null;
+ if (desc.hasGetter()) {
+ getter = desc.getGet();
+ } else if (IsAccessorDescriptor(current) && current.hasGetter()) {
+ getter = current.getGet();
+ }
+ var setter = null;
+ if (desc.hasSetter()) {
+ setter = desc.getSet();
+ } else if (IsAccessorDescriptor(current) && current.hasSetter()) {
+ setter = current.getSet();
+ }
%DefineAccessorPropertyUnchecked(obj, p, getter, setter, flag);
}
return true;
=======================================
--- /trunk/src/version.cc Wed Aug 20 13:33:20 2014 UTC
+++ /trunk/src/version.cc Thu Aug 21 00:04:56 2014 UTC
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 29
-#define BUILD_NUMBER 9
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 10
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
=======================================
--- /trunk/test/cctest/cctest.status Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/test/cctest/cctest.status Thu Aug 21 00:04:56 2014 UTC
@@ -194,7 +194,10 @@
'test-mark-compact/Promotion': [PASS, FAIL],
# BUG(v8:3434).
- ' test-api/LoadICFastApi_DirectCall_GCMoveStubWithProfiler': [SKIP]
+ ' test-api/LoadICFastApi_DirectCall_GCMoveStubWithProfiler': [SKIP],
+
+ # TODO(rodolph): Please investigate.
+ 'test-run-machops/RunTruncateFloat64ToInt32P': [SKIP],
}], # 'arch == arm64'
['arch == arm64 and simulator_run == True', {
=======================================
--- /trunk/test/cctest/compiler/test-run-machops.cc Wed Aug 20 00:06:26
2014 UTC
+++ /trunk/test/cctest/compiler/test-run-machops.cc Thu Aug 21 00:04:56
2014 UTC
@@ -4244,5 +4244,75 @@
}
}
}
+
+
+TEST(RunTruncateFloat64ToInt32P) {
+ struct {
+ double from;
+ double raw;
+ } kValues[] = {{0, 0},
+ {0.5, 0},
+ {-0.5, 0},
+ {1.5, 1},
+ {-1.5, -1},
+ {5.5, 5},
+ {-5.0, -5},
+ {v8::base::OS::nan_value(), 0},
+ {std::numeric_limits<double>::infinity(), 0},
+ {-v8::base::OS::nan_value(), 0},
+ {-std::numeric_limits<double>::infinity(), 0},
+ {4.94065645841e-324, 0},
+ {-4.94065645841e-324, 0},
+ {0.9999999999999999, 0},
+ {-0.9999999999999999, 0},
+ {4294967296.0, 0},
+ {-4294967296.0, 0},
+ {9223372036854775000.0, 4294966272.0},
+ {-9223372036854775000.0, -4294966272.0},
+ {4.5036e+15, 372629504},
+ {-4.5036e+15, -372629504},
+ {287524199.5377777, 0x11234567},
+ {-287524199.5377777, -0x11234567},
+ {2300193596.302222, 2300193596.0},
+ {-2300193596.302222, -2300193596.0},
+ {4600387192.604444, 305419896},
+ {-4600387192.604444, -305419896},
+ {4823855600872397.0, 1737075661},
+ {-4823855600872397.0, -1737075661},
+ {4503603922337791.0, -1},
+ {-4503603922337791.0, 1},
+ {4503601774854143.0, 2147483647},
+ {-4503601774854143.0, -2147483647},
+ {9007207844675582.0, -2},
+ {-9007207844675582.0, 2},
+ {2.4178527921507624e+24, -536870912},
+ {-2.4178527921507624e+24, 536870912},
+ {2.417853945072267e+24, -536870912},
+ {-2.417853945072267e+24, 536870912},
+ {4.8357055843015248e+24, -1073741824},
+ {-4.8357055843015248e+24, 1073741824},
+ {4.8357078901445341e+24, -1073741824},
+ {-4.8357078901445341e+24, 1073741824},
+ {2147483647.0, 2147483647.0},
+ {-2147483648.0, -2147483648.0},
+ {9.6714111686030497e+24, -2147483648.0},
+ {-9.6714111686030497e+24, -2147483648.0},
+ {9.6714157802890681e+24, -2147483648.0},
+ {-9.6714157802890681e+24, -2147483648.0},
+ {1.9342813113834065e+25, 2147483648.0},
+ {-1.9342813113834065e+25, 2147483648.0},
+ {3.868562622766813e+25, 0},
+ {-3.868562622766813e+25, 0},
+ {1.7976931348623157e+308, 0},
+ {-1.7976931348623157e+308, 0}};
+ double input = -1.0;
+ RawMachineAssemblerTester<int32_t> m;
+ m.Return(m.TruncateFloat64ToInt32(m.LoadFromPointer(&input,
kMachFloat64)));
+ for (size_t i = 0; i < ARRAY_SIZE(kValues); ++i) {
+ input = kValues[i].from;
+ uint64_t expected = static_cast<int64_t>(kValues[i].raw);
+ CHECK_EQ(static_cast<int>(expected), m.Call());
+ }
+}
#endif // V8_TURBOFAN_TARGET
=======================================
--- /trunk/test/cctest/test-api.cc Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/test/cctest/test-api.cc Thu Aug 21 00:04:56 2014 UTC
@@ -2922,6 +2922,29 @@
CHECK(sym2->SameValue(glob));
CHECK(!sym2->SameValue(glob_api));
}
+
+
+static void
CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*),
+ const char* name) {
+ LocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ v8::Local<v8::Symbol> symbol = getter(isolate);
+ std::string script = std::string("var sym = ") + name;
+ CompileRun(script.c_str());
+ v8::Local<Value> value = env->Global()->Get(v8_str("sym"));
+
+ CHECK(!value.IsEmpty());
+ CHECK(!symbol.IsEmpty());
+ CHECK(value->SameValue(symbol));
+}
+
+
+THREADED_TEST(WellKnownSymbols) {
+ CheckWellKnownSymbol(v8::Symbol::GetIterator, "Symbol.iterator");
+ CheckWellKnownSymbol(v8::Symbol::GetUnscopables, "Symbol.unscopables");
+}
THREADED_TEST(GlobalPrivates) {
=======================================
--- /trunk/test/compiler-unittests/change-lowering-unittest.cc Wed Aug 20
00:06:26 2014 UTC
+++ /trunk/test/compiler-unittests/change-lowering-unittest.cc Thu Aug 21
00:04:56 2014 UTC
@@ -263,7 +263,7 @@
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
- IsPhi(IsChangeFloat64ToInt32(IsLoad(
+ IsPhi(IsTruncateFloat64ToInt32(IsLoad(
kMachFloat64, val,
IsInt32Constant(HeapNumberValueOffset()),
IsControlEffect(CaptureEq(&if_true)))),
IsWord32Sar(val, IsInt32Constant(SmiShiftAmount())),
@@ -341,7 +341,7 @@
Capture<Node*> branch, if_true;
EXPECT_THAT(
phi,
- IsPhi(IsChangeFloat64ToInt32(IsLoad(
+ IsPhi(IsTruncateFloat64ToInt32(IsLoad(
kMachFloat64, val,
IsInt32Constant(HeapNumberValueOffset()),
IsControlEffect(CaptureEq(&if_true)))),
IsTruncateInt64ToInt32(
=======================================
--- /trunk/test/compiler-unittests/graph-unittest.cc Wed Aug 20 00:06:26
2014 UTC
+++ /trunk/test/compiler-unittests/graph-unittest.cc Thu Aug 21 00:04:56
2014 UTC
@@ -680,6 +680,7 @@
IS_UNOP_MATCHER(ChangeInt32ToFloat64)
IS_UNOP_MATCHER(ChangeInt32ToInt64)
IS_UNOP_MATCHER(ChangeUint32ToUint64)
+IS_UNOP_MATCHER(TruncateFloat64ToInt32)
IS_UNOP_MATCHER(TruncateInt64ToInt32)
#undef IS_UNOP_MATCHER
=======================================
--- /trunk/test/compiler-unittests/graph-unittest.h Wed Aug 20 00:06:26
2014 UTC
+++ /trunk/test/compiler-unittests/graph-unittest.h Thu Aug 21 00:04:56
2014 UTC
@@ -98,6 +98,7 @@
Matcher<Node*> IsChangeInt32ToFloat64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeInt32ToInt64(const Matcher<Node*>& input_matcher);
Matcher<Node*> IsChangeUint32ToUint64(const Matcher<Node*>& input_matcher);
+Matcher<Node*> IsTruncateFloat64ToInt32(const Matcher<Node*>&
input_matcher);
Matcher<Node*> IsTruncateInt64ToInt32(const Matcher<Node*>& input_matcher);
} // namespace compiler
=======================================
--- /trunk/test/compiler-unittests/instruction-selector-unittest.cc Wed Aug
20 00:06:26 2014 UTC
+++ /trunk/test/compiler-unittests/instruction-selector-unittest.cc Thu Aug
21 00:04:56 2014 UTC
@@ -69,6 +69,10 @@
}
return s;
}
+
+
+//
-----------------------------------------------------------------------------
+// Return.
TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
@@ -95,6 +99,23 @@
EXPECT_EQ(kArchRet, s[1]->arch_opcode());
EXPECT_EQ(1U, s[1]->InputCount());
}
+
+
+//
-----------------------------------------------------------------------------
+// Conversions.
+
+
+TARGET_TEST_F(InstructionSelectorTest,
TruncateFloat64ToInt32WithParameter) {
+ StreamBuilder m(this, kMachInt32, kMachFloat64);
+ m.Return(m.TruncateFloat64ToInt32(m.Parameter(0)));
+ Stream s = m.Build(kAllInstructions);
+ ASSERT_EQ(3U, s.size());
+ EXPECT_EQ(kArchNop, s[0]->arch_opcode());
+ EXPECT_EQ(kArchTruncateDoubleToI, s[1]->arch_opcode());
+ EXPECT_EQ(1U, s[1]->InputCount());
+ EXPECT_EQ(1U, s[1]->OutputCount());
+ EXPECT_EQ(kArchRet, s[2]->arch_opcode());
+}
} // namespace compiler
} // namespace internal
=======================================
--- /trunk/test/compiler-unittests/machine-operator-unittest.cc Wed Aug 20
00:06:26 2014 UTC
+++ /trunk/test/compiler-unittests/machine-operator-unittest.cc Thu Aug 21
00:04:56 2014 UTC
@@ -55,6 +55,16 @@
EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
}
+
+
+TEST_P(MachineOperatorCommonTest, TruncateFloat64ToInt32) {
+ Operator* op = machine()->TruncateFloat64ToInt32();
+ EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
+ EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
+ EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
+ EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
+ EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
+}
TEST_P(MachineOperatorCommonTest, TruncateInt64ToInt32) {
=======================================
--- /trunk/test/mjsunit/es6/collections.js Wed Aug 20 00:06:26 2014 UTC
+++ /trunk/test/mjsunit/es6/collections.js Thu Aug 21 00:04:56 2014 UTC
@@ -117,7 +117,8 @@
TestMapping(m, i / 10, new Object);
TestMapping(m, 'key-' + i, new Object);
}
- var keys = [ +0, -0, +Infinity, -Infinity, true, false, null, undefined
];
+ // -0 is handled in TestMinusZeroMap
+ var keys = [ 0, +Infinity, -Infinity, true, false, null, undefined ];
for (var i = 0; i < keys.length; i++) {
TestMapping(m, keys[i], new Object);
}
@@ -495,24 +496,26 @@
(function TestMinusZeroSet() {
- var m = new Set();
- m.add(0);
- m.add(-0);
- assertEquals(1, m.size);
- assertTrue(m.has(0));
- assertTrue(m.has(-0));
+ var s = new Set();
+ s.add(-0);
+ assertSame(0, s.values().next().value);
+ s.add(0);
+ assertEquals(1, s.size);
+ assertTrue(s.has(0));
+ assertTrue(s.has(-0));
})();
(function TestMinusZeroMap() {
var m = new Map();
+ m.set(-0, 'minus');
+ assertSame(0, m.keys().next().value);
m.set(0, 'plus');
- m.set(-0, 'minus');
assertEquals(1, m.size);
assertTrue(m.has(0));
assertTrue(m.has(-0));
- assertEquals('minus', m.get(0));
- assertEquals('minus', m.get(-0));
+ assertEquals('plus', m.get(0));
+ assertEquals('plus', m.get(-0));
})();
=======================================
--- /trunk/test/mjsunit/es6/unscopables.js Fri Aug 8 15:46:17 2014 UTC
+++ /trunk/test/mjsunit/es6/unscopables.js Thu Aug 21 00:04:56 2014 UTC
@@ -2,9 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Flags: --harmony-unscopables
-// Flags: --harmony-collections
-
var global = this;
var globalProto = Object.getPrototypeOf(global);
=======================================
***Additional files exist in this changeset.***
--
--
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.