[v8] r12836 committed - Version 3.15.0...

4 views
Skip to first unread message

codesite...@google.com

unread,
Oct 31, 2012, 6:07:47 AM10/31/12
to v8-...@googlegroups.com
Revision: 12836
Author: da...@chromium.org
Date: Wed Oct 31 03:02:10 2012
Log: Version 3.15.0

Loosened aligned code target requirement on ARM (issue 2380)

Fixed JSON.parse to treat leading zeros correctly. (Chromium issue 158185)

Performance and stability improvements on all platforms.
http://code.google.com/p/v8/source/detail?r=12836

Added:
/trunk/src/json-stringifier.h
/trunk/src/object-observe.js
/trunk/test/mjsunit/harmony/object-observe.js
/trunk/test/mjsunit/json-recursive.js
/trunk/test/mjsunit/json2.js
/trunk/test/mjsunit/regress/regress-crbug-157520.js
/trunk/test/mjsunit/regress/regress-crbug-158185.js
/trunk/test/mjsunit/regress/regress-json-stringify-gc.js
Modified:
/trunk/AUTHORS
/trunk/ChangeLog
/trunk/build/android.gypi
/trunk/build/common.gypi
/trunk/include/v8.h
/trunk/src/api.cc
/trunk/src/arm/assembler-arm-inl.h
/trunk/src/arm/assembler-arm.cc
/trunk/src/arm/assembler-arm.h
/trunk/src/arm/constants-arm.h
/trunk/src/arm/disasm-arm.cc
/trunk/src/arm/lithium-codegen-arm.cc
/trunk/src/array.js
/trunk/src/bootstrapper.cc
/trunk/src/compilation-cache.cc
/trunk/src/contexts.cc
/trunk/src/deoptimizer.cc
/trunk/src/elements.cc
/trunk/src/extensions/gc-extension.cc
/trunk/src/flag-definitions.h
/trunk/src/frames.cc
/trunk/src/heap-inl.h
/trunk/src/heap.cc
/trunk/src/heap.h
/trunk/src/hydrogen-instructions.h
/trunk/src/ia32/assembler-ia32.cc
/trunk/src/ia32/code-stubs-ia32.cc
/trunk/src/json-parser.h
/trunk/src/json.js
/trunk/src/mark-compact.cc
/trunk/src/mark-compact.h
/trunk/src/messages.js
/trunk/src/mips/lithium-mips.cc
/trunk/src/objects-debug.cc
/trunk/src/objects-inl.h
/trunk/src/objects.cc
/trunk/src/platform-cygwin.cc
/trunk/src/platform-freebsd.cc
/trunk/src/platform-linux.cc
/trunk/src/platform-macos.cc
/trunk/src/platform-nullos.cc
/trunk/src/platform-openbsd.cc
/trunk/src/platform-solaris.cc
/trunk/src/platform-win32.cc
/trunk/src/platform.h
/trunk/src/profile-generator.cc
/trunk/src/proxy.js
/trunk/src/regexp-stack.cc
/trunk/src/runtime.cc
/trunk/src/runtime.h
/trunk/src/serialize.cc
/trunk/src/spaces-inl.h
/trunk/src/spaces.cc
/trunk/src/spaces.h
/trunk/src/stub-cache.cc
/trunk/src/version.cc
/trunk/src/x64/code-stubs-x64.cc
/trunk/test/cctest/test-heap.cc
/trunk/test/mjsunit/json.js
/trunk/test/mjsunit/mjsunit.status
/trunk/test/mjsunit/testcfg.py
/trunk/tools/gyp/v8.gyp
/trunk/tools/run-tests.py

=======================================
--- /dev/null
+++ /trunk/src/json-stringifier.h Wed Oct 31 03:02:10 2012
@@ -0,0 +1,671 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_JSON_STRINGIFIER_H_
+#define V8_JSON_STRINGIFIER_H_
+
+#include "v8.h"
+#include "v8utils.h"
+#include "v8conversions.h"
+
+namespace v8 {
+namespace internal {
+
+class BasicJsonStringifier BASE_EMBEDDED {
+ public:
+ explicit BasicJsonStringifier(Isolate* isolate);
+
+ MaybeObject* Stringify(Handle<Object> object);
+
+ private:
+ static const int kInitialPartLength = 32;
+ static const int kMaxPartLength = 16 * 1024;
+ static const int kPartLengthGrowthFactor = 2;
+
+ enum Result { UNCHANGED, SUCCESS, BAILOUT, CIRCULAR, STACK_OVERFLOW };
+
+ template <bool is_ascii> void Extend();
+
+ void ChangeEncoding();
+
+ void ShrinkCurrentPart();
+
+ template <bool is_ascii, typename Char>
+ INLINE(void Append_(Char c));
+
+ template <bool is_ascii, typename Char>
+ INLINE(void Append_(const Char* chars));
+
+ INLINE(void Append(char c)) {
+ if (is_ascii_) {
+ Append_<true>(c);
+ } else {
+ Append_<false>(c);
+ }
+ }
+
+ INLINE(void Append(const char* chars)) {
+ if (is_ascii_) {
+ Append_<true>(chars);
+ } else {
+ Append_<false>(chars);
+ }
+ }
+
+ Handle<Object> GetProperty(Handle<JSObject> object,
+ Handle<String> key);
+
+ bool MayHaveToJsonFunction(Handle<JSObject> object);
+
+ INLINE(Result Serialize(Handle<Object> object)) {
+ return Serialize_<false>(object);
+ }
+
+ INLINE(Result SerializeDeferred(Handle<Object> object,
+ bool deferred_comma,
+ Handle<String> deferred_key)) {
+ ASSERT(!deferred_key.is_null());
+ return Serialize_<true>(object, deferred_comma, deferred_key);
+ }
+
+ template <bool deferred_key>
+ Result Serialize_(Handle<Object> object,
+ bool comma = false,
+ Handle<String> key = Handle<String>::null());
+
+ void SerializeDeferredKey(bool deferred_comma, Handle<String>
deferred_key) {
+ if (deferred_comma) Append(',');
+ SerializeString(deferred_key);
+ Append(':');
+ }
+
+ Result SerializeSmi(Smi* object);
+
+ Result SerializeDouble(double number);
+ INLINE(Result SerializeHeapNumber(Handle<HeapNumber> object)) {
+ return SerializeDouble(object->value());
+ }
+
+ INLINE(Result SerializeArray(Handle<JSArray> object));
+ INLINE(Result SerializeObject(Handle<JSObject> object));
+
+ void SerializeString(Handle<String> object);
+
+ template <typename SrcChar, typename DestChar>
+ INLINE(void SerializeStringUnchecked_(const SrcChar* src,
+ DestChar* dest,
+ int length));
+
+ template <bool is_ascii, typename Char>
+ INLINE(void SerializeString_(Vector<const Char> vector,
+ Handle<String> string));
+
+ template <typename Char>
+ INLINE(bool DoNotEscape(Char c));
+
+ template <typename Char>
+ INLINE(Vector<const Char> GetCharVector(Handle<String> string));
+
+ Result StackPush(Handle<Object> object);
+ void StackPop();
+
+ INLINE(Handle<String> accumulator()) {
+ return Handle<String>(String::cast(accumulator_store_->value()));
+ }
+
+ INLINE(void set_accumulator(Handle<String> string)) {
+ return accumulator_store_->set_value(*string);
+ }
+
+ Isolate* isolate_;
+ // We use a value wrapper for the string accumulator to keep the
+ // (indirect) handle to it in the outermost handle scope.
+ Handle<JSValue> accumulator_store_;
+ Handle<String> current_part_;
+ Handle<String> tojson_symbol_;
+ Handle<JSArray> stack_;
+ int current_index_;
+ int part_length_;
+ bool is_ascii_;
+
+ static const int kJsonEscapeTableEntrySize = 8;
+ static const char* const JsonEscapeTable;
+};
+
+
+// Translation table to escape ASCII characters.
+// Table entries start at a multiple of 8 and are null-terminated.
+const char* const BasicJsonStringifier::JsonEscapeTable =
+ "\\u0000\0 \\u0001\0 \\u0002\0 \\u0003\0 "
+ "\\u0004\0 \\u0005\0 \\u0006\0 \\u0007\0 "
+ "\\b\0 \\t\0 \\n\0 \\u000b\0 "
+ "\\f\0 \\r\0 \\u000e\0 \\u000f\0 "
+ "\\u0010\0 \\u0011\0 \\u0012\0 \\u0013\0 "
+ "\\u0014\0 \\u0015\0 \\u0016\0 \\u0017\0 "
+ "\\u0018\0 \\u0019\0 \\u001a\0 \\u001b\0 "
+ "\\u001c\0 \\u001d\0 \\u001e\0 \\u001f\0 "
+ " \0 !\0 \\\"\0 #\0 "
+ "$\0 %\0 &\0 '\0 "
+ "(\0 )\0 *\0 +\0 "
+ ",\0 -\0 .\0 /\0 "
+ "0\0 1\0 2\0 3\0 "
+ "4\0 5\0 6\0 7\0 "
+ "8\0 9\0 :\0 ;\0 "
+ "<\0 =\0 >\0 ?\0 "
+ "@\0 A\0 B\0 C\0 "
+ "D\0 E\0 F\0 G\0 "
+ "H\0 I\0 J\0 K\0 "
+ "L\0 M\0 N\0 O\0 "
+ "P\0 Q\0 R\0 S\0 "
+ "T\0 U\0 V\0 W\0 "
+ "X\0 Y\0 Z\0 [\0 "
+ "\\\\\0 ]\0 ^\0 _\0 "
+ "`\0 a\0 b\0 c\0 "
+ "d\0 e\0 f\0 g\0 "
+ "h\0 i\0 j\0 k\0 "
+ "l\0 m\0 n\0 o\0 "
+ "p\0 q\0 r\0 s\0 "
+ "t\0 u\0 v\0 w\0 "
+ "x\0 y\0 z\0 {\0 "
+ "|\0 }\0 ~\0 \177\0 ";
+
+
+BasicJsonStringifier::BasicJsonStringifier(Isolate* isolate)
+ : isolate_(isolate), current_index_(0), is_ascii_(true) {
+ accumulator_store_ = Handle<JSValue>::cast(
+ isolate_->factory()->ToObject(isolate_->factory()->empty_string()));
+ part_length_ = kInitialPartLength;
+ current_part_ =
+ isolate_->factory()->NewRawAsciiString(kInitialPartLength);
+ tojson_symbol_ = isolate_->factory()->LookupAsciiSymbol("toJSON");
+ stack_ = isolate_->factory()->NewJSArray(8);
+}
+
+
+MaybeObject* BasicJsonStringifier::Stringify(Handle<Object> object) {
+ switch (Serialize(object)) {
+ case SUCCESS:
+ ShrinkCurrentPart();
+ return *isolate_->factory()->NewConsString(accumulator(),
current_part_);
+ case UNCHANGED:
+ return isolate_->heap()->undefined_value();
+ case CIRCULAR:
+ return isolate_->Throw(*isolate_->factory()->NewTypeError(
+ "circular_structure", HandleVector<Object>(NULL, 0)));
+ case STACK_OVERFLOW:
+ return isolate_->StackOverflow();
+ default:
+ return Smi::FromInt(0);
+ }
+}
+
+
+template <bool is_ascii, typename Char>
+void BasicJsonStringifier::Append_(Char c) {
+ if (is_ascii) {
+ SeqAsciiString::cast(*current_part_)->SeqAsciiStringSet(
+ current_index_++, c);
+ } else {
+ SeqTwoByteString::cast(*current_part_)->SeqTwoByteStringSet(
+ current_index_++, c);
+ }
+ if (current_index_ == part_length_) Extend<is_ascii>();
+}
+
+
+template <bool is_ascii, typename Char>
+void BasicJsonStringifier::Append_(const Char* chars) {
+ for ( ; *chars != '\0'; chars++) Append_<is_ascii, Char>(*chars);
+}
+
+
+Handle<Object> BasicJsonStringifier::GetProperty(Handle<JSObject> object,
+ Handle<String> key) {
+ LookupResult lookup(isolate_);
+ object->LocalLookupRealNamedProperty(*key, &lookup);
+ if (!lookup.IsProperty()) return isolate_->factory()->undefined_value();
+ switch (lookup.type()) {
+ case NORMAL: {
+ Object* value = lookup.holder()->GetNormalizedProperty(&lookup);
+ ASSERT(!value->IsTheHole());
+ return Handle<Object>(value);
+ }
+ case FIELD: {
+ Object* value =
lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+ ASSERT(!value->IsTheHole());
+ return Handle<Object>(value);
+ }
+ case CONSTANT_FUNCTION:
+ return Handle<Object>(lookup.GetConstantFunction());
+ case CALLBACKS:
+ case HANDLER:
+ case INTERCEPTOR:
+ return Handle<Object>::null();
+ case TRANSITION:
+ case NONEXISTENT:
+ UNREACHABLE();
+ break;
+ }
+ return Handle<Object>::null();
+}
+
+
+bool BasicJsonStringifier::MayHaveToJsonFunction(Handle<JSObject> object) {
+ LookupResult lookup(isolate_);
+ object->LookupRealNamedProperty(*tojson_symbol_, &lookup);
+ if (!lookup.IsProperty()) return false;
+ Object* value;
+ switch (lookup.type()) {
+ case NORMAL:
+ value = lookup.holder()->GetNormalizedProperty(&lookup);
+ break;
+ case FIELD:
+ value = lookup.holder()->FastPropertyAt(lookup.GetFieldIndex());
+ break;
+ default:
+ return true;
+ }
+ ASSERT(!value->IsTheHole());
+ return value->IsSpecFunction();
+}
+
+
+BasicJsonStringifier::Result BasicJsonStringifier::StackPush(
+ Handle<Object> object) {
+ StackLimitCheck check(isolate_);
+ if (check.HasOverflowed()) return STACK_OVERFLOW;
+
+ int length = Smi::cast(stack_->length())->value();
+ FixedArray* elements = FixedArray::cast(stack_->elements());
+ for (int i = 0; i < length; i++) {
+ if (elements->get(i) == *object) {
+ return CIRCULAR;
+ }
+ }
+ stack_->EnsureSize(length + 1);
+ FixedArray::cast(stack_->elements())->set(length, *object);
+ stack_->set_length(Smi::FromInt(length + 1));
+ return SUCCESS;
+}
+
+
+void BasicJsonStringifier::StackPop() {
+ int length = Smi::cast(stack_->length())->value();
+ stack_->set_length(Smi::FromInt(length - 1));
+}
+
+
+template <bool deferred_key>
+BasicJsonStringifier::Result BasicJsonStringifier::Serialize_(
+ Handle<Object> object, bool comma, Handle<String> key) {
+ if (object->IsJSObject()) {
+ // We don't deal with custom toJSON functions.
+ if (MayHaveToJsonFunction(Handle<JSObject>::cast(object))) return
BAILOUT;
+
+ if (object->IsJSFunction()) {
+ return UNCHANGED;
+ } else if (object->IsJSArray()) {
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ return SerializeArray(Handle<JSArray>::cast(object));
+ } else if (object->IsJSValue()) {
+ // JSValue with a custom prototype.
+ if (object->GetPrototype()->IsJSReceiver()) return BAILOUT;
+ // Unpack value wrapper and fall through.
+ object = Handle<Object>(JSValue::cast(*object)->value());
+ } else {
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ return SerializeObject(Handle<JSObject>::cast(object));
+ }
+ }
+
+ if (object->IsString()) {
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ SerializeString(Handle<String>::cast(object));
+ return SUCCESS;
+ } else if (object->IsSmi()) {
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ return SerializeSmi(Smi::cast(*object));
+ } else if (object->IsHeapNumber()) {
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ return SerializeHeapNumber(Handle<HeapNumber>::cast(object));
+ } else if (object->IsOddball()) {
+ switch (Oddball::cast(*object)->kind()) {
+ case Oddball::kFalse:
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ Append("false");
+ return SUCCESS;
+ case Oddball::kTrue:
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ Append("true");
+ return SUCCESS;
+ case Oddball::kNull:
+ if (deferred_key) SerializeDeferredKey(comma, key);
+ Append("null");
+ return SUCCESS;
+ }
+ }
+
+ return UNCHANGED;
+}
+
+
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeSmi(Smi*
object) {
+ static const int kBufferSize = 100;
+ char chars[kBufferSize];
+ Vector<char> buffer(chars, kBufferSize);
+ Append(IntToCString(object->value(), buffer));
+ return SUCCESS;
+}
+
+
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeDouble(
+ double number) {
+ if (isinf(number) || isnan(number)) {
+ Append("null");
+ return SUCCESS;
+ }
+ static const int kBufferSize = 100;
+ char chars[kBufferSize];
+ Vector<char> buffer(chars, kBufferSize);
+ Append(DoubleToCString(number, buffer));
+ return SUCCESS;
+}
+
+
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeArray(
+ Handle<JSArray> object) {
+ HandleScope handle_scope(isolate_);
+ Result stack_push = StackPush(object);
+ if (stack_push != SUCCESS) return stack_push;
+ int length = Smi::cast(object->length())->value();
+ Append('[');
+ switch (object->GetElementsKind()) {
+ case FAST_SMI_ELEMENTS: {
+ Handle<FixedArray> elements = Handle<FixedArray>(
+ FixedArray::cast(object->elements()));
+ for (int i = 0; i < length; i++) {
+ if (i > 0) Append(',');
+ SerializeSmi(Smi::cast(elements->get(i)));
+ }
+ break;
+ }
+ case FAST_DOUBLE_ELEMENTS: {
+ Handle<FixedDoubleArray> elements = Handle<FixedDoubleArray>(
+ FixedDoubleArray::cast(object->elements()));
+ for (int i = 0; i < length; i++) {
+ if (i > 0) Append(',');
+ SerializeDouble(elements->get_scalar(i));
+ }
+ break;
+ }
+ case FAST_ELEMENTS: {
+ Handle<FixedArray> elements = Handle<FixedArray>(
+ FixedArray::cast(object->elements()));
+ for (int i = 0; i < length; i++) {
+ if (i > 0) Append(',');
+ Result result = Serialize(Handle<Object>(elements->get(i)));
+ if (result == SUCCESS) continue;
+ if (result == UNCHANGED) {
+ Append("null");
+ } else {
+ return result;
+ }
+ }
+ break;
+ }
+ default:
+ return BAILOUT;
+ }
+ Append(']');
+ StackPop();
+ current_part_ = handle_scope.CloseAndEscape(current_part_);
+ return SUCCESS;
+}
+
+
+BasicJsonStringifier::Result BasicJsonStringifier::SerializeObject(
+ Handle<JSObject> object) {
+ HandleScope handle_scope(isolate_);
+ Result stack_push = StackPush(object);
+ if (stack_push != SUCCESS) return stack_push;
+ if (object->IsJSGlobalProxy()) return BAILOUT;
+ bool threw = false;
+ Handle<FixedArray> contents =
+ GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
+ if (threw) return BAILOUT;
+ Append('{');
+ bool comma = false;
+ for (int i = 0; i < contents->length(); i++) {
+ Object* key = contents->get(i);
+ Handle<String> key_handle;
+ Handle<Object> property;
+ if (key->IsString()) {
+ key_handle = Handle<String>(String::cast(key));
+ property = GetProperty(object, key_handle);
+ } else {
+ ASSERT(key->IsNumber());
+ key_handle =
isolate_->factory()->NumberToString(Handle<Object>(key));
+ uint32_t index;
+ if (key->IsSmi()) {
+ property = Object::GetElement(object, Smi::cast(key)->value());
+ } else if (key_handle->AsArrayIndex(&index)) {
+ property = Object::GetElement(object, index);
+ } else {
+ property = GetProperty(object, key_handle);
+ }
+ }
+ if (property.is_null()) return BAILOUT;
+ Result result = SerializeDeferred(property, comma, key_handle);
+ if (!comma && result == SUCCESS) comma = true;
+ if (result >= BAILOUT) return result;
+ }
+ Append('}');
+ StackPop();
+ current_part_ = handle_scope.CloseAndEscape(current_part_);
+ return SUCCESS;
+}
+
+
+void BasicJsonStringifier::ShrinkCurrentPart() {
+ ASSERT(current_index_ < part_length_);
+ if (current_index_ == 0) {
+ current_part_ = isolate_->factory()->empty_string();
+ return;
+ }
+
+ int string_size, allocated_string_size;
+ if (is_ascii_) {
+ allocated_string_size = SeqAsciiString::SizeFor(part_length_);
+ string_size = SeqAsciiString::SizeFor(current_index_);
+ } else {
+ allocated_string_size = SeqTwoByteString::SizeFor(part_length_);
+ string_size = SeqTwoByteString::SizeFor(current_index_);
+ }
+
+ int delta = allocated_string_size - string_size;
+ current_part_->set_length(current_index_);
+
+ // String sizes are pointer size aligned, so that we can use filler
objects
+ // that are a multiple of pointer size.
+ Address end_of_string = current_part_->address() + string_size;
+ isolate_->heap()->CreateFillerObjectAt(end_of_string, delta);
+ if (Marking::IsBlack(Marking::MarkBitFrom(*current_part_))) {
+ MemoryChunk::IncrementLiveBytesFromMutator(
+ current_part_->address(), -delta);
+ }
+}
+
+
+template <bool is_ascii>
+void BasicJsonStringifier::Extend() {
+ set_accumulator(
+ isolate_->factory()->NewConsString(accumulator(), current_part_));
+ if (part_length_ <= kMaxPartLength / kPartLengthGrowthFactor) {
+ part_length_ *= kPartLengthGrowthFactor;
+ }
+ if (is_ascii) {
+ current_part_ =
+ isolate_->factory()->NewRawAsciiString(part_length_);
+ } else {
+ current_part_ =
+ isolate_->factory()->NewRawTwoByteString(part_length_);
+ }
+ current_index_ = 0;
+}
+
+
+void BasicJsonStringifier::ChangeEncoding() {
+ ShrinkCurrentPart();
+ set_accumulator(
+ isolate_->factory()->NewConsString(accumulator(), current_part_));
+ current_part_ =
+ isolate_->factory()->NewRawTwoByteString(part_length_);
+ current_index_ = 0;
+ is_ascii_ = false;
+}
+
+
+template <typename SrcChar, typename DestChar>
+void BasicJsonStringifier::SerializeStringUnchecked_(const SrcChar* src,
+ DestChar* dest,
+ int length) {
+ dest += current_index_;
+ DestChar* dest_start = dest;
+
+ // Assert that uc16 character is not truncated down to 8 bit.
+ // The <uc16, char> version of this method must not be called.
+ ASSERT(sizeof(*dest) >= sizeof(*src));
+
+ *(dest++) = '"';
+ for (int i = 0; i < length; i++) {
+ SrcChar c = src[i];
+ if (DoNotEscape(c)) {
+ *(dest++) = static_cast<DestChar>(c);
+ } else {
+ const char* chars = &JsonEscapeTable[c * kJsonEscapeTableEntrySize];
+ while (*chars != '\0') *(dest++) = *(chars++);
+ }
+ }
+
+ *(dest++) = '"';
+ current_index_ += static_cast<int>(dest - dest_start);
+}
+
+
+template <bool is_ascii, typename Char>
+void BasicJsonStringifier::SerializeString_(Vector<const Char> vector,
+ Handle<String> string) {
+ int length = vector.length();
+ // We make a rough estimate to find out if the current string can be
+ // serialized without allocating a new string part. The worst case
length of
+ // an escaped character is 6. Shifting left by 3 is a more pessimistic
+ // estimate than multiplying by 6, but faster to calculate.
+ static const int kEnclosingQuotesLength = 2;
+ if (current_index_ + (length << 3) + kEnclosingQuotesLength <
part_length_) {
+ if (is_ascii) {
+ SerializeStringUnchecked_(
+ vector.start(),
+ SeqAsciiString::cast(*current_part_)->GetChars(),
+ length);
+ } else {
+ SerializeStringUnchecked_(
+ vector.start(),
+ SeqTwoByteString::cast(*current_part_)->GetChars(),
+ length);
+ }
+ } else {
+ Append_<is_ascii, char>('"');
+ String* string_location = *string;
+ for (int i = 0; i < length; i++) {
+ Char c = vector[i];
+ if (DoNotEscape(c)) {
+ Append_<is_ascii, Char>(c);
+ } else {
+ Append_<is_ascii, char>(
+ &JsonEscapeTable[c * kJsonEscapeTableEntrySize]);
+ }
+ // If GC moved the string, we need to refresh the vector.
+ if (*string != string_location) {
+ vector = GetCharVector<Char>(string);
+ string_location = *string;
+ }
+ }
+ Append_<is_ascii, char>('"');
+ }
+}
+
+
+template <>
+bool BasicJsonStringifier::DoNotEscape(char c) {
+ return c >= '#' && c <= '~' && c != '\\';
+}
+
+
+template <>
+bool BasicJsonStringifier::DoNotEscape(uc16 c) {
+ return (c >= 0x80) || (c >= '#' && c <= '~' && c != '\\');
+}
+
+
+template <>
+Vector<const char> BasicJsonStringifier::GetCharVector(Handle<String>
string) {
+ String::FlatContent flat = string->GetFlatContent();
+ ASSERT(flat.IsAscii());
+ return flat.ToAsciiVector();
+}
+
+
+template <>
+Vector<const uc16> BasicJsonStringifier::GetCharVector(Handle<String>
string) {
+ String::FlatContent flat = string->GetFlatContent();
+ ASSERT(flat.IsTwoByte());
+ return flat.ToUC16Vector();
+}
+
+
+void BasicJsonStringifier::SerializeString(Handle<String> object) {
+ FlattenString(object);
+ String::FlatContent flat = object->GetFlatContent();
+ if (is_ascii_) {
+ if (flat.IsAscii()) {
+ SerializeString_<true, char>(flat.ToAsciiVector(), object);
+ } else {
+ ChangeEncoding();
+ SerializeString(object);
+ }
+ } else {
+ if (flat.IsAscii()) {
+ SerializeString_<false, char>(flat.ToAsciiVector(), object);
+ } else {
+ SerializeString_<false, uc16>(flat.ToUC16Vector(), object);
+ }
+ }
+}
+
+} } // namespace v8::internal
+
+#endif // V8_JSON_STRINGIFIER_H_
=======================================
--- /dev/null
+++ /trunk/src/object-observe.js Wed Oct 31 03:02:10 2012
@@ -0,0 +1,164 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"use strict";
+
+var InternalObjectIsFrozen = $Object.isFrozen;
+var InternalObjectFreeze = $Object.freeze;
+
+var InternalWeakMapProto = {
+ __proto__: null,
+ set: $WeakMap.prototype.set,
+ get: $WeakMap.prototype.get,
+ has: $WeakMap.prototype.has
+}
+
+function createInternalWeakMap() {
+ var map = new $WeakMap;
+ map.__proto__ = InternalWeakMapProto;
+ return map;
+}
+
+var observerInfoMap = createInternalWeakMap();
+var objectInfoMap = createInternalWeakMap();
+
+function ObjectObserve(object, callback) {
+ if (!IS_SPEC_OBJECT(object))
+ throw MakeTypeError("observe_non_object", ["observe"]);
+ if (!IS_SPEC_FUNCTION(callback))
+ throw MakeTypeError("observe_non_function", ["observe"]);
+ if (InternalObjectIsFrozen(callback))
+ throw MakeTypeError("observe_callback_frozen");
+
+ if (!observerInfoMap.has(callback)) {
+ // TODO: setup observerInfo.priority.
+ observerInfoMap.set(callback, {
+ pendingChangeRecords: null
+ });
+ }
+
+ var objectInfo = objectInfoMap.get(object);
+ if (IS_UNDEFINED(objectInfo)) {
+ // TODO: setup objectInfo.notifier
+ objectInfo = {
+ changeObservers: new InternalArray(callback)
+ };
+ objectInfoMap.set(object, objectInfo);
+ return;
+ }
+
+ var changeObservers = objectInfo.changeObservers;
+ if (changeObservers.indexOf(callback) >= 0)
+ return;
+
+ changeObservers.push(callback);
+}
+
+function ObjectUnobserve(object, callback) {
+ if (!IS_SPEC_OBJECT(object))
+ throw MakeTypeError("observe_non_object", ["unobserve"]);
+
+ var objectInfo = objectInfoMap.get(object);
+ if (IS_UNDEFINED(objectInfo))
+ return;
+
+ var changeObservers = objectInfo.changeObservers;
+ var index = changeObservers.indexOf(callback);
+ if (index < 0)
+ return;
+
+ changeObservers.splice(index, 1);
+}
+
+function EnqueueChangeRecord(changeRecord, observers) {
+ for (var i = 0; i < observers.length; i++) {
+ var observer = observers[i];
+ var observerInfo = observerInfoMap.get(observer);
+
+ // TODO: "activate" the observer
+
+ if (IS_NULL(observerInfo.pendingChangeRecords)) {
+ observerInfo.pendingChangeRecords = new InternalArray(changeRecord);
+ } else {
+ observerInfo.pendingChangeRecords.push(changeRecord);
+ }
+ }
+}
+
+function ObjectNotify(object, changeRecord) {
+ // TODO: notifier needs to be [[THIS]]
+ if (!IS_STRING(changeRecord.type))
+ throw MakeTypeError("observe_type_non_string");
+
+ var objectInfo = objectInfoMap.get(object);
+ if (IS_UNDEFINED(objectInfo))
+ return;
+
+ var newRecord = {
+ object: object // TODO: Needs to be 'object' retreived from notifier
+ };
+ for (var prop in changeRecord) {
+ if (prop === 'object')
+ continue;
+ newRecord[prop] = changeRecord[prop];
+ }
+ InternalObjectFreeze(newRecord);
+
+ EnqueueChangeRecord(newRecord, objectInfo.changeObservers);
+}
+
+function ObjectDeliverChangeRecords(callback) {
+ if (!IS_SPEC_FUNCTION(callback))
+ throw MakeTypeError("observe_non_function", ["deliverChangeRecords"]);
+
+ var observerInfo = observerInfoMap.get(callback);
+ if (IS_UNDEFINED(observerInfo))
+ return;
+
+ var pendingChangeRecords = observerInfo.pendingChangeRecords;
+ if (IS_NULL(pendingChangeRecords))
+ return;
+
+ observerInfo.pendingChangeRecords = null;
+ var delivered = [];
+ %MoveArrayContents(pendingChangeRecords, delivered);
+ try {
+ %Call(void 0, delivered, callback);
+ } catch (ex) {}
+}
+
+function SetupObjectObserve() {
+ %CheckIsBootstrapping();
+ InstallFunctions($Object, DONT_ENUM, $Array(
+ "deliverChangeRecords", ObjectDeliverChangeRecords,
+ "notify", ObjectNotify, // TODO: Remove when getNotifier is
implemented.
+ "observe", ObjectObserve,
+ "unobserve", ObjectUnobserve
+ ));
+}
+
+SetupObjectObserve();
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/harmony/object-observe.js Wed Oct 31 03:02:10 2012
@@ -0,0 +1,241 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --harmony-object-observe
+
+var allObservers = [];
+function reset() {
+ allObservers.forEach(function(observer) { observer.reset(); });
+}
+
+function createObserver() {
+ "use strict"; // So that |this| in callback can be undefined.
+
+ var observer = {
+ records: undefined,
+ callbackCount: 0,
+ reset: function() {
+ this.records = undefined;
+ this.callbackCount = 0;
+ },
+ assertNotCalled: function() {
+ assertEquals(undefined, this.records);
+ assertEquals(0, this.callbackCount);
+ },
+ assertCalled: function() {
+ assertEquals(1, this.callbackCount);
+ },
+ assertRecordCount: function(count) {
+ this.assertCalled();
+ assertEquals(count, this.records.length);
+ },
+ assertCallbackRecords: function(recs) {
+ this.assertRecordCount(recs.length);
+ for (var i = 0; i < recs.length; i++) {
+ assertSame(this.records[i].object, recs[i].object);
+ assertEquals('string', typeof recs[i].type);
+ assertPropertiesEqual(this.records[i], recs[i]);
+ }
+ }
+ };
+
+ observer.callback = function(r) {
+ assertEquals(undefined, this);
+ assertEquals('object', typeof r);
+ assertTrue(r instanceof Array)
+ observer.records = r;
+ observer.callbackCount++;
+ };
+
+ observer.reset();
+ allObservers.push(observer);
+ return observer;
+}
+
+var observer = createObserver();
+assertEquals("function", typeof observer.callback);
+var obj = {};
+
+function frozenFunction() {}
+Object.freeze(frozenFunction);
+var nonFunction = {};
+var changeRecordWithAccessor = { type: 'foo' };
+var recordCreated = false;
+Object.defineProperty(changeRecordWithAccessor, 'name', {
+ get: function() {
+ recordCreated = true;
+ },
+ enumerable: true
+})
+
+// Object.observe
+assertThrows(function() { Object.observe("non-object", observer.callback);
}, TypeError);
+assertThrows(function() { Object.observe(obj, nonFunction); }, TypeError);
+assertThrows(function() { Object.observe(obj, frozenFunction); },
TypeError);
+
+// Object.unobserve
+assertThrows(function() { Object.unobserve(4, observer.callback); },
TypeError);
+
+// Object.notify
+assertThrows(function() { Object.notify(obj, {}); }, TypeError);
+assertThrows(function() { Object.notify(obj, { type: 4 }); }, TypeError);
+Object.notify(obj, changeRecordWithAccessor);
+assertFalse(recordCreated);
+
+// Object.deliverChangeRecords
+assertThrows(function() { Object.deliverChangeRecords(nonFunction); },
TypeError);
+
+// Multiple records are delivered.
+Object.observe(obj, observer.callback);
+Object.notify(obj, {
+ object: obj,
+ type: 'updated',
+ name: 'foo',
+ expando: 1
+});
+
+Object.notify(obj, {
+ object: obj,
+ type: 'deleted',
+ name: 'bar',
+ expando2: 'str'
+});
+Object.deliverChangeRecords(observer.callback);
+observer.assertCallbackRecords([
+ { object: obj, name: 'foo', type: 'updated', expando: 1 },
+ { object: obj, name: 'bar', type: 'deleted', expando2: 'str' }
+]);
+
+// No delivery takes place if no records are pending
+reset();
+Object.deliverChangeRecords(observer.callback);
+observer.assertNotCalled();
+
+// Multiple observation has no effect.
+reset();
+Object.observe(obj, observer.callback);
+Object.observe(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+});
+Object.deliverChangeRecords(observer.callback);
+observer.assertCalled();
+
+// Observation can be stopped.
+reset();
+Object.unobserve(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+});
+Object.deliverChangeRecords(observer.callback);
+observer.assertNotCalled();
+
+// Multiple unobservation has no effect
+reset();
+Object.unobserve(obj, observer.callback);
+Object.unobserve(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+});
+Object.deliverChangeRecords(observer.callback);
+observer.assertNotCalled();
+
+// Re-observation works and only includes changeRecords after of call.
+reset();
+Object.notify(obj, {
+ type: 'foo',
+});
+Object.observe(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+});
+records = undefined;
+Object.deliverChangeRecords(observer.callback);
+observer.assertRecordCount(1);
+
+// Observing a continuous stream of changes, while itermittantly
unobserving.
+reset();
+Object.observe(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+ val: 1
+});
+
+Object.unobserve(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+ val: 2
+});
+
+Object.observe(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+ val: 3
+});
+
+Object.unobserve(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+ val: 4
+});
+
+Object.observe(obj, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+ val: 5
+});
+
+Object.unobserve(obj, observer.callback);
+Object.deliverChangeRecords(observer.callback);
+observer.assertCallbackRecords([
+ { object: obj, type: 'foo', val: 1 },
+ { object: obj, type: 'foo', val: 3 },
+ { object: obj, type: 'foo', val: 5 }
+]);
+
+// Observing multiple objects; records appear in order;.
+reset();
+var obj2 = {};
+var obj3 = {}
+Object.observe(obj, observer.callback);
+Object.observe(obj3, observer.callback);
+Object.observe(obj2, observer.callback);
+Object.notify(obj, {
+ type: 'foo',
+});
+Object.notify(obj2, {
+ type: 'foo',
+});
+Object.notify(obj3, {
+ type: 'foo',
+});
+Object.deliverChangeRecords(observer.callback);
+observer.assertCallbackRecords([
+ { object: obj, type: 'foo' },
+ { object: obj2, type: 'foo' },
+ { object: obj3, type: 'foo' }
+]);
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/json-recursive.js Wed Oct 31 03:02:10 2012
@@ -0,0 +1,66 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+var a = {};
+for (i = 0; i < 10000; i++) {
+ var current = {};
+ current.a = a;
+ a = current;
+}
+
+function rec(a,b,c,d,e,f,g,h,i,j,k,l,m,n) {
+ JSON.stringify(a);
+ rec(a,b,c,d,e,f,g,h,i,j,k,l,m,n);
+}
+
+assertThrows(function() { rec(1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4) },
+ RangeError);
+
+
+var depth1 = 1500;
+var depth2 = 10000;
+var deepArray = [];
+for (var i = 0; i < depth1; i++) deepArray = [deepArray];
+JSON.stringify(deepArray);
+for (var i = depth1; i < depth2; i++) deepArray = [deepArray];
+assertThrows(function() { JSON.stringify(deepArray); }, RangeError);
+
+
+var deepObject = {};
+for (var i = 0; i < depth1; i++) deepObject = { next: deepObject };
+JSON.stringify(deepObject);
+for (var i = depth1; i < depth2; i++) deepObject = { next: deepObject };
+assertThrows(function() { JSON.stringify(deepObject); }, RangeError);
+
+
+var str = "[1]";
+for (var i = 0; i < 100000; i++) {
+ str = "[1," + str + "]";
+}
+
+assertThrows(function() { JSON.parse(str); }, RangeError);
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/json2.js Wed Oct 31 03:02:10 2012
@@ -0,0 +1,48 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var fast_smi = [1, 2, 3, 4];
+fast_smi.__proto__ = [7, 7, 7, 7];
+delete fast_smi[2];
+assertTrue(%HasFastSmiElements(fast_smi));
+assertEquals("[1,2,7,4]", JSON.stringify(fast_smi));
+
+var fast_double = [1.1, 2, 3, 4];
+fast_double.__proto__ = [7, 7, 7, 7];
+
+delete fast_double[2];
+assertTrue(%HasFastDoubleElements(fast_double));
+assertEquals("[1.1,2,7,4]", JSON.stringify(fast_double));
+
+var fast_obj = [1, 2, {}, {}];
+fast_obj.__proto__ = [7, 7, 7, 7];
+
+delete fast_obj[2];
+assertTrue(%HasFastObjectElements(fast_obj));
+assertEquals("[1,2,7,{}]", JSON.stringify(fast_obj));
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-157520.js Wed Oct 31 03:02:10
2012
@@ -0,0 +1,38 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --nocrankshaft
+
+(function(){
+ var f = function(arg) {
+ arg = 2;
+ return arguments[0];
+ };
+ for (var i = 0; i < 50000; i++) {
+ assertSame(2, f(1));
+ }
+})();
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-158185.js Wed Oct 31 03:02:10
2012
@@ -0,0 +1,39 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+assertEquals("0023456",
+ Object.keys(JSON.parse('{"0023456": 1}'))[0]);
+assertEquals("1234567890123",
+ Object.keys(JSON.parse('{"1234567890123": 1}'))[0]);
+assertEquals("123456789ABCD",
+ Object.keys(JSON.parse('{"123456789ABCD": 1}'))[0]);
+assertEquals("12A",
+ Object.keys(JSON.parse('{"12A": 1}'))[0]);
+
+assertEquals(1, JSON.parse('{"0":1}')[0]);
+assertEquals(undefined, JSON.parse('{"00":1}')[0]);
+
=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-json-stringify-gc.js Wed Oct 31
03:02:10 2012
@@ -0,0 +1,41 @@
+// Copyright 2012 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+var a = [];
+var new_space_string = "";
+for (var i = 0; i < 128; i++) {
+ new_space_string += String.fromCharCode((Math.random() * 26 + 65) | 0);
+}
+for (var i = 0; i < 10000; i++) a.push(new_space_string);
+
+// At some point during the first stringify, allocation causes a GC and
+// new_space_string is moved to old space. Make sure that this does not
+// screw up reading from the correct location.
+json1 = JSON.stringify(a);
+json2 = JSON.stringify(a);
+assertEquals(json1, json2);
+
=======================================
--- /trunk/AUTHORS Fri Jul 27 01:03:27 2012
+++ /trunk/AUTHORS Wed Oct 31 03:02:10 2012
@@ -20,6 +20,7 @@
Craig Schlenter <craig.s...@gmail.com>
Daniel Andersson <kodand...@gmail.com>
Daniel James <dnl...@gmail.com>
+Derek J Conrod <dco...@codeaurora.org>
Dineel D Sule <ds...@codeaurora.org>
Erich Ocean <erich...@me.com>
Fedor Indutny <fe...@indutny.com>
@@ -44,6 +45,7 @@
Patrick Gansterer <par...@paroga.com>
Peter Varga <pva...@inf.u-szeged.hu>
Rafal Krypa <ra...@krypa.net>
+Rajeev R Krithivasan <rkri...@codeaurora.org>
Rene Rebe <re...@exactcode.de>
Robert Mustacchi <r...@fingolfin.org>
Rodolph Perfetta <rodolph....@arm.com>
@@ -53,6 +55,7 @@
Subrato K De <subra...@codeaurora.org>
Tobias Burnus <bur...@net-b.de>
Vlad Burlik <vla...@gmail.com>
+Xi Qian <xi....@intel.com>
Yuqiang Xian <yuqian...@intel.com>
Zaheer Ahmad <zah...@codeaurora.org>
Zhongping Wang <kewpi...@gmail.com>
=======================================
--- /trunk/ChangeLog Mon Oct 22 06:09:53 2012
+++ /trunk/ChangeLog Wed Oct 31 03:02:10 2012
@@ -1,3 +1,13 @@
+2012-10-31: Version 3.15.0
+
+ Loosened aligned code target requirement on ARM (issue 2380)
+
+ Fixed JSON.parse to treat leading zeros correctly.
+ (Chromium issue 158185)
+
+ Performance and stability improvements on all platforms.
+
+
2012-10-22: Version 3.14.5

Killed off the SCons based build.
=======================================
--- /trunk/build/android.gypi Thu Sep 6 06:50:42 2012
+++ /trunk/build/android.gypi Wed Oct 31 03:02:10 2012
@@ -122,8 +122,6 @@
'ldflags': [
'-nostdlib',
'-Wl,--no-undefined',
- # Don't export symbols from statically linked libraries.
- '-Wl,--exclude-libs=ALL',
],
'libraries!': [
'-lrt', # librt is built into Bionic.
@@ -219,6 +217,13 @@
['_type=="shared_library"', {
'ldflags': [
'-Wl,-shared,-Bsymbolic',
+ '<(android_lib)/crtbegin_so.o',
+ ],
+ }],
+ ['_type=="static_library"', {
+ 'ldflags': [
+ # Don't export symbols from statically linked libraries.
+ '-Wl,--exclude-libs=ALL',
],
}],
],
=======================================
--- /trunk/build/common.gypi Mon Oct 22 06:09:53 2012
+++ /trunk/build/common.gypi Wed Oct 31 03:02:10 2012
@@ -134,6 +134,11 @@
'V8_TARGET_ARCH_ARM',
],
'conditions': [
+ ['armv7==1', {
+ 'defines': [
+ 'CAN_USE_ARMV7_INSTRUCTIONS=1',
+ ],
+ }],
[ 'v8_can_use_unaligned_accesses=="true"', {
'defines': [
'CAN_USE_UNALIGNED_ACCESSES=1',
@@ -200,10 +205,11 @@
['mips_arch_variant=="mips32r2"', {
'cflags': ['-mips32r2', '-Wa,-mips32r2'],
}],
+ ['mips_arch_variant=="mips32r1"', {
+ 'cflags': ['-mips32', '-Wa,-mips32'],
+ }],
['mips_arch_variant=="loongson"', {
'cflags': ['-mips3', '-Wa,-mips3'],
- }, {
- 'cflags': ['-mips32', '-Wa,-mips32'],
}],
],
}],
=======================================
--- /trunk/include/v8.h Mon Oct 22 06:09:53 2012
+++ /trunk/include/v8.h Wed Oct 31 03:02:10 2012
@@ -2773,6 +2773,7 @@
HeapStatistics();
size_t total_heap_size() { return total_heap_size_; }
size_t total_heap_size_executable() { return
total_heap_size_executable_; }
+ size_t total_physical_size() { return total_physical_size_; }
size_t used_heap_size() { return used_heap_size_; }
size_t heap_size_limit() { return heap_size_limit_; }

@@ -2781,11 +2782,15 @@
void set_total_heap_size_executable(size_t size) {
total_heap_size_executable_ = size;
}
+ void set_total_physical_size(size_t size) {
+ total_physical_size_ = size;
+ }
void set_used_heap_size(size_t size) { used_heap_size_ = size; }
void set_heap_size_limit(size_t size) { heap_size_limit_ = size; }

size_t total_heap_size_;
size_t total_heap_size_executable_;
+ size_t total_physical_size_;
size_t used_heap_size_;
size_t heap_size_limit_;

=======================================
--- /trunk/src/api.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/api.cc Wed Oct 31 03:02:10 2012
@@ -643,7 +643,7 @@

void V8::MarkIndependent(i::Object** object) {
i::Isolate* isolate = i::Isolate::Current();
- LOG_API(isolate, "MakeIndependent");
+ LOG_API(isolate, "MarkIndependent");
isolate->global_handles()->MarkIndependent(object);
}

@@ -4314,6 +4314,7 @@

HeapStatistics::HeapStatistics(): total_heap_size_(0),
total_heap_size_executable_(0),
+ total_physical_size_(0),
used_heap_size_(0),
heap_size_limit_(0) { }

@@ -4323,6 +4324,7 @@
// Isolate is unitialized thus heap is not configured yet.
heap_statistics->set_total_heap_size(0);
heap_statistics->set_total_heap_size_executable(0);
+ heap_statistics->set_total_physical_size(0);
heap_statistics->set_used_heap_size(0);
heap_statistics->set_heap_size_limit(0);
return;
@@ -4332,6 +4334,7 @@
heap_statistics->set_total_heap_size(heap->CommittedMemory());
heap_statistics->set_total_heap_size_executable(
heap->CommittedMemoryExecutable());
+
heap_statistics->set_total_physical_size(heap->CommittedPhysicalMemory());
heap_statistics->set_used_heap_size(heap->SizeOfObjects());
heap_statistics->set_heap_size_limit(heap->MaxReserved());
}
=======================================
--- /trunk/src/arm/assembler-arm-inl.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/arm/assembler-arm-inl.h Wed Oct 31 03:02:10 2012
@@ -86,8 +86,7 @@

void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
- Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(
- reinterpret_cast<intptr_t>(target) & ~3));
+ Assembler::set_target_address_at(pc_, target);
if (mode == UPDATE_WRITE_BARRIER && host() != NULL &&
IsCodeTarget(rmode_)) {
Object* target_code = Code::GetCodeFromTargetAddress(target);
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
@@ -473,14 +472,12 @@


Address Assembler::target_address_at(Address pc) {
- return reinterpret_cast<Address>(
- reinterpret_cast<intptr_t>(target_pointer_at(pc)) & ~3);
+ return target_pointer_at(pc);
}


void Assembler::set_target_address_at(Address pc, Address target) {
- set_target_pointer_at(pc, reinterpret_cast<Address>(
- reinterpret_cast<intptr_t>(target) & ~3));
+ set_target_pointer_at(pc, target);
}


=======================================
--- /trunk/src/arm/assembler-arm.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/arm/assembler-arm.cc Wed Oct 31 03:02:10 2012
@@ -2730,9 +2730,9 @@
b(&after_pool);
}

- // Put down constant pool marker "Undefined instruction" as specified
by
- // A5.6 (ARMv7) Instruction set encoding.
- emit(kConstantPoolMarker | num_pending_reloc_info_);
+ // Put down constant pool marker "Undefined instruction".
+ emit(kConstantPoolMarker |
+ EncodeConstantPoolLength(num_pending_reloc_info_));

// Emit constant pool entries.
for (int i = 0; i < num_pending_reloc_info_; i++) {
=======================================
--- /trunk/src/arm/assembler-arm.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/arm/assembler-arm.h Wed Oct 31 03:02:10 2012
@@ -1329,6 +1329,8 @@
// and the accessed constant.
static const int kMaxDistToPool = 4*KB;
static const int kMaxNumPendingRelocInfo = kMaxDistToPool/kInstrSize;
+ STATIC_ASSERT((kConstantPoolLengthMaxMask & kMaxNumPendingRelocInfo) ==
+ kMaxNumPendingRelocInfo);

// Postpone the generation of the constant pool for the specified number
of
// instructions.
=======================================
--- /trunk/src/arm/constants-arm.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/arm/constants-arm.h Wed Oct 31 03:02:10 2012
@@ -84,9 +84,18 @@
namespace internal {

// Constant pool marker.
-const int kConstantPoolMarkerMask = 0xffe00000;
-const int kConstantPoolMarker = 0x0c000000;
-const int kConstantPoolLengthMask = 0x001ffff;
+// Use UDF, the permanently undefined instruction.
+const int kConstantPoolMarkerMask = 0xfff000f0;
+const int kConstantPoolMarker = 0xe7f000f0;
+const int kConstantPoolLengthMaxMask = 0xffff;
+inline int EncodeConstantPoolLength(int length) {
+ ASSERT((length & kConstantPoolLengthMaxMask) == length);
+ return ((length & 0xfff0) << 4) | (length & 0xf);
+}
+inline int DecodeConstantPoolLength(int instr) {
+ ASSERT((instr & kConstantPoolMarkerMask) == kConstantPoolMarker);
+ return ((instr >> 4) & 0xfff0) | (instr & 0xf);
+}

// Number of registers in normal ARM mode.
const int kNumRegisters = 16;
=======================================
--- /trunk/src/arm/disasm-arm.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/arm/disasm-arm.cc Wed Oct 31 03:02:10 2012
@@ -1388,7 +1388,7 @@
int Decoder::ConstantPoolSizeAt(byte* instr_ptr) {
if (IsConstantPoolAt(instr_ptr)) {
int instruction_bits = *(reinterpret_cast<int*>(instr_ptr));
- return instruction_bits & kConstantPoolLengthMask;
+ return DecodeConstantPoolLength(instruction_bits);
} else {
return -1;
}
@@ -1410,8 +1410,7 @@
if ((instruction_bits & kConstantPoolMarkerMask) == kConstantPoolMarker)
{
out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_,
"constant pool begin (length %d)",
- instruction_bits &
- kConstantPoolLengthMask);
+
DecodeConstantPoolLength(instruction_bits));
return Instruction::kInstrSize;
}
switch (instr->TypeValue()) {
=======================================
--- /trunk/src/arm/lithium-codegen-arm.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/arm/lithium-codegen-arm.cc Wed Oct 31 03:02:10 2012
@@ -4936,7 +4936,6 @@
DoCheckMapCommon(temp1, temp2,
Handle<Map>(current_prototype->map()),
ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment());
- DeoptimizeIf(ne, instr->environment());
}


=======================================
--- /trunk/src/array.js Mon Oct 22 06:09:53 2012
+++ /trunk/src/array.js Wed Oct 31 03:02:10 2012
@@ -1549,9 +1549,11 @@
// exposed to user code.
// Adding only the functions that are actually used.
SetUpLockedPrototype(InternalArray, $Array(), $Array(
+ "indexOf", getFunction("indexOf", ArrayIndexOf),
"join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop),
- "push", getFunction("push", ArrayPush)
+ "push", getFunction("push", ArrayPush),
+ "splice", getFunction("splice", ArraySplice)
));
}

=======================================
--- /trunk/src/bootstrapper.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/bootstrapper.cc Wed Oct 31 03:02:10 2012
@@ -1828,6 +1828,11 @@
"native collection.js") == 0) {
if (!CompileExperimentalBuiltin(isolate(), i)) return false;
}
+ if (FLAG_harmony_object_observe &&
+ strcmp(ExperimentalNatives::GetScriptName(i).start(),
+ "native object-observe.js") == 0) {
+ if (!CompileExperimentalBuiltin(isolate(), i)) return false;
+ }
}

InstallExperimentalNativeFunctions();
=======================================
--- /trunk/src/compilation-cache.cc Wed Aug 29 08:32:24 2012
+++ /trunk/src/compilation-cache.cc Wed Oct 31 03:02:10 2012
@@ -98,7 +98,7 @@


void CompilationSubCache::IterateFunctions(ObjectVisitor* v) {
- Object* undefined = isolate()->heap()->raw_unchecked_undefined_value();
+ Object* undefined = isolate()->heap()->undefined_value();
for (int i = 0; i < generations_; i++) {
if (tables_[i] != undefined) {

reinterpret_cast<CompilationCacheTable*>(tables_[i])->IterateElements(v);
=======================================
--- /trunk/src/contexts.cc Thu Sep 20 05:51:09 2012
+++ /trunk/src/contexts.cc Wed Oct 31 03:02:10 2012
@@ -250,8 +250,6 @@
element = JSFunction::cast(element)->next_function_link();
}
}
-
- CHECK(function->next_function_link()->IsUndefined());

// Check that the context belongs to the weak native contexts list.
bool found = false;
@@ -265,6 +263,16 @@
}
CHECK(found);
#endif
+
+ // If the function link field is already used then the function was
+ // enqueued as a code flushing candidate and we remove it now.
+ if (!function->next_function_link()->IsUndefined()) {
+ CodeFlusher* flusher =
GetHeap()->mark_compact_collector()->code_flusher();
+ flusher->EvictCandidate(function);
+ }
+
+ ASSERT(function->next_function_link()->IsUndefined());
+
function->set_next_function_link(get(OPTIMIZED_FUNCTIONS_LIST));
set(OPTIMIZED_FUNCTIONS_LIST, function);
}
=======================================
--- /trunk/src/deoptimizer.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/deoptimizer.cc Wed Oct 31 03:02:10 2012
@@ -62,6 +62,13 @@
lazy_deoptimization_entry_code_);
lazy_deoptimization_entry_code_ = NULL;
}
+ DeoptimizingCodeListNode* current = deoptimizing_code_list_;
+ while (current != NULL) {
+ DeoptimizingCodeListNode* prev = current;
+ current = current->next();
+ delete prev;
+ }
+ deoptimizing_code_list_ = NULL;
}


=======================================
--- /trunk/src/elements.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/elements.cc Wed Oct 31 03:02:10 2012
@@ -503,8 +503,8 @@
Map* map = fixed_array_base->map();
// Arrays that have been shifted in place can't be verified.
Heap* heap = holder->GetHeap();
- if (map == heap->raw_unchecked_one_pointer_filler_map() ||
- map == heap->raw_unchecked_two_pointer_filler_map() ||
+ if (map == heap->one_pointer_filler_map() ||
+ map == heap->two_pointer_filler_map() ||
map == heap->free_space_map()) {
return;
}
=======================================
--- /trunk/src/extensions/gc-extension.cc Fri Mar 30 01:38:13 2012
+++ /trunk/src/extensions/gc-extension.cc Wed Oct 31 03:02:10 2012
@@ -40,7 +40,11 @@


v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
- HEAP->CollectAllGarbage(Heap::kNoGCFlags, "gc extension");
+ if (args[0]->BooleanValue()) {
+ HEAP->CollectGarbage(NEW_SPACE, "gc extension");
+ } else {
+ HEAP->CollectAllGarbage(Heap::kNoGCFlags, "gc extension");
+ }
return v8::Undefined();
}

=======================================
--- /trunk/src/flag-definitions.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/flag-definitions.h Wed Oct 31 03:02:10 2012
@@ -144,12 +144,16 @@
DEFINE_bool(harmony_proxies, false, "enable harmony proxies")
DEFINE_bool(harmony_collections, false,
"enable harmony collections (sets, maps, and weak maps)")
+DEFINE_bool(harmony_object_observe, false,
+ "enable harmony object observation (implies harmony
collections")
DEFINE_bool(harmony, false, "enable all harmony features (except typeof)")
DEFINE_implication(harmony, harmony_scoping)
DEFINE_implication(harmony, harmony_modules)
DEFINE_implication(harmony, harmony_proxies)
DEFINE_implication(harmony, harmony_collections)
+DEFINE_implication(harmony, harmony_object_observe)
DEFINE_implication(harmony_modules, harmony_scoping)
+DEFINE_implication(harmony_object_observe, harmony_collections)

// Flags for experimental implementation features.
DEFINE_bool(packed_arrays, true, "optimizes arrays that have no holes")
=======================================
--- /trunk/src/frames.cc Fri Aug 10 07:46:33 2012
+++ /trunk/src/frames.cc Wed Oct 31 03:02:10 2012
@@ -484,7 +484,7 @@


Code* EntryFrame::unchecked_code() const {
- return HEAP->raw_unchecked_js_entry_code();
+ return HEAP->js_entry_code();
}


@@ -507,7 +507,7 @@


Code* EntryConstructFrame::unchecked_code() const {
- return HEAP->raw_unchecked_js_construct_entry_code();
+ return HEAP->js_construct_entry_code();
}


=======================================
--- /trunk/src/heap-inl.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/heap-inl.h Wed Oct 31 03:02:10 2012
@@ -607,7 +607,7 @@
Object* obj = Object::cast(new_space_strings_[i]);
// TODO(yangguo): check that the object is indeed an external string.
ASSERT(heap_->InNewSpace(obj));
- ASSERT(obj != HEAP->raw_unchecked_the_hole_value());
+ ASSERT(obj != HEAP->the_hole_value());
if (obj->IsExternalAsciiString()) {
ExternalAsciiString* string = ExternalAsciiString::cast(obj);
ASSERT(String::IsAscii(string->GetChars(), string->length()));
@@ -617,7 +617,7 @@
Object* obj = Object::cast(old_space_strings_[i]);
// TODO(yangguo): check that the object is indeed an external string.
ASSERT(!heap_->InNewSpace(obj));
- ASSERT(obj != HEAP->raw_unchecked_the_hole_value());
+ ASSERT(obj != HEAP->the_hole_value());
if (obj->IsExternalAsciiString()) {
ExternalAsciiString* string = ExternalAsciiString::cast(obj);
ASSERT(String::IsAscii(string->GetChars(), string->length()));
=======================================
--- /trunk/src/heap.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/heap.cc Wed Oct 31 03:02:10 2012
@@ -211,6 +211,20 @@
cell_space_->CommittedMemory() +
lo_space_->Size();
}
+
+
+size_t Heap::CommittedPhysicalMemory() {
+ if (!HasBeenSetUp()) return 0;
+
+ return new_space_.CommittedPhysicalMemory() +
+ old_pointer_space_->CommittedPhysicalMemory() +
+ old_data_space_->CommittedPhysicalMemory() +
+ code_space_->CommittedPhysicalMemory() +
+ map_space_->CommittedPhysicalMemory() +
+ cell_space_->CommittedPhysicalMemory() +
+ lo_space_->CommittedPhysicalMemory();
+}
+

intptr_t Heap::CommittedMemoryExecutable() {
if (!HasBeenSetUp()) return 0;
@@ -406,6 +420,14 @@
gc_count_++;
unflattened_strings_length_ = 0;

+ bool should_enable_code_flushing = FLAG_flush_code;
+#ifdef ENABLE_DEBUGGER_SUPPORT
+ if (isolate_->debug()->IsLoaded() ||
isolate_->debug()->has_break_points()) {
+ should_enable_code_flushing = false;
+ }
+#endif
+
mark_compact_collector()->EnableCodeFlushing(should_enable_code_flushing);
+
#ifdef VERIFY_HEAP
if (FLAG_verify_heap) {
Verify();
@@ -1304,6 +1326,12 @@

scavenge_visitor.VisitPointer(reinterpret_cast<Object**>(value_address));
}
}
+
+ // Copy objects reachable from the code flushing candidates list.
+ MarkCompactCollector* collector = mark_compact_collector();
+ if (collector->is_code_flushing_enabled()) {
+
collector->code_flusher()->IteratePointersToFromSpace(&scavenge_visitor);
+ }

// Scavenge object reachable from the native contexts list directly.
scavenge_visitor.VisitPointer(BitCast<Object**>(&native_contexts_list_));
@@ -5519,6 +5547,7 @@
}
return symbol_table()->LookupSymbolIfExists(string, symbol);
}
+

void Heap::ZapFromSpace() {
NewSpacePageIterator it(new_space_.FromSpaceStart(),
@@ -7184,7 +7213,7 @@
void ExternalStringTable::CleanUp() {
int last = 0;
for (int i = 0; i < new_space_strings_.length(); ++i) {
- if (new_space_strings_[i] == heap_->raw_unchecked_the_hole_value()) {
+ if (new_space_strings_[i] == heap_->the_hole_value()) {
continue;
}
if (heap_->InNewSpace(new_space_strings_[i])) {
@@ -7196,7 +7225,7 @@
new_space_strings_.Rewind(last);
last = 0;
for (int i = 0; i < old_space_strings_.length(); ++i) {
- if (old_space_strings_[i] == heap_->raw_unchecked_the_hole_value()) {
+ if (old_space_strings_[i] == heap_->the_hole_value()) {
continue;
}
ASSERT(!heap_->InNewSpace(old_space_strings_[i]));
=======================================
--- /trunk/src/heap.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/heap.h Wed Oct 31 03:02:10 2012
@@ -487,6 +487,9 @@
// Returns the amount of executable memory currently committed for the
heap.
intptr_t CommittedMemoryExecutable();

+ // Returns the amount of phyical memory currently committed for the heap.
+ size_t CommittedPhysicalMemory();
+
// Returns the available bytes in space w/o growing.
// Heap doesn't guarantee that it can allocate an object that requires
// all available bytes. Check MaxHeapObjectSize() instead.
=======================================
--- /trunk/src/hydrogen-instructions.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/hydrogen-instructions.h Wed Oct 31 03:02:10 2012
@@ -3917,7 +3917,8 @@

inline bool ReceiverObjectNeedsWriteBarrier(HValue* object,
HValue* new_space_dominator) {
- return !object->IsAllocateObject() || (object != new_space_dominator);
+ return (!object->IsAllocateObject() && !object->IsFastLiteral()) ||
+ (object != new_space_dominator);
}


@@ -4805,6 +4806,7 @@
set_representation(Representation::Tagged());
SetFlag(kUseGVN);
SetGVNFlag(kDependsOnMaps);
+ SetGVNFlag(kChangesNewSpacePromotion);
}

virtual Representation RequiredInputRepresentation(int index) {
=======================================
--- /trunk/src/ia32/assembler-ia32.cc Wed Oct 10 10:07:22 2012
+++ /trunk/src/ia32/assembler-ia32.cc Wed Oct 31 03:02:10 2012
@@ -1501,7 +1501,7 @@

void Assembler::j(Condition cc, Label* L, Label::Distance distance) {
EnsureSpace ensure_space(this);
- ASSERT(0 <= cc && cc < 16);
+ ASSERT(0 <= cc && static_cast<int>(cc) < 16);
if (L->is_bound()) {
const int short_size = 2;
const int long_size = 6;
@@ -1533,7 +1533,7 @@

void Assembler::j(Condition cc, byte* entry, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
- ASSERT((0 <= cc) && (cc < 16));
+ ASSERT((0 <= cc) && (static_cast<int>(cc) < 16));
// 0000 1111 1000 tttn #32-bit disp.
EMIT(0x0F);
EMIT(0x80 | cc);
=======================================
--- /trunk/src/ia32/code-stubs-ia32.cc Mon Oct 15 04:51:39 2012
+++ /trunk/src/ia32/code-stubs-ia32.cc Wed Oct 31 03:02:10 2012
@@ -3593,7 +3593,7 @@
__ bind(&runtime);
__ pop(eax); // Remove saved parameter count.
__ mov(Operand(esp, 1 * kPointerSize), ecx); // Patch argument count.
- __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1);
+ __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1);
}


=======================================
--- /trunk/src/json-parser.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/json-parser.h Wed Oct 31 03:02:10 2012
@@ -154,6 +154,7 @@
inline Zone* zone() const { return zone_; }

static const int kInitialSpecialStringLength = 1024;
+ static const int kPretenureTreshold = 100 * 1024;


private:
@@ -161,6 +162,7 @@
int source_length_;
Handle<SeqAsciiString> seq_source_;

+ PretenureFlag pretenure_;
Isolate* isolate_;
Factory* factory_;
Handle<JSFunction> object_constructor_;
@@ -180,6 +182,7 @@
FlattenString(source);
source_ = source;
source_length_ = source_->length();
+ pretenure_ = (source_length_ >= kPretenureTreshold) ? TENURED :
NOT_TENURED;

// Optimized fast case where we only have ASCII characters.
if (seq_ascii) {
@@ -192,8 +195,10 @@
AdvanceSkipWhitespace();
Handle<Object> result = ParseJsonValue();
if (result.is_null() || c0_ != kEndOfString) {
- // Parse failed. Current character is the unexpected token.
+ // Some exception (for example stack overflow) is already pending.
+ if (isolate_->has_pending_exception()) return Handle<Object>::null();

+ // Parse failed. Current character is the unexpected token.
const char* message;
Factory* factory = this->factory();
Handle<JSArray> array;
@@ -244,6 +249,12 @@
// Parse any JSON value.
template <bool seq_ascii>
Handle<Object> JsonParser<seq_ascii>::ParseJsonValue() {
+ StackLimitCheck stack_check(isolate_);
+ if (stack_check.HasOverflowed()) {
+ isolate_->StackOverflow();
+ return Handle<Object>::null();
+ }
+
if (c0_ == '"') return ParseJsonString();
if ((c0_ >= '0' && c0_ <= '9') || c0_ == '-') return ParseJsonNumber();
if (c0_ == '{') return ParseJsonObject();
@@ -281,7 +292,7 @@
Handle<Object> JsonParser<seq_ascii>::ParseJsonObject() {
Handle<Object> prototype;
Handle<JSObject> json_object =
- factory()->NewJSObject(object_constructor());
+ factory()->NewJSObject(object_constructor(), pretenure_);
ASSERT_EQ(c0_, '{');

AdvanceSkipWhitespace();
@@ -293,45 +304,56 @@
Advance();

uint32_t index = 0;
- while (c0_ >= '0' && c0_ <= '9') {
- int d = c0_ - '0';
- if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
- index = (index * 10) + d;
- Advance();
- }
+ if (c0_ >= '0' && c0_ <= '9') {
+ // Maybe an array index, try to parse it.
+ if (c0_ == '0') {
+ // With a leading zero, the string has to be "0" only to be an
index.
+ Advance();
+ } else {
+ do {
+ int d = c0_ - '0';
+ if (index > 429496729U - ((d > 5) ? 1 : 0)) break;
+ index = (index * 10) + d;
+ Advance();
+ } while (c0_ >= '0' && c0_ <= '9');
+ }

- if (position_ != start_position + 1 && c0_ == '"') {
- AdvanceSkipWhitespace();
+ if (c0_ == '"') {
+ // Successfully parsed index, parse and store element.
+ AdvanceSkipWhitespace();

- if (c0_ != ':') return ReportUnexpectedCharacter();
- AdvanceSkipWhitespace();
- Handle<Object> value = ParseJsonValue();
- if (value.is_null()) return ReportUnexpectedCharacter();
+ if (c0_ != ':') return ReportUnexpectedCharacter();
+ AdvanceSkipWhitespace();
+ Handle<Object> value = ParseJsonValue();
+ if (value.is_null()) return ReportUnexpectedCharacter();

- JSObject::SetOwnElement(json_object, index, value, kNonStrictMode);
- } else {
- position_ = start_position;
+ JSObject::SetOwnElement(json_object, index, value,
kNonStrictMode);
+ continue;
+ }
+ // Not an index, fallback to the slow path.
+ }
+
+ position_ = start_position;
#ifdef DEBUG
- c0_ = '"';
+ c0_ = '"';
#endif

- Handle<String> key = ParseJsonSymbol();
- if (key.is_null() || c0_ != ':') return
ReportUnexpectedCharacter();
+ Handle<String> key = ParseJsonSymbol();
+ if (key.is_null() || c0_ != ':') return ReportUnexpectedCharacter();

- AdvanceSkipWhitespace();
- Handle<Object> value = ParseJsonValue();
- if (value.is_null()) return ReportUnexpectedCharacter();
+ AdvanceSkipWhitespace();
+ Handle<Object> value = ParseJsonValue();
+ if (value.is_null()) return ReportUnexpectedCharacter();

- if (key->Equals(isolate()->heap()->Proto_symbol())) {
- prototype = value;
+ if (key->Equals(isolate()->heap()->Proto_symbol())) {
+ prototype = value;
+ } else {
+ if (JSObject::TryTransitionToField(json_object, key)) {
+ int index = json_object->LastAddedFieldIndex();
+ json_object->FastPropertyAtPut(index, *value);
} else {
- if (JSObject::TryTransitionToField(json_object, key)) {
- int index = json_object->LastAddedFieldIndex();
- json_object->FastPropertyAtPut(index, *value);
- } else {
- JSObject::SetLocalPropertyIgnoreAttributes(
- json_object, key, value, NONE);
- }
+ JSObject::SetLocalPropertyIgnoreAttributes(
+ json_object, key, value, NONE);
}
}
} while (MatchSkipWhiteSpace(','));
@@ -365,11 +387,12 @@
AdvanceSkipWhitespace();
// Allocate a fixed array with all the elements.
Handle<FixedArray> fast_elements =
- factory()->NewFixedArray(elements.length());
+ factory()->NewFixedArray(elements.length(), pretenure_);
for (int i = 0, n = elements.length(); i < n; i++) {
fast_elements->set(i, *elements[i]);
}
- return factory()->NewJSArrayWithElements(fast_elements);
+ return factory()->NewJSArrayWithElements(
+ fast_elements, FAST_ELEMENTS, pretenure_);
}


@@ -436,7 +459,7 @@
buffer.Dispose();
}
SkipWhitespace();
- return factory()->NewNumber(number);
+ return factory()->NewNumber(number, pretenure_);
}


@@ -454,16 +477,22 @@
}

template <typename StringType>
-inline Handle<StringType> NewRawString(Factory* factory, int length);
+inline Handle<StringType> NewRawString(Factory* factory,
+ int length,
+ PretenureFlag pretenure);

template <>
-inline Handle<SeqTwoByteString> NewRawString(Factory* factory, int length)
{
- return factory->NewRawTwoByteString(length, NOT_TENURED);
+inline Handle<SeqTwoByteString> NewRawString(Factory* factory,
+ int length,
+ PretenureFlag pretenure) {
+ return factory->NewRawTwoByteString(length, pretenure);
}

template <>
-inline Handle<SeqAsciiString> NewRawString(Factory* factory, int length) {
- return factory->NewRawAsciiString(length, NOT_TENURED);
+inline Handle<SeqAsciiString> NewRawString(Factory* factory,
+ int length,
+ PretenureFlag pretenure) {
+ return factory->NewRawAsciiString(length, pretenure);
}


@@ -477,7 +506,8 @@
int count = end - start;
int max_length = count + source_length_ - position_;
int length = Min(max_length, Max(kInitialSpecialStringLength, 2 *
count));
- Handle<StringType> seq_str = NewRawString<StringType>(factory(), length);
+ Handle<StringType> seq_str =
+ NewRawString<StringType>(factory(), length, pretenure_);
// Copy prefix into seq_str.
SinkChar* dest = seq_str->GetChars();
String::WriteToFlat(*prefix, dest, start, end);
@@ -617,11 +647,11 @@
uint32_t count = 1;
while (true) {
Object* element = symbol_table->KeyAt(entry);
- if (element == isolate()->heap()->raw_unchecked_undefined_value()) {
+ if (element == isolate()->heap()->undefined_value()) {
// Lookup failure.
break;
}
- if (element != isolate()->heap()->raw_unchecked_the_hole_value() &&
+ if (element != isolate()->heap()->the_hole_value() &&
String::cast(element)->IsAsciiEqualTo(string_vector)) {
// Lookup success, update the current position.
position_ = position;
@@ -656,10 +686,10 @@
Handle<String> result;
if (seq_ascii && is_symbol) {
result = factory()->LookupAsciiSymbol(seq_source_,
- beg_pos,
- length);
+ beg_pos,
+ length);
} else {
- result = factory()->NewRawAsciiString(length);
+ result = factory()->NewRawAsciiString(length, pretenure_);
char* dest = SeqAsciiString::cast(*result)->GetChars();
String::WriteToFlat(*source_, dest, beg_pos, position_);
}
=======================================
--- /trunk/src/json.js Thu Sep 6 06:50:42 2012
+++ /trunk/src/json.js Wed Oct 31 03:02:10 2012
@@ -307,10 +307,12 @@

function JSONStringify(value, replacer, space) {
if (%_ArgumentsLength() == 1) {
+ var result = %BasicJSONStringify(value);
+ if (result != 0) return result;
var builder = new InternalArray();
BasicJSONSerialize('', value, new InternalArray(), builder);
if (builder.length == 0) return;
- var result = %_FastAsciiArrayJoin(builder, "");
+ result = %_FastAsciiArrayJoin(builder, "");
if (!IS_UNDEFINED(result)) return result;
return %StringBuilderConcat(builder, builder.length, "");
}
=======================================
--- /trunk/src/mark-compact.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/mark-compact.cc Wed Oct 31 03:02:10 2012
@@ -924,6 +924,47 @@

shared_function_info_candidates_head_ = NULL;
}
+
+
+void CodeFlusher::EvictCandidate(JSFunction* function) {
+ ASSERT(!function->next_function_link()->IsUndefined());
+ Object* undefined = isolate_->heap()->undefined_value();
+
+ JSFunction* candidate = jsfunction_candidates_head_;
+ JSFunction* next_candidate;
+ if (candidate == function) {
+ next_candidate = GetNextCandidate(function);
+ jsfunction_candidates_head_ = next_candidate;
+ ClearNextCandidate(function, undefined);
+ } else {
+ while (candidate != NULL) {
+ next_candidate = GetNextCandidate(candidate);
+
+ if (next_candidate == function) {
+ next_candidate = GetNextCandidate(function);
+ SetNextCandidate(candidate, next_candidate);
+ ClearNextCandidate(function, undefined);
+ }
+
+ candidate = next_candidate;
+ }
+ }
+}
+
+
+void CodeFlusher::IteratePointersToFromSpace(ObjectVisitor* v) {
+ Heap* heap = isolate_->heap();
+
+ JSFunction** slot = &jsfunction_candidates_head_;
+ JSFunction* candidate = jsfunction_candidates_head_;
+ while (candidate != NULL) {
+ if (heap->InFromSpace(candidate)) {
+ v->VisitPointer(reinterpret_cast<Object**>(slot));
+ }
+ candidate = GetNextCandidate(*slot);
+ slot = GetNextCandidateSlot(*slot);
+ }
+}


MarkCompactCollector::~MarkCompactCollector() {
@@ -1430,21 +1471,8 @@
void MarkCompactCollector::PrepareForCodeFlushing() {
ASSERT(heap() == Isolate::Current()->heap());

- // TODO(1609) Currently incremental marker does not support code
flushing.
- if (!FLAG_flush_code || was_marked_incrementally_) {
- EnableCodeFlushing(false);
- return;
- }
-
-#ifdef ENABLE_DEBUGGER_SUPPORT
- if (heap()->isolate()->debug()->IsLoaded() ||
- heap()->isolate()->debug()->has_break_points()) {
- EnableCodeFlushing(false);
- return;
- }
-#endif
-
- EnableCodeFlushing(true);
+ // If code flushing is disabled, there is no need to prepare for it.
+ if (!is_code_flushing_enabled()) return;

// Ensure that empty descriptor array is marked. Method
MarkDescriptorArray
// relies on it being marked before any other descriptor array.
@@ -2005,9 +2033,6 @@
// Flush code from collected candidates.
if (is_code_flushing_enabled()) {
code_flusher_->ProcessCandidates();
- // TODO(1609) Currently incremental marker does not support code
flushing,
- // we need to disable it before incremental marking steps for next
cycle.
- EnableCodeFlushing(false);
}

if (!FLAG_watch_ic_patching) {
=======================================
--- /trunk/src/mark-compact.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/mark-compact.h Wed Oct 31 03:02:10 2012
@@ -420,26 +420,38 @@
shared_function_info_candidates_head_(NULL) {}

void AddCandidate(SharedFunctionInfo* shared_info) {
- SetNextCandidate(shared_info, shared_function_info_candidates_head_);
- shared_function_info_candidates_head_ = shared_info;
+ if (GetNextCandidate(shared_info) == NULL) {
+ SetNextCandidate(shared_info, shared_function_info_candidates_head_);
+ shared_function_info_candidates_head_ = shared_info;
+ }
}

void AddCandidate(JSFunction* function) {
ASSERT(function->code() == function->shared()->code());
- ASSERT(function->next_function_link()->IsUndefined());
- SetNextCandidate(function, jsfunction_candidates_head_);
- jsfunction_candidates_head_ = function;
+ if (GetNextCandidate(function)->IsUndefined()) {
+ SetNextCandidate(function, jsfunction_candidates_head_);
+ jsfunction_candidates_head_ = function;
+ }
}
+
+ void EvictCandidate(JSFunction* function);

void ProcessCandidates() {
ProcessSharedFunctionInfoCandidates();
ProcessJSFunctionCandidates();
}
+
+ void IteratePointersToFromSpace(ObjectVisitor* v);

private:
void ProcessJSFunctionCandidates();
void ProcessSharedFunctionInfoCandidates();

+ static JSFunction** GetNextCandidateSlot(JSFunction* candidate) {
+ return reinterpret_cast<JSFunction**>(
+ HeapObject::RawField(candidate,
JSFunction::kNextFunctionLinkOffset));
+ }
+
static JSFunction* GetNextCandidate(JSFunction* candidate) {
Object* next_candidate = candidate->next_function_link();
return reinterpret_cast<JSFunction*>(next_candidate);
=======================================
--- /trunk/src/messages.js Thu Oct 11 08:57:38 2012
+++ /trunk/src/messages.js Wed Oct 31 03:02:10 2012
@@ -203,6 +203,10 @@
"proxy_repeated_prop_name", ["Trap '", "%1", "' returned
repeated property name '", "%2", "'"],
"invalid_weakmap_key", ["Invalid value used as weak map
key"],
"not_date_object", ["this is not a Date object."],
+ "observe_non_object", ["Object.", "%0", "
cannot ", "%0", " non-object"],
+ "observe_non_function", ["Object.", "%0", " cannot deliver
to non-function"],
+ "observe_callback_frozen", ["Object.observe cannot deliver to a
frozen function object"],
+ "observe_type_non_string", ["Object.notify provided
changeRecord with non-string 'type' property"],
// RangeError
"invalid_array_length", ["Invalid array length"],
"stack_overflow", ["Maximum call stack size exceeded"],
=======================================
--- /trunk/src/mips/lithium-mips.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/mips/lithium-mips.cc Wed Oct 31 03:02:10 2012
@@ -702,15 +702,13 @@
right = UseRegisterAtStart(right_value);
}

+ // Shift operations can only deoptimize if we do a logical shift
+ // by 0 and the result cannot be truncated to int32.
bool does_deopt = false;
-
- if (FLAG_opt_safe_uint32_operations) {
- does_deopt = !instr->CheckFlag(HInstruction::kUint32);
- } else {
- // Shift operations can only deoptimize if we do a logical shift
- // by 0 and the result cannot be truncated to int32.
- bool may_deopt = (op == Token::SHR && constant_value == 0);
- if (may_deopt) {
+ if (op == Token::SHR && constant_value == 0) {
+ if (FLAG_opt_safe_uint32_operations) {
+ does_deopt = !instr->CheckFlag(HInstruction::kUint32);
+ } else {
for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) {
does_deopt = true;
=======================================
--- /trunk/src/objects-debug.cc Mon Oct 15 04:51:39 2012
+++ /trunk/src/objects-debug.cc Wed Oct 31 03:02:10 2012
@@ -499,7 +499,8 @@
VerifyObjectField(kPrototypeOrInitialMapOffset);
VerifyObjectField(kNextFunctionLinkOffset);
CHECK(code()->IsCode());
- CHECK(next_function_link()->IsUndefined() ||
+ CHECK(next_function_link() == NULL ||
+ next_function_link()->IsUndefined() ||
next_function_link()->IsJSFunction());
}

=======================================
--- /trunk/src/objects-inl.h Mon Oct 22 06:09:53 2012
+++ /trunk/src/objects-inl.h Wed Oct 31 03:02:10 2012
@@ -660,8 +660,8 @@


bool Object::IsSymbolTable() {
- return IsHashTable() && this ==
- HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
+ return IsHashTable() &&
+ this ==
HeapObject::cast(this)->GetHeap()->raw_unchecked_symbol_table();
}


@@ -1850,7 +1850,7 @@
void FixedArray::NoIncrementalWriteBarrierSet(FixedArray* array,
int index,
Object* value) {
- ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
+ ASSERT(array->map() != HEAP->fixed_cow_array_map());
ASSERT(index >= 0 && index < array->length());
int offset = kHeaderSize + index * kPointerSize;
WRITE_FIELD(array, offset, value);
@@ -1864,7 +1864,7 @@
void FixedArray::NoWriteBarrierSet(FixedArray* array,
int index,
Object* value) {
- ASSERT(array->map() != HEAP->raw_unchecked_fixed_cow_array_map());
+ ASSERT(array->map() != HEAP->fixed_cow_array_map());
ASSERT(index >= 0 && index < array->length());
ASSERT(!HEAP->InNewSpace(value));
WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
@@ -2290,7 +2290,8 @@
// EnsureCapacity will guarantee the hash table is never full.
while (true) {
Object* element = KeyAt(entry);
- // Empty entry.
+ // Empty entry. Uses raw unchecked accessors because it is called by
the
+ // symbol table during bootstrapping.
if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
Shape::IsMatch(key, element)) return entry;
@@ -5252,8 +5253,8 @@
// Please note this function is used during marking:
// - MarkCompactCollector::MarkUnmarkedObject
// - IncrementalMarking::Step
- ASSERT(!heap->InNewSpace(heap->raw_unchecked_empty_fixed_array()));
- WRITE_FIELD(this, kCodeCacheOffset,
heap->raw_unchecked_empty_fixed_array());
+ ASSERT(!heap->InNewSpace(heap->empty_fixed_array()));
+ WRITE_FIELD(this, kCodeCacheOffset, heap->empty_fixed_array());
}


@@ -5347,7 +5348,7 @@


Object* TypeFeedbackCells::RawUninitializedSentinel(Heap* heap) {
- return heap->raw_unchecked_the_hole_value();
+ return heap->the_hole_value();
}


=======================================
--- /trunk/src/objects.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/objects.cc Wed Oct 31 03:02:10 2012
@@ -8105,7 +8105,7 @@
// constructor is called. The countdown will continue and (possibly after
// several more GCs) CompleteInobjectSlackTracking will eventually be
called.
Heap* heap = map->GetHeap();
- set_initial_map(heap->raw_unchecked_undefined_value());
+ set_initial_map(heap->undefined_value());
Builtins* builtins = heap->isolate()->builtins();
ASSERT_EQ(builtins->builtin(Builtins::kJSConstructStubCountdown),
*RawField(this, kConstructStubOffset));
=======================================
--- /trunk/src/platform-cygwin.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/platform-cygwin.cc Wed Oct 31 03:02:10 2012
@@ -357,6 +357,12 @@
}
return true;
}
+
+
+bool VirtualMemory::HasLazyCommits() {
+ // TODO(alph): implement for the platform.
+ return false;
+}


class Thread::PlatformData : public Malloced {
=======================================
--- /trunk/src/platform-freebsd.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/platform-freebsd.cc Wed Oct 31 03:02:10 2012
@@ -454,6 +454,12 @@
bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
return munmap(base, size) == 0;
}
+
+
+bool VirtualMemory::HasLazyCommits() {
+ // TODO(alph): implement for the platform.
+ return false;
+}


class Thread::PlatformData : public Malloced {
=======================================
--- /trunk/src/platform-linux.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/platform-linux.cc Wed Oct 31 03:02:10 2012
@@ -720,6 +720,11 @@
bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
return munmap(base, size) == 0;
}
+
+
+bool VirtualMemory::HasLazyCommits() {
+ return true;
+}


class Thread::PlatformData : public Malloced {
=======================================
--- /trunk/src/platform-macos.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/platform-macos.cc Wed Oct 31 03:02:10 2012
@@ -469,6 +469,11 @@
bool VirtualMemory::ReleaseRegion(void* address, size_t size) {
return munmap(address, size) == 0;
}
+
+
+bool VirtualMemory::HasLazyCommits() {
+ return false;
+}


class Thread::PlatformData : public Malloced {
=======================================
--- /trunk/src/platform-nullos.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/platform-nullos.cc Wed Oct 31 03:02:10 2012
@@ -338,6 +338,12 @@
UNIMPLEMENTED();
return false;
}
+
+
+bool VirtualMemory::HasLazyCommits() {
+ // TODO(alph): implement for the platform.
+ return false;
+}


class Thread::PlatformData : public Malloced {
=======================================
--- /trunk/src/platform-openbsd.cc Mon Oct 22 06:09:53 2012
+++ /trunk/src/platform-openbsd.cc Wed Oct 31 03:02:10 2012
@@ -502,6 +502,12 @@
bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
return munmap(base, size) == 0;
}
+
+
+bool VirtualMemory::HasLazyCommits() {
+ // TODO(alph): implement for the platform.
+ return false;
+}


class Thread::PlatformData : public Malloced {
=======================================
***Additional files exist in this changeset.***
Reply all
Reply to author
Forward
0 new messages