Upgrade V8 to 3.8.5
authorRyan Dahl <ry@tinyclouds.org>
Fri, 6 Jan 2012 21:03:06 +0000 (13:03 -0800)
committerRyan Dahl <ry@tinyclouds.org>
Fri, 6 Jan 2012 21:03:06 +0000 (13:03 -0800)
47 files changed:
deps/v8/ChangeLog
deps/v8/LICENSE
deps/v8/build/common.gypi
deps/v8/build/standalone.gypi
deps/v8/include/v8.h
deps/v8/src/api.cc
deps/v8/src/arm/builtins-arm.cc
deps/v8/src/arm/code-stubs-arm.cc
deps/v8/src/checks.h
deps/v8/src/collection.js
deps/v8/src/d8-posix.cc
deps/v8/src/d8.gyp
deps/v8/src/flag-definitions.h
deps/v8/src/heap.cc
deps/v8/src/heap.h
deps/v8/src/ia32/builtins-ia32.cc
deps/v8/src/ia32/code-stubs-ia32.cc
deps/v8/src/isolate.h
deps/v8/src/macros.py
deps/v8/src/math.js
deps/v8/src/mips/builtins-mips.cc
deps/v8/src/mips/code-stubs-mips.cc
deps/v8/src/mips/lithium-codegen-mips.cc
deps/v8/src/mips/lithium-codegen-mips.h
deps/v8/src/mips/lithium-gap-resolver-mips.cc
deps/v8/src/mips/macro-assembler-mips.h
deps/v8/src/objects-inl.h
deps/v8/src/objects.cc
deps/v8/src/objects.h
deps/v8/src/platform-openbsd.cc
deps/v8/src/platform-posix.cc
deps/v8/src/profile-generator.cc
deps/v8/src/runtime.cc
deps/v8/src/spaces.cc
deps/v8/src/store-buffer.cc
deps/v8/src/store-buffer.h
deps/v8/src/v8.cc
deps/v8/src/v8.h
deps/v8/src/version.cc
deps/v8/src/x64/builtins-x64.cc
deps/v8/src/x64/code-stubs-x64.cc
deps/v8/test/cctest/test-api.cc
deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js
deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js
deps/v8/test/mjsunit/harmony/collections.js
deps/v8/tools/grokdump.py
deps/v8/tools/gyp/v8.gyp

index 5eb4b26..059b692 100644 (file)
@@ -1,3 +1,29 @@
+2012-01-05: Version 3.8.5
+
+        Fix broken test that assumes that no GC can clear the regexp cache (GC
+        can happen at any time due to Crankshaft).
+
+        Fix handling of bogus receivers for Harmony collections. (issue 1884)
+
+        Add netbsd support to gyp build.
+
+        Determine page size at runtime on posix platforms.
+
+        Ensure that store buffer filtering hash sets are cleared after
+        StoreBuffer::Filter.
+
+        Randomize the seed used for string hashing.  This helps guard against
+        CPU-eating DOS attacks against node.js servers.  Based on code from
+        Bert Belder.  This version only solves the issue for those that compile
+        V8 themselves or those that do not use snapshots.  A snapshot-based
+        precompiled V8 will still have predictable string hash codes.
+
+        Implement callback when script finishes running in V8 API.
+
+        Improve performance of Math.min and Math.max for the case of two
+        arguments. (issue 1325)
+
+
 2012-01-02: Version 3.8.4
 
         Performance improvements for large Smi-only arrays.
index e435050..2e516ba 100644 (file)
@@ -14,7 +14,9 @@ are:
 
   - Strongtalk assembler, the basis of the files assembler-arm-inl.h,
     assembler-arm.cc, assembler-arm.h, assembler-ia32-inl.h,
-    assembler-ia32.cc, assembler-ia32.h, assembler.cc and assembler.h.
+    assembler-ia32.cc, assembler-ia32.h, assembler-x64-inl.h,
+    assembler-x64.cc, assembler-x64.h, assembler-mips-inl.h,
+    assembler-mips.cc, assembler-mips.h, assembler.cc and assembler.h.
     This code is copyrighted by Sun Microsystems Inc. and released
     under a 3-clause BSD license.
 
@@ -24,7 +26,7 @@ are:
 These libraries have their own licenses; we recommend you read them,
 as their terms may differ from the terms below.
 
-Copyright 2006-2011, the V8 project authors. All rights reserved.
+Copyright 2006-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:
index 9129d01..7aab913 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011 the V8 project authors. All rights reserved.
+# 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:
           },
         },
       }],
-      ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
+      ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+         or OS=="netbsd"', {
         'conditions': [
           [ 'target_arch=="ia32"', {
             'cflags': [ '-m32' ],
           ['OS=="freebsd" or OS=="openbsd"', {
             'cflags': [ '-I/usr/local/include' ],
           }],
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+          ['OS=="netbsd"', {
+            'cflags': [ '-I/usr/pkg/include' ],
+          }],
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
             'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter',
                         '-Wnon-virtual-dtor' ],
           }],
       },
       'Release': {
         'conditions': [
-          ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
+          ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
             'cflags!': [
               '-O2',
               '-Os',
           ['OS=="freebsd" or OS=="openbsd"', {
             'cflags': [ '-I/usr/local/include' ],
           }],
+          ['OS=="netbsd"', {
+            'cflags': [ '-I/usr/pkg/include' ],
+          }],
           ['OS=="mac"', {
             'xcode_settings': {
               'GCC_OPTIMIZATION_LEVEL': '3',  # -O3
index 4297f5c..86f6d46 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011 the V8 project authors. All rights reserved.
+# 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:
       'variables': {
         'variables': {
           'conditions': [
-            [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
-              # This handles the Linux platforms we generally deal with. Anything
-              # else gets passed through, which probably won't work very well; such
-              # hosts should pass an explicit target_arch to gyp.
+            ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
+              # This handles the Linux platforms we generally deal with.
+              # Anything else gets passed through, which probably won't work
+              # very well; such hosts should pass an explicit target_arch
+              # to gyp.
               'host_arch%':
-                '<!(uname -m | sed -e "s/i.86/ia32/;s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/;s/mips.*/mips/")',
-            }, {  # OS!="linux" and OS!="freebsd" and OS!="openbsd"
+                '<!(uname -m | sed -e "s/i.86/ia32/;\
+                  s/x86_64/x64/;s/amd64/x64/;s/arm.*/arm/;s/mips.*/mips/")',
+            }, {
+              # OS!="linux" and OS!="freebsd" and OS!="openbsd" and OS!="netbsd"
               'host_arch%': 'ia32',
             }],
           ],
@@ -78,7 +81,8 @@
     },
   },
   'conditions': [
-    [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', {
+    ['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
+       or OS=="netbsd"', {
       'target_defaults': {
         'cflags': [ '-Wall', '<(werror)', '-W', '-Wno-unused-parameter',
                     '-Wnon-virtual-dtor', '-pthread', '-fno-rtti',
           }],
         ],
       },
-    }],  # 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"'
+    }],
+    # 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"
+    #  or OS=="netbsd"'
     ['OS=="win"', {
       'target_defaults': {
         'defines': [
index 53bad21..1819943 100644 (file)
@@ -2635,6 +2635,9 @@ typedef void (*MemoryAllocationCallback)(ObjectSpace space,
                                          AllocationAction action,
                                          int size);
 
+// --- Leave Script Callback ---
+typedef void (*CallCompletedCallback)();
+
 // --- Failed Access Check Callback ---
 typedef void (*FailedAccessCheckCallback)(Local<Object> target,
                                           AccessType type,
@@ -3033,12 +3036,25 @@ class V8EXPORT V8 {
                                           AllocationAction action);
 
   /**
-   * This function removes callback which was installed by
-   * AddMemoryAllocationCallback function.
+   * Removes callback that was installed by AddMemoryAllocationCallback.
    */
   static void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback);
 
   /**
+   * Adds a callback to notify the host application when a script finished
+   * running.  If a script re-enters the runtime during executing, the
+   * CallCompletedCallback is only invoked when the outer-most script
+   * execution ends.  Executing scripts inside the callback do not trigger
+   * further callbacks.
+   */
+  static void AddCallCompletedCallback(CallCompletedCallback callback);
+
+  /**
+   * Removes callback that was installed by AddCallCompletedCallback.
+   */
+  static void RemoveCallCompletedCallback(CallCompletedCallback callback);
+
+  /**
    * Allows the host application to group objects together. If one
    * object in the group is alive, all objects in the group are alive.
    * After each garbage collection, object groups are removed. It is
index 7eaadbb..3bd5a31 100644 (file)
@@ -78,7 +78,7 @@ namespace v8 {
   bool has_pending_exception = false
 
 
-#define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
+#define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback)           \
   do {                                                                         \
     i::HandleScopeImplementer* handle_scope_implementer =                      \
         (isolate)->handle_scope_implementer();                                 \
@@ -91,11 +91,22 @@ namespace v8 {
       }                                                                        \
       bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
       (isolate)->OptionalRescheduleException(call_depth_is_zero);              \
+      do_callback                                                              \
       return value;                                                            \
     }                                                                          \
+    do_callback                                                                \
   } while (false)
 
 
+#define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value)                    \
+  EXCEPTION_BAILOUT_CHECK_GENERIC(                                             \
+      isolate, value, i::V8::FireCallCompletedCallback(isolate);)
+
+
+#define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
+  EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
+
+
 #define API_ENTRY_CHECK(isolate, msg)                                          \
   do {                                                                         \
     if (v8::Locker::IsActive()) {                                              \
@@ -1568,7 +1579,7 @@ Local<Value> Script::Run() {
         isolate->context()->global_proxy(), isolate);
     i::Handle<i::Object> result =
         i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
+    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
     raw_result = *result;
   }
   i::Handle<i::Object> result(raw_result, isolate);
@@ -3494,7 +3505,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv,
   EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> returned =
       i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
+  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
   return Utils::ToLocal(scope.CloseAndEscape(returned));
 }
 
@@ -3515,7 +3526,7 @@ Local<v8::Value> Object::CallAsConstructor(int argc,
     EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> returned =
         i::Execution::New(fun, argc, args, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
+    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
     return Utils::ToLocal(scope.CloseAndEscape(
         i::Handle<i::JSObject>::cast(returned)));
   }
@@ -3528,7 +3539,7 @@ Local<v8::Value> Object::CallAsConstructor(int argc,
     EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> returned =
         i::Execution::Call(fun, obj, argc, args, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
+    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
     ASSERT(!delegate->IsUndefined());
     return Utils::ToLocal(scope.CloseAndEscape(returned));
   }
@@ -3555,7 +3566,7 @@ Local<v8::Object> Function::NewInstance(int argc,
   EXCEPTION_PREAMBLE(isolate);
   i::Handle<i::Object> returned =
       i::Execution::New(function, argc, args, &has_pending_exception);
-  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
+  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
   return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
 }
 
@@ -3576,7 +3587,7 @@ Local<v8::Value> Function::Call(v8::Handle<v8::Object> recv, int argc,
     EXCEPTION_PREAMBLE(isolate);
     i::Handle<i::Object> returned =
         i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception);
-    EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
+    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
     raw_result = *returned;
   }
   i::Handle<i::Object> result(raw_result);
@@ -5045,6 +5056,21 @@ void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
 }
 
 
+void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
+  if (callback == NULL) return;
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::AddLeaveScriptCallback()")) return;
+  i::V8::AddCallCompletedCallback(callback);
+}
+
+
+void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) {
+  i::Isolate* isolate = i::Isolate::Current();
+  if (IsDeadCheck(isolate, "v8::V8::RemoveLeaveScriptCallback()")) return;
+  i::V8::RemoveCallCompletedCallback(callback);
+}
+
+
 void V8::PauseProfiler() {
   i::Isolate* isolate = i::Isolate::Current();
   isolate->logger()->PauseProfiler();
index c452821..69ef187 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -316,7 +316,8 @@ static void AllocateJSArray(MacroAssembler* masm,
 static void ArrayNativeCode(MacroAssembler* masm,
                             Label* call_generic_code) {
   Counters* counters = masm->isolate()->counters();
-  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array;
+  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
+      has_non_smi_element;
 
   // Check for array construction with zero arguments or one.
   __ cmp(r0, Operand(0, RelocInfo::NONE));
@@ -415,7 +416,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ bind(&loop);
   __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex));
   if (FLAG_smi_only_arrays) {
-    __ JumpIfNotSmi(r2, call_generic_code);
+    __ JumpIfNotSmi(r2, &has_non_smi_element);
   }
   __ str(r2, MemOperand(r5, -kPointerSize, PreIndex));
   __ bind(&entry);
@@ -431,6 +432,10 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ add(sp, sp, Operand(kPointerSize));
   __ mov(r0, r3);
   __ Jump(lr);
+
+  __ bind(&has_non_smi_element);
+  __ UndoAllocationInNewSpace(r3, r4);
+  __ b(call_generic_code);
 }
 
 
index 209c48e..e95e2cf 100644 (file)
@@ -5730,7 +5730,11 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
                                     Register hash,
                                     Register character) {
   // hash = character + (character << 10);
-  __ add(hash, character, Operand(character, LSL, 10));
+  __ LoadRoot(hash, Heap::kStringHashSeedRootIndex);
+  // Untag smi seed and add the character.
+  __ add(hash, character, Operand(hash, LSR, kSmiTagSize));
+  // hash += hash << 10;
+  __ add(hash, hash, Operand(hash, LSL, 10));
   // hash ^= hash >> 6;
   __ eor(hash, hash, Operand(hash, LSR, 6));
 }
index 8608b0e..d93d451 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -265,16 +265,16 @@ extern bool FLAG_enable_slow_asserts;
 // The ASSERT macro is equivalent to CHECK except that it only
 // generates code in debug builds.
 #ifdef DEBUG
-#define ASSERT_RESULT(expr)  CHECK(expr)
-#define ASSERT(condition)    CHECK(condition)
-#define ASSERT_EQ(v1, v2)    CHECK_EQ(v1, v2)
-#define ASSERT_NE(v1, v2)    CHECK_NE(v1, v2)
-#define ASSERT_GE(v1, v2)    CHECK_GE(v1, v2)
-#define ASSERT_LT(v1, v2)    CHECK_LT(v1, v2)
-#define ASSERT_LE(v1, v2)    CHECK_LE(v1, v2)
-#define SLOW_ASSERT(condition) if (FLAG_enable_slow_asserts) CHECK(condition)
+#define ASSERT_RESULT(expr)    CHECK(expr)
+#define ASSERT(condition)      CHECK(condition)
+#define ASSERT_EQ(v1, v2)      CHECK_EQ(v1, v2)
+#define ASSERT_NE(v1, v2)      CHECK_NE(v1, v2)
+#define ASSERT_GE(v1, v2)      CHECK_GE(v1, v2)
+#define ASSERT_LT(v1, v2)      CHECK_LT(v1, v2)
+#define ASSERT_LE(v1, v2)      CHECK_LE(v1, v2)
+#define SLOW_ASSERT(condition) CHECK(!FLAG_enable_slow_asserts || (condition))
 #else
-#define ASSERT_RESULT(expr)     (expr)
+#define ASSERT_RESULT(expr)    (expr)
 #define ASSERT(condition)      ((void) 0)
 #define ASSERT_EQ(v1, v2)      ((void) 0)
 #define ASSERT_NE(v1, v2)      ((void) 0)
index d116126..fcf4d38 100644 (file)
@@ -47,6 +47,10 @@ function SetConstructor() {
 
 
 function SetAdd(key) {
+  if (!IS_SET(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Set.prototype.add', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -55,6 +59,10 @@ function SetAdd(key) {
 
 
 function SetHas(key) {
+  if (!IS_SET(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Set.prototype.has', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -63,6 +71,10 @@ function SetHas(key) {
 
 
 function SetDelete(key) {
+  if (!IS_SET(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Set.prototype.delete', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -80,6 +92,10 @@ function MapConstructor() {
 
 
 function MapGet(key) {
+  if (!IS_MAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Map.prototype.get', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -88,6 +104,10 @@ function MapGet(key) {
 
 
 function MapSet(key, value) {
+  if (!IS_MAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Map.prototype.set', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -96,6 +116,10 @@ function MapSet(key, value) {
 
 
 function MapHas(key) {
+  if (!IS_MAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Map.prototype.has', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -104,6 +128,10 @@ function MapHas(key) {
 
 
 function MapDelete(key) {
+  if (!IS_MAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['Map.prototype.delete', this]);
+  }
   if (IS_UNDEFINED(key)) {
     key = undefined_sentinel;
   }
@@ -126,6 +154,10 @@ function WeakMapConstructor() {
 
 
 function WeakMapGet(key) {
+  if (!IS_WEAKMAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['WeakMap.prototype.get', this]);
+  }
   if (!IS_SPEC_OBJECT(key)) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
@@ -134,6 +166,10 @@ function WeakMapGet(key) {
 
 
 function WeakMapSet(key, value) {
+  if (!IS_WEAKMAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['WeakMap.prototype.set', this]);
+  }
   if (!IS_SPEC_OBJECT(key)) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
@@ -142,6 +178,10 @@ function WeakMapSet(key, value) {
 
 
 function WeakMapHas(key) {
+  if (!IS_WEAKMAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['WeakMap.prototype.has', this]);
+  }
   if (!IS_SPEC_OBJECT(key)) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
@@ -150,6 +190,10 @@ function WeakMapHas(key) {
 
 
 function WeakMapDelete(key) {
+  if (!IS_WEAKMAP(this)) {
+    throw MakeTypeError('incompatible_method_receiver',
+                        ['WeakMap.prototype.delete', this]);
+  }
   if (!IS_SPEC_OBJECT(key)) {
     throw %MakeTypeError('invalid_weakmap_key', [this, key]);
   }
index 289c3b0..8a278e4 100644 (file)
@@ -366,7 +366,8 @@ static Handle<Value> GetStdout(int child_fd,
 // We're disabling usage of waitid in Mac OS X because it doens't work for us:
 // a parent process hangs on waiting while a child process is already a zombie.
 // See http://code.google.com/p/v8/issues/detail?id=401.
-#if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__)
+#if defined(WNOWAIT) && !defined(ANDROID) && !defined(__APPLE__) \
+    && !defined(__NetBSD__)
 #if !defined(__FreeBSD__)
 #define HAS_WAITID 1
 #endif
index bdc23a2..a096af3 100644 (file)
@@ -64,8 +64,8 @@
               'libraries': [ '-lreadline', ],
               'sources': [ 'd8-readline.cc' ],
             }],
-            [ '(OS=="linux" or OS=="mac" or OS=="freebsd" \
-              or OS=="openbsd" or OS=="solaris" or OS=="android")', {
+            ['(OS=="linux" or OS=="mac" or OS=="freebsd" or OS=="netbsd" \
+               or OS=="openbsd" or OS=="solaris" or OS=="android")', {
               'sources': [ 'd8-posix.cc', ]
             }],
             [ 'OS=="win"', {
index 1ae1b17..07060dc 100644 (file)
@@ -349,6 +349,14 @@ DEFINE_bool(trace_exception, false,
             "print stack trace when throwing exceptions")
 DEFINE_bool(preallocate_message_memory, false,
             "preallocate some memory to build stack traces.")
+DEFINE_bool(randomize_string_hashes,
+            true,
+            "randomize string hashes to avoid predictable hash collisions "
+            "(with snapshots this option cannot override the baked-in seed)")
+DEFINE_int(string_hash_seed,
+           0,
+           "Fixed seed to use to string hashing (0 means random)"
+           "(with snapshots this option cannot override the baked-in seed)")
 
 // v8.cc
 DEFINE_bool(preemption, false,
index 5984834..31cd889 100644 (file)
@@ -2318,6 +2318,10 @@ bool Heap::CreateInitialObjects() {
   }
   set_infinity_value(HeapNumber::cast(obj));
 
+  // The hole has not been created yet, but we want to put something
+  // predictable in the gaps in the symbol table, so lets make that Smi zero.
+  set_the_hole_value(reinterpret_cast<Oddball*>(Smi::FromInt(0)));
+
   // Allocate initial symbol table.
   { MaybeObject* maybe_obj = SymbolTable::Allocate(kInitialSymbolTableSize);
     if (!maybe_obj->ToObject(&obj)) return false;
@@ -5638,6 +5642,18 @@ bool Heap::Setup(bool create_heap_objects) {
   lo_space_ = new LargeObjectSpace(this, max_old_generation_size_, LO_SPACE);
   if (lo_space_ == NULL) return false;
   if (!lo_space_->Setup()) return false;
+
+  // Setup the seed that is used to randomize the string hash function.
+  ASSERT(string_hash_seed() == 0);
+  if (FLAG_randomize_string_hashes) {
+    if (FLAG_string_hash_seed == 0) {
+      set_string_hash_seed(
+          Smi::FromInt(V8::RandomPrivate(isolate()) & 0x3fffffff));
+    } else {
+      set_string_hash_seed(Smi::FromInt(FLAG_string_hash_seed));
+    }
+  }
+
   if (create_heap_objects) {
     // Create initial maps.
     if (!CreateInitialMaps()) return false;
index d92a4fb..2d993bb 100644 (file)
@@ -96,6 +96,7 @@ inline Heap* _inline_get_heap_();
   V(FixedArray, single_character_string_cache, SingleCharacterStringCache)     \
   V(FixedArray, string_split_cache, StringSplitCache)                          \
   V(Object, termination_exception, TerminationException)                       \
+  V(Smi, string_hash_seed, StringHashSeed)                                     \
   V(Map, string_map, StringMap)                                                \
   V(Map, symbol_map, SymbolMap)                                                \
   V(Map, cons_string_map, ConsStringMap)                                       \
@@ -954,8 +955,7 @@ class Heap {
   // Please note this function does not perform a garbage collection.
   MUST_USE_RESULT MaybeObject* LookupSymbol(Vector<const char> str);
   MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(Vector<const char> str);
-  MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(
-      Vector<const uc16> str);
+  MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str);
   MUST_USE_RESULT MaybeObject* LookupAsciiSymbol(const char* str) {
     return LookupSymbol(CStrVector(str));
   }
@@ -1506,6 +1506,12 @@ class Heap {
     return idle_notification_will_schedule_next_gc_;
   }
 
+  uint32_t StringHashSeed() {
+    uint32_t seed = static_cast<uint32_t>(string_hash_seed()->value());
+    ASSERT(FLAG_randomize_string_hashes || seed == 0);
+    return seed;
+  }
+
  private:
   Heap();
 
index 3d274f2..55f66f1 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -1297,6 +1297,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ bind(&has_non_smi_element);
   // Throw away the array that's only been partially constructed.
   __ pop(eax);
+  __ UndoAllocationInNewSpace(eax);
 
   // Restore argc and constructor before running the generic code.
   __ bind(&prepare_generic_code_call);
index bb42295..9bc024f 100644 (file)
@@ -6033,10 +6033,24 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
                                     Register hash,
                                     Register character,
                                     Register scratch) {
-  // hash = character + (character << 10);
-  __ mov(hash, character);
-  __ shl(hash, 10);
-  __ add(hash, character);
+  // hash = (seed + character) + ((seed + character) << 10);
+  if (Serializer::enabled()) {
+    ExternalReference roots_array_start =
+        ExternalReference::roots_array_start(masm->isolate());
+    __ mov(scratch, Immediate(Heap::kStringHashSeedRootIndex));
+    __ mov(scratch, Operand::StaticArray(scratch,
+                                         times_pointer_size,
+                                         roots_array_start));
+    __ add(scratch, character);
+    __ mov(hash, scratch);
+    __ shl(scratch, 10);
+    __ add(hash, scratch);
+  } else {
+    int32_t seed = masm->isolate()->heap()->StringHashSeed();
+    __ lea(scratch, Operand(character, seed));
+    __ shl(scratch, 10);
+    __ lea(hash, Operand(scratch, character, times_1, seed));
+  }
   // hash ^= hash >> 6;
   __ mov(scratch, hash);
   __ shr(scratch, 6);
index 2ea9b80..c044e1f 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -106,15 +106,21 @@ class Simulator;
 // of handles to the actual constants.
 typedef ZoneList<Handle<Object> > ZoneObjectList;
 
-#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)    \
-  if (isolate->has_scheduled_exception())         \
-      return isolate->PromoteScheduledException()
+#define RETURN_IF_SCHEDULED_EXCEPTION(isolate)            \
+  do {                                                    \
+    Isolate* __isolate__ = (isolate);                     \
+    if (__isolate__->has_scheduled_exception()) {         \
+      return __isolate__->PromoteScheduledException();    \
+    }                                                     \
+  } while (false)
 
 #define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value) \
-  if (call.is_null()) {                                    \
-    ASSERT(isolate->has_pending_exception());              \
-    return value;                                          \
-  }
+  do {                                                     \
+    if ((call).is_null()) {                                \
+      ASSERT((isolate)->has_pending_exception());          \
+      return (value);                                      \
+    }                                                      \
+  } while (false)
 
 #define RETURN_IF_EMPTY_HANDLE(isolate, call)                       \
   RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, Failure::Exception())
index bf7119f..34b07ab 100644 (file)
@@ -101,6 +101,9 @@ macro IS_OBJECT(arg)            = (%_IsObject(arg));
 macro IS_ARRAY(arg)             = (%_IsArray(arg));
 macro IS_FUNCTION(arg)          = (%_IsFunction(arg));
 macro IS_REGEXP(arg)            = (%_IsRegExp(arg));
+macro IS_SET(arg)               = (%_ClassOf(arg) === 'Set');
+macro IS_MAP(arg)               = (%_ClassOf(arg) === 'Map');
+macro IS_WEAKMAP(arg)           = (%_ClassOf(arg) === 'WeakMap');
 macro IS_DATE(arg)              = (%_ClassOf(arg) === 'Date');
 macro IS_NUMBER_WRAPPER(arg)    = (%_ClassOf(arg) === 'Number');
 macro IS_STRING_WRAPPER(arg)    = (%_ClassOf(arg) === 'String');
index 18492aa..f4426f4 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// 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:
@@ -119,6 +119,19 @@ function MathLog(x) {
 // ECMA 262 - 15.8.2.11
 function MathMax(arg1, arg2) {  // length == 2
   var length = %_ArgumentsLength();
+  if (length == 2) {
+    if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
+    if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
+    if (arg2 > arg1) return arg2;
+    if (arg1 > arg2) return arg1;
+    if (arg1 == arg2) {
+      // Make sure -0 is considered less than +0.  -0 is never a Smi, +0 can be
+      // a Smi or a heap number.
+      return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg2 : arg1;
+    }
+    // All comparisons failed, one of the arguments must be NaN.
+    return 0/0;  // Compiler constant-folds this to NaN.
+  }
   if (length == 0) {
     return -1/0;  // Compiler constant-folds this to -Infinity.
   }
@@ -131,7 +144,7 @@ function MathMax(arg1, arg2) {  // length == 2
     if (NUMBER_IS_NAN(n)) return n;
     // Make sure +0 is considered greater than -0.  -0 is never a Smi, +0 can be
     // a Smi or heap number.
-    if (n > r || (r === 0 && n === 0 && !%_IsSmi(r) && 1 / r < 0)) r = n;
+    if (n > r || (r == 0 && n == 0 && !%_IsSmi(r) && 1 / r < 0)) r = n;
   }
   return r;
 }
@@ -139,6 +152,19 @@ function MathMax(arg1, arg2) {  // length == 2
 // ECMA 262 - 15.8.2.12
 function MathMin(arg1, arg2) {  // length == 2
   var length = %_ArgumentsLength();
+  if (length == 2) {
+    if (!IS_NUMBER(arg1)) arg1 = NonNumberToNumber(arg1);
+    if (!IS_NUMBER(arg2)) arg2 = NonNumberToNumber(arg2);
+    if (arg2 > arg1) return arg1;
+    if (arg1 > arg2) return arg2;
+    if (arg1 == arg2) {
+      // Make sure -0 is considered less than +0.  -0 is never a Smi, +0 can be
+      // a Smi or a heap number.
+      return (arg1 == 0 && !%_IsSmi(arg1) && 1 / arg1 < 0) ? arg1 : arg2;
+    }
+    // All comparisons failed, one of the arguments must be NaN.
+    return 0/0;  // Compiler constant-folds this to NaN.
+  }
   if (length == 0) {
     return 1/0;  // Compiler constant-folds this to Infinity.
   }
@@ -149,9 +175,9 @@ function MathMin(arg1, arg2) {  // length == 2
     var n = %_Arguments(i);
     if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
     if (NUMBER_IS_NAN(n)) return n;
-    // Make sure -0 is considered less than +0.  -0 is never a Smi, +0 can b a
+    // Make sure -0 is considered less than +0.  -0 is never a Smi, +0 can be a
     // Smi or a heap number.
-    if (n < r || (r === 0 && n === 0 && !%_IsSmi(n) && 1 / n < 0)) r = n;
+    if (n < r || (r == 0 && n == 0 && !%_IsSmi(n) && 1 / n < 0)) r = n;
   }
   return r;
 }
index 701450b..46a912b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -74,17 +74,33 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
 }
 
 
+// Load the built-in InternalArray function from the current context.
+static void GenerateLoadInternalArrayFunction(MacroAssembler* masm,
+                                              Register result) {
+  // Load the global context.
+
+  __ lw(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+  __ lw(result,
+        FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
+  // Load the InternalArray function from the global context.
+  __ lw(result,
+         MemOperand(result,
+                    Context::SlotOffset(
+                        Context::INTERNAL_ARRAY_FUNCTION_INDEX)));
+}
+
+
 // Load the built-in Array function from the current context.
 static void GenerateLoadArrayFunction(MacroAssembler* masm, Register result) {
   // Load the global context.
 
   __ lw(result, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   __ lw(result,
-         FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
+        FieldMemOperand(result, GlobalObject::kGlobalContextOffset));
   // Load the Array function from the global context.
   __ lw(result,
-         MemOperand(result,
-                    Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
+        MemOperand(result,
+                   Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX)));
 }
 
 
@@ -308,7 +324,8 @@ static void AllocateJSArray(MacroAssembler* masm,
 static void ArrayNativeCode(MacroAssembler* masm,
                             Label* call_generic_code) {
   Counters* counters = masm->isolate()->counters();
-  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array;
+  Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array,
+      has_non_smi_element;
 
   // Check for array construction with zero arguments or one.
   __ Branch(&argc_one_or_more, ne, a0, Operand(zero_reg));
@@ -406,7 +423,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ lw(a2, MemOperand(t3));
   __ Addu(t3, t3, kPointerSize);
   if (FLAG_smi_only_arrays) {
-    __ JumpIfNotSmi(a2, call_generic_code);
+    __ JumpIfNotSmi(a2, &has_non_smi_element);
   }
   __ Addu(t1, t1, -kPointerSize);
   __ sw(a2, MemOperand(t1));
@@ -422,6 +439,46 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ Addu(sp, sp, Operand(kPointerSize));
   __ mov(v0, a3);
   __ Ret();
+
+  __ bind(&has_non_smi_element);
+  __ UndoAllocationInNewSpace(a3, t0);
+  __ b(call_generic_code);
+}
+
+
+void Builtins::Generate_InternalArrayCode(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0     : number of arguments
+  //  -- ra     : return address
+  //  -- sp[...]: constructor arguments
+  // -----------------------------------
+  Label generic_array_code, one_or_more_arguments, two_or_more_arguments;
+
+  // Get the InternalArray function.
+  GenerateLoadInternalArrayFunction(masm, a1);
+
+  if (FLAG_debug_code) {
+    // Initial map for the builtin InternalArray functions should be maps.
+    __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset));
+    __ And(t0, a2, Operand(kSmiTagMask));
+    __ Assert(ne, "Unexpected initial map for InternalArray function",
+              t0, Operand(zero_reg));
+    __ GetObjectType(a2, a3, t0);
+    __ Assert(eq, "Unexpected initial map for InternalArray function",
+              t0, Operand(MAP_TYPE));
+  }
+
+  // Run the native code for the InternalArray function called as a normal
+  // function.
+  ArrayNativeCode(masm, &generic_array_code);
+
+  // Jump to the generic array code if the specialized code cannot handle the
+  // construction.
+  __ bind(&generic_array_code);
+
+  Handle<Code> array_code =
+      masm->isolate()->builtins()->InternalArrayCodeGeneric();
+  __ Jump(array_code, RelocInfo::CODE_TARGET);
 }
 
 
index b8e97f6..3e811bd 100644 (file)
@@ -5924,11 +5924,15 @@ void StringHelper::GenerateTwoCharacterSymbolTableProbe(MacroAssembler* masm,
 
 
 void StringHelper::GenerateHashInit(MacroAssembler* masm,
-                                      Register hash,
-                                      Register character) {
-  // hash = character + (character << 10);
-  __ sll(hash, character, 10);
+                                    Register hash,
+                                    Register character) {
+  // hash = seed + character + ((seed + character) << 10);
+  __ LoadRoot(hash, Heap::kStringHashSeedRootIndex);
+  // Untag smi seed and add the character.
+  __ SmiUntag(hash);
   __ addu(hash, hash, character);
+  __ sll(at, hash, 10);
+  __ addu(hash, hash, at);
   // hash ^= hash >> 6;
   __ srl(at, hash, 6);
   __ xor_(hash, hash, at);
@@ -5936,8 +5940,8 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
 
 
 void StringHelper::GenerateHashAddCharacter(MacroAssembler* masm,
-                                              Register hash,
-                                              Register character) {
+                                            Register hash,
+                                            Register character) {
   // hash += character;
   __ addu(hash, hash, character);
   // hash += hash << 10;
index 53be7d1..06e886c 100644 (file)
@@ -353,6 +353,18 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op,
 }
 
 
+Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const {
+  Handle<Object> literal = chunk_->LookupLiteral(op);
+  ASSERT(chunk_->LookupLiteralRepresentation(op).IsTagged());
+  return literal;
+}
+
+
+bool LCodeGen::IsInteger32(LConstantOperand* op) const {
+  return chunk_->LookupLiteralRepresentation(op).IsInteger32();
+}
+
+
 int LCodeGen::ToInteger32(LConstantOperand* op) const {
   Handle<Object> value = chunk_->LookupLiteral(op);
   ASSERT(chunk_->LookupLiteralRepresentation(op).IsInteger32());
index 32d4fb3..68a7c5b 100644 (file)
@@ -93,6 +93,9 @@ class LCodeGen BASE_EMBEDDED {
   // Returns a MemOperand pointing to the high word of a DoubleStackSlot.
   MemOperand ToHighMemOperand(LOperand* op) const;
 
+  bool IsInteger32(LConstantOperand* op) const;
+  Handle<Object> ToHandle(LConstantOperand* op) const;
+
   // Try to generate code for the entire chunk, but it may fail if the
   // chunk contains constructs we cannot handle. Returns true if the
   // code generation attempt succeeded.
index 8f7f89c..2e5c64e 100644 (file)
@@ -252,14 +252,24 @@ void LGapResolver::EmitMove(int index) {
     }
 
   } else if (source->IsConstantOperand()) {
-    Operand source_operand = cgen_->ToOperand(source);
+    LConstantOperand* constant_source = LConstantOperand::cast(source);
     if (destination->IsRegister()) {
-      __ li(cgen_->ToRegister(destination), source_operand);
+      Register dst = cgen_->ToRegister(destination);
+      if (cgen_->IsInteger32(constant_source)) {
+        __ li(dst, Operand(cgen_->ToInteger32(constant_source)));
+      } else {
+        __ LoadObject(dst, cgen_->ToHandle(constant_source));
+      }
     } else {
       ASSERT(destination->IsStackSlot());
       ASSERT(!in_cycle_);  // Constant moves happen after all cycles are gone.
-      MemOperand destination_operand = cgen_->ToMemOperand(destination);
-      __ li(kSavedValueRegister, source_operand);
+      if (cgen_->IsInteger32(constant_source)) {
+        __ li(kSavedValueRegister,
+              Operand(cgen_->ToInteger32(constant_source)));
+      } else {
+        __ LoadObject(kSavedValueRegister,
+                      cgen_->ToHandle(constant_source));
+      }
       __ sw(kSavedValueRegister, cgen_->ToMemOperand(destination));
     }
 
index 4e14fbf..bd5b94f 100644 (file)
@@ -264,6 +264,14 @@ class MacroAssembler: public Assembler {
 
   void LoadHeapObject(Register dst, Handle<HeapObject> object);
 
+  void LoadObject(Register result, Handle<Object> object) {
+    if (object->IsHeapObject()) {
+      LoadHeapObject(result, Handle<HeapObject>::cast(object));
+    } else {
+      li(result, object);
+    }
+  }
+
   // ---------------------------------------------------------------------------
   // GC Support
 
index 99a0bb0..c5cf060 100644 (file)
@@ -2062,8 +2062,9 @@ int HashTable<Shape, Key>::FindEntry(Isolate* isolate, Key key) {
   // EnsureCapacity will guarantee the hash table is never full.
   while (true) {
     Object* element = KeyAt(entry);
-    if (element == isolate->heap()->undefined_value()) break;  // Empty entry.
-    if (element != isolate->heap()->the_hole_value() &&
+    // Empty entry.
+    if (element == isolate->heap()->raw_unchecked_undefined_value()) break;
+    if (element != isolate->heap()->raw_unchecked_the_hole_value() &&
         Shape::IsMatch(key, element)) return entry;
     entry = NextProbe(entry, count++, capacity);
   }
@@ -4320,13 +4321,15 @@ uint32_t String::Hash() {
 }
 
 
-StringHasher::StringHasher(int length)
+StringHasher::StringHasher(int length, uint32_t seed)
   : length_(length),
-    raw_running_hash_(0),
+    raw_running_hash_(seed),
     array_index_(0),
     is_array_index_(0 < length_ && length_ <= String::kMaxArrayIndexSize),
     is_first_char_(true),
-    is_valid_(true) { }
+    is_valid_(true) {
+  ASSERT(FLAG_randomize_string_hashes || raw_running_hash_ == 0);
+}
 
 
 bool StringHasher::has_trivial_hash() {
@@ -4378,7 +4381,7 @@ uint32_t StringHasher::GetHash() {
   result += (result << 3);
   result ^= (result >> 11);
   result += (result << 15);
-  if (result == 0) {
+  if ((result & String::kHashBitMask) == 0) {
     result = 27;
   }
   return result;
@@ -4386,8 +4389,8 @@ uint32_t StringHasher::GetHash() {
 
 
 template <typename schar>
-uint32_t HashSequentialString(const schar* chars, int length) {
-  StringHasher hasher(length);
+uint32_t HashSequentialString(const schar* chars, int length, uint32_t seed) {
+  StringHasher hasher(length, seed);
   if (!hasher.has_trivial_hash()) {
     int i;
     for (i = 0; hasher.is_array_index() && (i < length); i++) {
index f3a543f..3687909 100644 (file)
@@ -6682,6 +6682,20 @@ bool String::SlowEquals(String* other) {
   // Fast check: if hash code is computed for both strings
   // a fast negative check can be performed.
   if (HasHashCode() && other->HasHashCode()) {
+#ifdef DEBUG
+    if (FLAG_enable_slow_asserts) {
+      if (Hash() != other->Hash()) {
+        bool found_difference = false;
+        for (int i = 0; i < len; i++) {
+          if (Get(i) != other->Get(i)) {
+            found_difference = true;
+            break;
+          }
+        }
+        ASSERT(found_difference);
+      }
+    }
+#endif
     if (Hash() != other->Hash()) return false;
   }
 
@@ -6817,12 +6831,16 @@ uint32_t String::ComputeAndSetHash() {
   // Compute the hash code.
   uint32_t field = 0;
   if (StringShape(this).IsSequentialAscii()) {
-    field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(), len);
+    field = HashSequentialString(SeqAsciiString::cast(this)->GetChars(),
+                                 len,
+                                 GetHeap()->StringHashSeed());
   } else if (StringShape(this).IsSequentialTwoByte()) {
-    field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(), len);
+    field = HashSequentialString(SeqTwoByteString::cast(this)->GetChars(),
+                                 len,
+                                 GetHeap()->StringHashSeed());
   } else {
     StringInputBuffer buffer(this);
-    field = ComputeHashField(&buffer, len);
+    field = ComputeHashField(&buffer, len, GetHeap()->StringHashSeed());
   }
 
   // Store the hash code in the object.
@@ -6913,8 +6931,9 @@ uint32_t StringHasher::GetHashField() {
 
 
 uint32_t String::ComputeHashField(unibrow::CharacterStream* buffer,
-                                  int length) {
-  StringHasher hasher(length);
+                                  int length,
+                                  uint32_t seed) {
+  StringHasher hasher(length, seed);
 
   // Very long strings have a trivial hash that doesn't inspect the
   // string contents.
@@ -10456,8 +10475,8 @@ class RegExpKey : public HashTableKey {
 // Utf8SymbolKey carries a vector of chars as key.
 class Utf8SymbolKey : public HashTableKey {
  public:
-  explicit Utf8SymbolKey(Vector<const char> string)
-      : string_(string), hash_field_(0) { }
+  explicit Utf8SymbolKey(Vector<const char> string, uint32_t seed)
+      : string_(string), hash_field_(0), seed_(seed) { }
 
   bool IsMatch(Object* string) {
     return String::cast(string)->IsEqualTo(string_);
@@ -10468,7 +10487,7 @@ class Utf8SymbolKey : public HashTableKey {
     unibrow::Utf8InputBuffer<> buffer(string_.start(),
                                       static_cast<unsigned>(string_.length()));
     chars_ = buffer.Length();
-    hash_field_ = String::ComputeHashField(&buffer, chars_);
+    hash_field_ = String::ComputeHashField(&buffer, chars_, seed_);
     uint32_t result = hash_field_ >> String::kHashShift;
     ASSERT(result != 0);  // Ensure that the hash value of 0 is never computed.
     return result;
@@ -10487,17 +10506,18 @@ class Utf8SymbolKey : public HashTableKey {
   Vector<const char> string_;
   uint32_t hash_field_;
   int chars_;  // Caches the number of characters when computing the hash code.
+  uint32_t seed_;
 };
 
 
 template <typename Char>
 class SequentialSymbolKey : public HashTableKey {
  public:
-  explicit SequentialSymbolKey(Vector<const Char> string)
-      : string_(string), hash_field_(0) { }
+  explicit SequentialSymbolKey(Vector<const Char> string, uint32_t seed)
+      : string_(string), hash_field_(0), seed_(seed) { }
 
   uint32_t Hash() {
-    StringHasher hasher(string_.length());
+    StringHasher hasher(string_.length(), seed_);
 
     // Very long strings have a trivial hash that doesn't inspect the
     // string contents.
@@ -10533,14 +10553,15 @@ class SequentialSymbolKey : public HashTableKey {
 
   Vector<const Char> string_;
   uint32_t hash_field_;
+  uint32_t seed_;
 };
 
 
 
 class AsciiSymbolKey : public SequentialSymbolKey<char> {
  public:
-  explicit AsciiSymbolKey(Vector<const char> str)
-      : SequentialSymbolKey<char>(str) { }
+  AsciiSymbolKey(Vector<const char> str, uint32_t seed)
+      : SequentialSymbolKey<char>(str, seed) { }
 
   bool IsMatch(Object* string) {
     return String::cast(string)->IsAsciiEqualTo(string_);
@@ -10557,13 +10578,14 @@ class SubStringAsciiSymbolKey : public HashTableKey {
  public:
   explicit SubStringAsciiSymbolKey(Handle<SeqAsciiString> string,
                                    int from,
-                                   int length)
-      : string_(string), from_(from), length_(length) { }
+                                   int length,
+                                   uint32_t seed)
+      : string_(string), from_(from), length_(length), seed_(seed) { }
 
   uint32_t Hash() {
     ASSERT(length_ >= 0);
     ASSERT(from_ + length_ <= string_->length());
-    StringHasher hasher(length_);
+    StringHasher hasher(length_, string_->GetHeap()->StringHashSeed());
 
     // Very long strings have a trivial hash that doesn't inspect the
     // string contents.
@@ -10615,13 +10637,14 @@ class SubStringAsciiSymbolKey : public HashTableKey {
   int from_;
   int length_;
   uint32_t hash_field_;
+  uint32_t seed_;
 };
 
 
 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
  public:
-  explicit TwoByteSymbolKey(Vector<const uc16> str)
-      : SequentialSymbolKey<uc16>(str) { }
+  explicit TwoByteSymbolKey(Vector<const uc16> str, uint32_t seed)
+      : SequentialSymbolKey<uc16>(str, seed) { }
 
   bool IsMatch(Object* string) {
     return String::cast(string)->IsTwoByteEqualTo(string_);
@@ -11406,10 +11429,12 @@ MaybeObject* SymbolTable::LookupString(String* string, Object** s) {
 // algorithm.
 class TwoCharHashTableKey : public HashTableKey {
  public:
-  TwoCharHashTableKey(uint32_t c1, uint32_t c2)
+  TwoCharHashTableKey(uint32_t c1, uint32_t c2, uint32_t seed)
     : c1_(c1), c2_(c2) {
     // Char 1.
-    uint32_t hash = c1 + (c1 << 10);
+    uint32_t hash = seed;
+    hash += c1;
+    hash += hash << 10;
     hash ^= hash >> 6;
     // Char 2.
     hash += c2;
@@ -11419,9 +11444,9 @@ class TwoCharHashTableKey : public HashTableKey {
     hash += hash << 3;
     hash ^= hash >> 11;
     hash += hash << 15;
-    if (hash == 0) hash = 27;
+    if ((hash & String::kHashBitMask) == 0) hash = 27;
 #ifdef DEBUG
-    StringHasher hasher(2);
+    StringHasher hasher(2, seed);
     hasher.AddCharacter(c1);
     hasher.AddCharacter(c2);
     // If this assert fails then we failed to reproduce the two-character
@@ -11478,7 +11503,7 @@ bool SymbolTable::LookupSymbolIfExists(String* string, String** symbol) {
 bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
                                                uint32_t c2,
                                                String** symbol) {
-  TwoCharHashTableKey key(c1, c2);
+  TwoCharHashTableKey key(c1, c2, GetHeap()->StringHashSeed());
   int entry = FindEntry(&key);
   if (entry == kNotFound) {
     return false;
@@ -11491,15 +11516,16 @@ bool SymbolTable::LookupTwoCharsSymbolIfExists(uint32_t c1,
 }
 
 
-MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) {
-  Utf8SymbolKey key(str);
+MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str,
+                                       Object** s) {
+  Utf8SymbolKey key(str, GetHeap()->StringHashSeed());
   return LookupKey(&key, s);
 }
 
 
 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str,
                                             Object** s) {
-  AsciiSymbolKey key(str);
+  AsciiSymbolKey key(str, GetHeap()->StringHashSeed());
   return LookupKey(&key, s);
 }
 
@@ -11508,14 +11534,14 @@ MaybeObject* SymbolTable::LookupSubStringAsciiSymbol(Handle<SeqAsciiString> str,
                                                      int from,
                                                      int length,
                                                      Object** s) {
-  SubStringAsciiSymbolKey key(str, from, length);
+  SubStringAsciiSymbolKey key(str, from, length, GetHeap()->StringHashSeed());
   return LookupKey(&key, s);
 }
 
 
 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str,
                                               Object** s) {
-  TwoByteSymbolKey key(str);
+  TwoByteSymbolKey key(str, GetHeap()->StringHashSeed());
   return LookupKey(&key, s);
 }
 
index a0e77cb..541334a 100644 (file)
@@ -6117,7 +6117,7 @@ enum RobustnessFlag {ROBUST_STRING_TRAVERSAL, FAST_STRING_TRAVERSAL};
 
 class StringHasher {
  public:
-  explicit inline StringHasher(int length);
+  explicit inline StringHasher(int length, uint32_t seed);
 
   // Returns true if the hash of this string can be computed without
   // looking at the contents.
@@ -6168,7 +6168,9 @@ class StringHasher {
 
 // Calculates string hash.
 template <typename schar>
-inline uint32_t HashSequentialString(const schar* chars, int length);
+inline uint32_t HashSequentialString(const schar* chars,
+                                     int length,
+                                     uint32_t seed);
 
 
 // The characteristics of a string are stored in its map.  Retrieving these
@@ -6391,7 +6393,8 @@ class String: public HeapObject {
   inline uint32_t Hash();
 
   static uint32_t ComputeHashField(unibrow::CharacterStream* buffer,
-                                   int length);
+                                   int length,
+                                   uint32_t seed);
 
   static bool ComputeArrayIndex(unibrow::CharacterStream* buffer,
                                 uint32_t* index,
@@ -6456,6 +6459,10 @@ class String: public HeapObject {
   // Shift constant retrieving hash code from hash field.
   static const int kHashShift = kNofHashBitFields;
 
+  // Only these bits are relevant in the hash, since the top two are shifted
+  // out.
+  static const uint32_t kHashBitMask = 0xffffffffu >> kHashShift;
+
   // Array index strings this short can keep their index in the hash
   // field.
   static const int kMaxCachedArrayIndexLength = 7;
index b3f4924..772d08b 100644 (file)
@@ -25,8 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// Platform specific code for OpenBSD goes here. For the POSIX comaptible parts
-// the implementation is in platform-posix.cc.
+// Platform specific code for OpenBSD and NetBSD goes here. For the POSIX
+// comaptible parts the implementation is in platform-posix.cc.
 
 #include <pthread.h>
 #include <semaphore.h>
@@ -742,8 +742,20 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   if (sample == NULL) sample = &sample_obj;
 
   // Extracting the sample from the context is extremely machine dependent.
-  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
   sample->state = isolate->current_vm_state();
+  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
+#ifdef __NetBSD__
+  mcontext_t& mcontext = ucontext->uc_mcontext;
+#if V8_HOST_ARCH_IA32
+  sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_EIP]);
+  sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_ESP]);
+  sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_EBP]);
+#elif V8_HOST_ARCH_X64
+  sample->pc = reinterpret_cast<Address>(mcontext.__gregs[_REG_RIP]);
+  sample->sp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RSP]);
+  sample->fp = reinterpret_cast<Address>(mcontext.__gregs[_REG_RBP]);
+#endif  // V8_HOST_ARCH
+#else  // OpenBSD
 #if V8_HOST_ARCH_IA32
   sample->pc = reinterpret_cast<Address>(ucontext->sc_eip);
   sample->sp = reinterpret_cast<Address>(ucontext->sc_esp);
@@ -752,7 +764,8 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
   sample->pc = reinterpret_cast<Address>(ucontext->sc_rip);
   sample->sp = reinterpret_cast<Address>(ucontext->sc_rsp);
   sample->fp = reinterpret_cast<Address>(ucontext->sc_rbp);
-#endif
+#endif  // V8_HOST_ARCH
+#endif  // __NetBSD__
   sampler->SampleStack(sample);
   sampler->Tick(sample);
 }
index a59d0bb..08417ff 100644 (file)
@@ -71,7 +71,8 @@ intptr_t OS::MaxVirtualMemory() {
 
 
 intptr_t OS::CommitPageSize() {
-  return 4096;
+  static intptr_t page_size = getpagesize();
+  return page_size;
 }
 
 
index a46122b..00fc7b7 100644 (file)
@@ -110,7 +110,8 @@ const char* StringsStorage::GetCopy(const char* src) {
   Vector<char> dst = Vector<char>::New(len + 1);
   OS::StrNCpy(dst, src, len);
   dst[len] = '\0';
-  uint32_t hash = HashSequentialString(dst.start(), len);
+  uint32_t hash =
+      HashSequentialString(dst.start(), len, HEAP->StringHashSeed());
   return AddOrDisposeString(dst.start(), hash);
 }
 
@@ -143,7 +144,8 @@ const char* StringsStorage::GetVFormatted(const char* format, va_list args) {
     DeleteArray(str.start());
     return format;
   }
-  uint32_t hash = HashSequentialString(str.start(), len);
+  uint32_t hash = HashSequentialString(
+      str.start(), len, HEAP->StringHashSeed());
   return AddOrDisposeString(str.start(), hash);
 }
 
@@ -153,7 +155,8 @@ const char* StringsStorage::GetName(String* name) {
     int length = Min(kMaxNameSize, name->length());
     SmartArrayPointer<char> data =
         name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL, 0, length);
-    uint32_t hash = HashSequentialString(*data, length);
+    uint32_t hash =
+        HashSequentialString(*data, length, name->GetHeap()->StringHashSeed());
     return AddOrDisposeString(data.Detach(), hash);
   }
   return "";
@@ -1501,7 +1504,9 @@ void HeapObjectsMap::RemoveDeadEntries() {
 uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
   uint64_t id = static_cast<uint64_t>(info->GetHash());
   const char* label = info->GetLabel();
-  id ^= HashSequentialString(label, static_cast<int>(strlen(label)));
+  id ^= HashSequentialString(label,
+                             static_cast<int>(strlen(label)),
+                             HEAP->StringHashSeed());
   intptr_t element_count = info->GetElementCount();
   if (element_count != -1)
     id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count));
index fb46114..811d72d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -8707,14 +8707,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
 RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
   HandleScope scope(isolate);
   ASSERT(args.length() == 5);
-  CONVERT_CHECKED(JSReceiver, fun, args[0]);
-  Object* receiver = args[1];
-  CONVERT_CHECKED(JSObject, arguments, args[2]);
-  CONVERT_CHECKED(Smi, shift, args[3]);
-  CONVERT_CHECKED(Smi, arity, args[4]);
-
-  int offset = shift->value();
-  int argc = arity->value();
+  CONVERT_ARG_CHECKED(JSReceiver, fun, 0);
+  Handle<Object> receiver = args.at<Object>(1);
+  CONVERT_ARG_CHECKED(JSObject, arguments, 2);
+  CONVERT_SMI_ARG_CHECKED(offset, 3);
+  CONVERT_SMI_ARG_CHECKED(argc, 4);
   ASSERT(offset >= 0);
   ASSERT(argc >= 0);
 
@@ -8730,17 +8727,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
   }
 
   for (int i = 0; i < argc; ++i) {
-     MaybeObject* maybe = arguments->GetElement(offset + i);
-     Object* object;
-     if (!maybe->To<Object>(&object)) return maybe;
-     argv[i] = Handle<Object>(object);
+    argv[i] = Object::GetElement(arguments, offset + i);
   }
 
   bool threw;
-  Handle<JSReceiver> hfun(fun);
-  Handle<Object> hreceiver(receiver);
   Handle<Object> result =
-      Execution::Call(hfun, hreceiver, argc, argv, &threw, true);
+      Execution::Call(fun, receiver, argc, argv, &threw, true);
 
   if (threw) return Failure::Exception();
   return *result;
index 84b0f1b..ebd3e65 100644 (file)
@@ -1256,24 +1256,29 @@ bool SemiSpace::ShrinkTo(int new_capacity) {
   ASSERT((new_capacity & Page::kPageAlignmentMask) == 0);
   ASSERT(new_capacity >= initial_capacity_);
   ASSERT(new_capacity < capacity_);
-  // Semispaces grow backwards from the end of their allocated capacity,
-  // so we find the before and after start addresses relative to the
-  // end of the space.
-  Address space_end = start_ + maximum_capacity_;
-  Address old_start = space_end - capacity_;
-  size_t delta = capacity_ - new_capacity;
-  ASSERT(IsAligned(delta, OS::AllocateAlignment()));
-  if (!heap()->isolate()->memory_allocator()->UncommitBlock(old_start, delta)) {
-    return false;
+  if (is_committed()) {
+    // Semispaces grow backwards from the end of their allocated capacity,
+    // so we find the before and after start addresses relative to the
+    // end of the space.
+    Address space_end = start_ + maximum_capacity_;
+    Address old_start = space_end - capacity_;
+    size_t delta = capacity_ - new_capacity;
+    ASSERT(IsAligned(delta, OS::AllocateAlignment()));
+
+    MemoryAllocator* allocator = heap()->isolate()->memory_allocator();
+    if (!allocator->UncommitBlock(old_start, delta)) {
+      return false;
+    }
+
+    int pages_after = new_capacity / Page::kPageSize;
+    NewSpacePage* new_last_page =
+        NewSpacePage::FromAddress(space_end - pages_after * Page::kPageSize);
+    new_last_page->set_next_page(anchor());
+    anchor()->set_prev_page(new_last_page);
+    ASSERT((current_page_ <= first_page()) && (current_page_ >= new_last_page));
   }
-  capacity_ = new_capacity;
 
-  int pages_after = capacity_ / Page::kPageSize;
-  NewSpacePage* new_last_page =
-      NewSpacePage::FromAddress(space_end - pages_after * Page::kPageSize);
-  new_last_page->set_next_page(anchor());
-  anchor()->set_prev_page(new_last_page);
-  ASSERT((current_page_ <= first_page()) && (current_page_ >= new_last_page));
+  capacity_ = new_capacity;
 
   return true;
 }
index c0315f2..0f1fed0 100644 (file)
@@ -49,8 +49,9 @@ StoreBuffer::StoreBuffer(Heap* heap)
       callback_(NULL),
       may_move_store_buffer_entries_(true),
       virtual_memory_(NULL),
-      hash_map_1_(NULL),
-      hash_map_2_(NULL) {
+      hash_set_1_(NULL),
+      hash_set_2_(NULL),
+      hash_sets_are_empty_(true) {
 }
 
 
@@ -97,18 +98,19 @@ void StoreBuffer::Setup() {
                                 false));  // Not executable.
   heap_->public_set_store_buffer_top(start_);
 
-  hash_map_1_ = new uintptr_t[kHashMapLength];
-  hash_map_2_ = new uintptr_t[kHashMapLength];
+  hash_set_1_ = new uintptr_t[kHashSetLength];
+  hash_set_2_ = new uintptr_t[kHashSetLength];
+  hash_sets_are_empty_ = false;
 
-  ZapHashTables();
+  ClearFilteringHashSets();
 }
 
 
 void StoreBuffer::TearDown() {
   delete virtual_memory_;
   delete old_virtual_memory_;
-  delete[] hash_map_1_;
-  delete[] hash_map_2_;
+  delete[] hash_set_1_;
+  delete[] hash_set_2_;
   old_start_ = old_top_ = old_limit_ = old_reserved_limit_ = NULL;
   start_ = limit_ = NULL;
   heap_->public_set_store_buffer_top(start_);
@@ -148,7 +150,6 @@ static int CompareAddresses(const void* void_a, const void* void_b) {
 
 
 void StoreBuffer::Uniq() {
-  ASSERT(HashTablesAreZapped());
   // Remove adjacent duplicates and cells that do not point at new space.
   Address previous = NULL;
   Address* write = old_start_;
@@ -272,13 +273,16 @@ void StoreBuffer::Filter(int flag) {
     }
   }
   old_top_ = new_top;
+
+  // Filtering hash sets are inconsistent with the store buffer after this
+  // operation.
+  ClearFilteringHashSets();
 }
 
 
 void StoreBuffer::SortUniq() {
   Compact();
   if (old_buffer_is_sorted_) return;
-  ZapHashTables();
   qsort(reinterpret_cast<void*>(old_start_),
         old_top_ - old_start_,
         sizeof(*old_top_),
@@ -286,6 +290,10 @@ void StoreBuffer::SortUniq() {
   Uniq();
 
   old_buffer_is_sorted_ = true;
+
+  // Filtering hash sets are inconsistent with the store buffer after this
+  // operation.
+  ClearFilteringHashSets();
 }
 
 
@@ -301,35 +309,23 @@ bool StoreBuffer::PrepareForIteration() {
   if (page_has_scan_on_scavenge_flag) {
     Filter(MemoryChunk::SCAN_ON_SCAVENGE);
   }
-  ZapHashTables();
+
+  // Filtering hash sets are inconsistent with the store buffer after
+  // iteration.
+  ClearFilteringHashSets();
+
   return page_has_scan_on_scavenge_flag;
 }
 
 
 #ifdef DEBUG
 void StoreBuffer::Clean() {
-  ZapHashTables();
+  ClearFilteringHashSets();
   Uniq();  // Also removes things that no longer point to new space.
   CheckForFullBuffer();
 }
 
 
-static bool Zapped(char* start, int size) {
-  for (int i = 0; i < size; i++) {
-    if (start[i] != 0) return false;
-  }
-  return true;
-}
-
-
-bool StoreBuffer::HashTablesAreZapped() {
-  return Zapped(reinterpret_cast<char*>(hash_map_1_),
-                sizeof(uintptr_t) * kHashMapLength) &&
-      Zapped(reinterpret_cast<char*>(hash_map_2_),
-             sizeof(uintptr_t) * kHashMapLength);
-}
-
-
 static Address* in_store_buffer_1_element_cache = NULL;
 
 
@@ -357,18 +353,21 @@ bool StoreBuffer::CellIsInStoreBuffer(Address cell_address) {
 #endif
 
 
-void StoreBuffer::ZapHashTables() {
-  memset(reinterpret_cast<void*>(hash_map_1_),
-         0,
-         sizeof(uintptr_t) * kHashMapLength);
-  memset(reinterpret_cast<void*>(hash_map_2_),
-         0,
-         sizeof(uintptr_t) * kHashMapLength);
+void StoreBuffer::ClearFilteringHashSets() {
+  if (!hash_sets_are_empty_) {
+    memset(reinterpret_cast<void*>(hash_set_1_),
+           0,
+           sizeof(uintptr_t) * kHashSetLength);
+    memset(reinterpret_cast<void*>(hash_set_2_),
+           0,
+           sizeof(uintptr_t) * kHashSetLength);
+    hash_sets_are_empty_ = true;
+  }
 }
 
 
 void StoreBuffer::GCPrologue() {
-  ZapHashTables();
+  ClearFilteringHashSets();
   during_gc_ = true;
 }
 
@@ -676,8 +675,9 @@ void StoreBuffer::Compact() {
   ASSERT(may_move_store_buffer_entries_);
   // Goes through the addresses in the store buffer attempting to remove
   // duplicates.  In the interest of speed this is a lossy operation.  Some
-  // duplicates will remain.  We have two hash tables with different hash
+  // duplicates will remain.  We have two hash sets with different hash
   // functions to reduce the number of unnecessary clashes.
+  hash_sets_are_empty_ = false;  // Hash sets are in use.
   for (Address* current = start_; current < top; current++) {
     ASSERT(!heap_->cell_space()->Contains(*current));
     ASSERT(!heap_->code_space()->Contains(*current));
@@ -686,21 +686,21 @@ void StoreBuffer::Compact() {
     // Shift out the last bits including any tags.
     int_addr >>= kPointerSizeLog2;
     int hash1 =
-        ((int_addr ^ (int_addr >> kHashMapLengthLog2)) & (kHashMapLength - 1));
-    if (hash_map_1_[hash1] == int_addr) continue;
-    int hash2 =
-        ((int_addr - (int_addr >> kHashMapLengthLog2)) & (kHashMapLength - 1));
-    hash2 ^= hash2 >> (kHashMapLengthLog2 * 2);
-    if (hash_map_2_[hash2] == int_addr) continue;
-    if (hash_map_1_[hash1] == 0) {
-      hash_map_1_[hash1] = int_addr;
-    } else if (hash_map_2_[hash2] == 0) {
-      hash_map_2_[hash2] = int_addr;
+        ((int_addr ^ (int_addr >> kHashSetLengthLog2)) & (kHashSetLength - 1));
+    if (hash_set_1_[hash1] == int_addr) continue;
+    uintptr_t hash2 = (int_addr - (int_addr >> kHashSetLengthLog2));
+    hash2 ^= hash2 >> (kHashSetLengthLog2 * 2);
+    hash2 &= (kHashSetLength - 1);
+    if (hash_set_2_[hash2] == int_addr) continue;
+    if (hash_set_1_[hash1] == 0) {
+      hash_set_1_[hash1] = int_addr;
+    } else if (hash_set_2_[hash2] == 0) {
+      hash_set_2_[hash2] = int_addr;
     } else {
       // Rather than slowing down we just throw away some entries.  This will
       // cause some duplicates to remain undetected.
-      hash_map_1_[hash1] = int_addr;
-      hash_map_2_[hash2] = 0;
+      hash_set_1_[hash1] = int_addr;
+      hash_set_2_[hash2] = 0;
     }
     old_buffer_is_sorted_ = false;
     old_buffer_is_filtered_ = false;
index ab25938..204fa3f 100644 (file)
@@ -85,8 +85,8 @@ class StoreBuffer {
   static const int kStoreBufferSize = kStoreBufferOverflowBit;
   static const int kStoreBufferLength = kStoreBufferSize / sizeof(Address);
   static const int kOldStoreBufferLength = kStoreBufferLength * 16;
-  static const int kHashMapLengthLog2 = 12;
-  static const int kHashMapLength = 1 << kHashMapLengthLog2;
+  static const int kHashSetLengthLog2 = 12;
+  static const int kHashSetLength = 1 << kHashSetLengthLog2;
 
   void Compact();
 
@@ -148,13 +148,18 @@ class StoreBuffer {
   bool may_move_store_buffer_entries_;
 
   VirtualMemory* virtual_memory_;
-  uintptr_t* hash_map_1_;
-  uintptr_t* hash_map_2_;
+
+  // Two hash sets used for filtering.
+  // If address is in the hash set then it is guaranteed to be in the
+  // old part of the store buffer.
+  uintptr_t* hash_set_1_;
+  uintptr_t* hash_set_2_;
+  bool hash_sets_are_empty_;
+
+  void ClearFilteringHashSets();
 
   void CheckForFullBuffer();
   void Uniq();
-  void ZapHashTables();
-  bool HashTablesAreZapped();
   void ExemptPopularPages(int prime_sample_step, int threshold);
 
   void FindPointersToNewSpaceInRegion(Address start,
index 0354fc1..c882d86 100644 (file)
@@ -51,6 +51,7 @@ bool V8::has_been_setup_ = false;
 bool V8::has_been_disposed_ = false;
 bool V8::has_fatal_error_ = false;
 bool V8::use_crankshaft_ = true;
+List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL;
 
 static Mutex* entropy_mutex = OS::CreateMutex();
 static EntropySource entropy_source;
@@ -104,6 +105,9 @@ void V8::TearDown() {
 
   is_running_ = false;
   has_been_disposed_ = true;
+
+  delete call_completed_callbacks_;
+  call_completed_callbacks_ = NULL;
 }
 
 
@@ -169,6 +173,41 @@ bool V8::IdleNotification(int hint) {
 }
 
 
+void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
+  if (call_completed_callbacks_ == NULL) {  // Lazy init.
+    call_completed_callbacks_ = new List<CallCompletedCallback>();
+  }
+  for (int i = 0; i < call_completed_callbacks_->length(); i++) {
+    if (callback == call_completed_callbacks_->at(i)) return;
+  }
+  call_completed_callbacks_->Add(callback);
+}
+
+
+void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) {
+  if (call_completed_callbacks_ == NULL) return;
+  for (int i = 0; i < call_completed_callbacks_->length(); i++) {
+    if (callback == call_completed_callbacks_->at(i)) {
+      call_completed_callbacks_->Remove(i);
+    }
+  }
+}
+
+
+void V8::FireCallCompletedCallback(Isolate* isolate) {
+  if (call_completed_callbacks_ == NULL) return;
+  HandleScopeImplementer* handle_scope_implementer =
+      isolate->handle_scope_implementer();
+  if (!handle_scope_implementer->CallDepthIsZero()) return;
+  // Fire callbacks.  Increase call depth to prevent recursive callbacks.
+  handle_scope_implementer->IncrementCallDepth();
+  for (int i = 0; i < call_completed_callbacks_->length(); i++) {
+    call_completed_callbacks_->at(i)();
+  }
+  handle_scope_implementer->DecrementCallDepth();
+}
+
+
 // Use a union type to avoid type-aliasing optimizations in GCC.
 typedef union {
   double double_value;
index 71e7fe4..b9a3e05 100644 (file)
@@ -108,6 +108,10 @@ class V8 : public AllStatic {
   // Idle notification directly from the API.
   static bool IdleNotification(int hint);
 
+  static void AddCallCompletedCallback(CallCompletedCallback callback);
+  static void RemoveCallCompletedCallback(CallCompletedCallback callback);
+  static void FireCallCompletedCallback(Isolate* isolate);
+
  private:
   static void InitializeOncePerProcess();
 
@@ -123,6 +127,8 @@ class V8 : public AllStatic {
   static bool has_been_disposed_;
   // True if we are using the crankshaft optimizing compiler.
   static bool use_crankshaft_;
+  // List of callbacks when a Call completes.
+  static List<CallCompletedCallback>* call_completed_callbacks_;
 };
 
 
index 46b2b1a..617b7d1 100644 (file)
@@ -34,7 +34,7 @@
 // cannot be changed without changing the SCons build script.
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     8
-#define BUILD_NUMBER      4
+#define BUILD_NUMBER      5
 #define PATCH_LEVEL       0
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
index dff55fb..ef63c7a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// 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:
@@ -1199,7 +1199,8 @@ static void AllocateJSArray(MacroAssembler* masm,
 // a construct call and a normal call.
 static void ArrayNativeCode(MacroAssembler* masm,
                             Label *call_generic_code) {
-  Label argc_one_or_more, argc_two_or_more, empty_array, not_empty_array;
+  Label argc_one_or_more, argc_two_or_more, empty_array, not_empty_array,
+      has_non_smi_element;
 
   // Check for array construction with zero arguments.
   __ testq(rax, rax);
@@ -1306,7 +1307,7 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ bind(&loop);
   __ movq(kScratchRegister, Operand(r9, rcx, times_pointer_size, 0));
   if (FLAG_smi_only_arrays) {
-    __ JumpIfNotSmi(kScratchRegister, call_generic_code);
+    __ JumpIfNotSmi(kScratchRegister, &has_non_smi_element);
   }
   __ movq(Operand(rdx, 0), kScratchRegister);
   __ addq(rdx, Immediate(kPointerSize));
@@ -1324,6 +1325,10 @@ static void ArrayNativeCode(MacroAssembler* masm,
   __ push(rcx);
   __ movq(rax, rbx);
   __ ret(0);
+
+  __ bind(&has_non_smi_element);
+  __ UndoAllocationInNewSpace(rbx);
+  __ jmp(call_generic_code);
 }
 
 
index 1d67bae..ea9c494 100644 (file)
@@ -4958,10 +4958,13 @@ void StringHelper::GenerateHashInit(MacroAssembler* masm,
                                     Register hash,
                                     Register character,
                                     Register scratch) {
-  // hash = character + (character << 10);
-  __ movl(hash, character);
-  __ shll(hash, Immediate(10));
-  __ addl(hash, character);
+  // hash = (seed + character) + ((seed + character) << 10);
+  __ LoadRoot(scratch, Heap::kStringHashSeedRootIndex);
+  __ SmiToInteger32(scratch, scratch);
+  __ addl(scratch, character);
+  __ movl(hash, scratch);
+  __ shll(scratch, Immediate(10));
+  __ addl(hash, scratch);
   // hash ^= hash >> 6;
   __ movl(scratch, hash);
   __ shrl(scratch, Immediate(6));
index dab8b7c..fb8becd 100644 (file)
@@ -14238,7 +14238,7 @@ THREADED_TEST(RoundRobinGetFromCache) {
       "  for (var i = 0; i < 16; i++) values[i] = %_GetFromCache(0, keys[i]);"
       "  for (var i = 0; i < 16; i++) {"
       "    var v = %_GetFromCache(0, keys[i]);"
-      "    if (v !== values[i])"
+      "    if (v.toString() !== values[i].toString())"
       "      return 'Wrong value for ' + "
       "          keys[i] + ': ' + v + ' vs. ' + values[i];"
       "  };"
@@ -15726,3 +15726,98 @@ THREADED_TEST(ForeignFunctionReceiver) {
 
   foreign_context.Dispose();
 }
+
+
+uint8_t callback_fired = 0;
+
+
+void CallCompletedCallback1() {
+  i::OS::Print("Firing callback 1.\n");
+  callback_fired ^= 1;  // Toggle first bit.
+}
+
+
+void CallCompletedCallback2() {
+  i::OS::Print("Firing callback 2.\n");
+  callback_fired ^= 2;  // Toggle second bit.
+}
+
+
+Handle<Value> RecursiveCall(const Arguments& args) {
+  int32_t level = args[0]->Int32Value();
+  if (level < 3) {
+    level++;
+    i::OS::Print("Entering recursion level %d.\n", level);
+    char script[64];
+    i::Vector<char> script_vector(script, sizeof(script));
+    i::OS::SNPrintF(script_vector, "recursion(%d)", level);
+    CompileRun(script_vector.start());
+    i::OS::Print("Leaving recursion level %d.\n", level);
+    CHECK_EQ(0, callback_fired);
+  } else {
+    i::OS::Print("Recursion ends.\n");
+    CHECK_EQ(0, callback_fired);
+  }
+  return Undefined();
+}
+
+
+TEST(CallCompletedCallback) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::Handle<v8::FunctionTemplate> recursive_runtime =
+      v8::FunctionTemplate::New(RecursiveCall);
+  env->Global()->Set(v8_str("recursion"),
+                     recursive_runtime->GetFunction());
+  // Adding the same callback a second time has no effect.
+  v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
+  v8::V8::AddCallCompletedCallback(CallCompletedCallback1);
+  v8::V8::AddCallCompletedCallback(CallCompletedCallback2);
+  i::OS::Print("--- Script (1) ---\n");
+  Local<Script> script =
+      v8::Script::Compile(v8::String::New("recursion(0)"));
+  script->Run();
+  CHECK_EQ(3, callback_fired);
+
+  i::OS::Print("\n--- Script (2) ---\n");
+  callback_fired = 0;
+  v8::V8::RemoveCallCompletedCallback(CallCompletedCallback1);
+  script->Run();
+  CHECK_EQ(2, callback_fired);
+
+  i::OS::Print("\n--- Function ---\n");
+  callback_fired = 0;
+  Local<Function> recursive_function =
+      Local<Function>::Cast(env->Global()->Get(v8_str("recursion")));
+  v8::Handle<Value> args[] = { v8_num(0) };
+  recursive_function->Call(env->Global(), 1, args);
+  CHECK_EQ(2, callback_fired);
+}
+
+
+void CallCompletedCallbackNoException() {
+  v8::HandleScope scope;
+  CompileRun("1+1;");
+}
+
+
+void CallCompletedCallbackException() {
+  v8::HandleScope scope;
+  CompileRun("throw 'second exception';");
+}
+
+
+TEST(CallCompletedCallbackOneException) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::V8::AddCallCompletedCallback(CallCompletedCallbackNoException);
+  CompileRun("throw 'exception';");
+}
+
+
+TEST(CallCompletedCallbackTwoExceptions) {
+  v8::HandleScope scope;
+  LocalContext env;
+  v8::V8::AddCallCompletedCallback(CallCompletedCallbackException);
+  CompileRun("throw 'first exception';");
+}
index 9ed1dbb..8447df5 100644 (file)
@@ -50,10 +50,12 @@ function listener(event, exec_state, event_data, data) {
           var expected_y = (i + 1) * 2 + 2 + ((i + 1) * 2 + 2) / 100;
 
           // All frames except the bottom one has normal variables a and b.
-          assertEquals('a', frame.localName(0));
-          assertEquals('b', frame.localName(1));
-          assertEquals(expected_a, frame.localValue(0).value());
-          assertEquals(expected_b, frame.localValue(1).value());
+          var a = ('a' === frame.localName(0)) ? 0 : 1;
+          var b = 1 - a;
+          assertEquals('a', frame.localName(a));
+          assertEquals('b', frame.localName(b));
+          assertEquals(expected_a, frame.localValue(a).value());
+          assertEquals(expected_b, frame.localValue(b).value());
 
           // All frames except the bottom one has arguments variables x and y.
           assertEquals('x', frame.argumentName(0));
index 683c139..c3cd5eb 100644 (file)
@@ -50,10 +50,12 @@ function listener(event, exec_state, event_data, data) {
           var expected_y = (i + 1) * 2 + 2;
 
           // All frames except the bottom one has normal variables a and b.
-          assertEquals('a', frame.localName(0));
-          assertEquals('b', frame.localName(1));
-          assertEquals(expected_a, frame.localValue(0).value());
-          assertEquals(expected_b, frame.localValue(1).value());
+          var a = ('a' === frame.localName(0)) ? 0 : 1;
+          var b = 1 - a;
+          assertEquals('a', frame.localName(a));
+          assertEquals('b', frame.localName(b));
+          assertEquals(expected_a, frame.localValue(a).value());
+          assertEquals(expected_b, frame.localValue(b).value());
 
           // All frames except the bottom one has arguments variables x and y.
           assertEquals('x', frame.argumentName(0));
@@ -119,7 +121,7 @@ function listener(event, exec_state, event_data, data) {
       listenerComplete = true;
     }
   } catch (e) {
-    exception = e
+    exception = e.stack;
   };
 };
 
index 4b435c1..412e6f1 100644 (file)
@@ -274,6 +274,40 @@ var o = Object.create({}, { myValue: {
 assertEquals(10, o.myValue);
 
 
+// Regression test for issue 1884: Invoking any of the methods for Harmony
+// maps, sets, or weak maps, with a wrong type of receiver should be throwing
+// a proper TypeError.
+var alwaysBogus = [ undefined, null, true, "x", 23, {} ];
+var bogusReceiversTestSet = [
+  { proto: Set.prototype,
+    funcs: [ 'add', 'has', 'delete' ],
+    receivers: alwaysBogus.concat([ new Map, new WeakMap ]),
+  },
+  { proto: Map.prototype,
+    funcs: [ 'get', 'set', 'has', 'delete' ],
+    receivers: alwaysBogus.concat([ new Set, new WeakMap ]),
+  },
+  { proto: WeakMap.prototype,
+    funcs: [ 'get', 'set', 'has', 'delete' ],
+    receivers: alwaysBogus.concat([ new Set, new Map ]),
+  },
+];
+function TestBogusReceivers(testSet) {
+  for (var i = 0; i < testSet.length; i++) {
+    var proto = testSet[i].proto;
+    var funcs = testSet[i].funcs;
+    var receivers = testSet[i].receivers;
+    for (var j = 0; j < funcs.length; j++) {
+      var func = proto[funcs[j]];
+      for (var k = 0; k < receivers.length; k++) {
+        assertThrows(function () { func.call(receivers[k], {}) }, TypeError);
+      }
+    }
+  }
+}
+TestBogusReceivers(bogusReceiversTestSet);
+
+
 // Stress Test
 // There is a proposed stress-test available at the es-discuss mailing list
 // which cannot be reasonably automated.  Check it out by hand if you like:
index 0c7e125..44f9518 100755 (executable)
@@ -486,7 +486,7 @@ class MinidumpReader(object):
     if self.arch == MD_CPU_ARCHITECTURE_AMD64:
       return self.exception_context.rsp
     elif self.arch == MD_CPU_ARCHITECTURE_X86:
-      return self.exception_context.rbp
+      return self.exception_context.esp
 
   def FormatIntPtr(self, value):
     if self.arch == MD_CPU_ARCHITECTURE_AMD64:
@@ -523,13 +523,20 @@ INSTANCE_TYPES = {
   66: "EXTERNAL_SYMBOL_TYPE",
   74: "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
   70: "EXTERNAL_ASCII_SYMBOL_TYPE",
+  82: "SHORT_EXTERNAL_SYMBOL_TYPE",
+  90: "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE",
+  86: "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE",
   0: "STRING_TYPE",
   4: "ASCII_STRING_TYPE",
   1: "CONS_STRING_TYPE",
   5: "CONS_ASCII_STRING_TYPE",
+  3: "SLICED_STRING_TYPE",
   2: "EXTERNAL_STRING_TYPE",
   10: "EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
   6: "EXTERNAL_ASCII_STRING_TYPE",
+  18: "SHORT_EXTERNAL_STRING_TYPE",
+  26: "SHORT_EXTERNAL_STRING_WITH_ASCII_DATA_TYPE",
+  22: "SHORT_EXTERNAL_ASCII_STRING_TYPE",
   6: "PRIVATE_EXTERNAL_ASCII_STRING_TYPE",
   128: "MAP_TYPE",
   129: "CODE_TYPE",
@@ -538,43 +545,45 @@ INSTANCE_TYPES = {
   132: "HEAP_NUMBER_TYPE",
   133: "FOREIGN_TYPE",
   134: "BYTE_ARRAY_TYPE",
-  135: "EXTERNAL_BYTE_ARRAY_TYPE",
-  136: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
-  137: "EXTERNAL_SHORT_ARRAY_TYPE",
-  138: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
-  139: "EXTERNAL_INT_ARRAY_TYPE",
-  140: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
-  141: "EXTERNAL_FLOAT_ARRAY_TYPE",
-  143: "EXTERNAL_PIXEL_ARRAY_TYPE",
-  145: "FILLER_TYPE",
-  146: "ACCESSOR_INFO_TYPE",
-  147: "ACCESS_CHECK_INFO_TYPE",
-  148: "INTERCEPTOR_INFO_TYPE",
-  149: "CALL_HANDLER_INFO_TYPE",
-  150: "FUNCTION_TEMPLATE_INFO_TYPE",
-  151: "OBJECT_TEMPLATE_INFO_TYPE",
-  152: "SIGNATURE_INFO_TYPE",
-  153: "TYPE_SWITCH_INFO_TYPE",
-  154: "SCRIPT_TYPE",
-  155: "CODE_CACHE_TYPE",
-  156: "POLYMORPHIC_CODE_CACHE_TYPE",
-  159: "FIXED_ARRAY_TYPE",
-  160: "SHARED_FUNCTION_INFO_TYPE",
-  161: "JS_MESSAGE_OBJECT_TYPE",
-  162: "JS_VALUE_TYPE",
-  163: "JS_OBJECT_TYPE",
-  164: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
-  165: "JS_GLOBAL_OBJECT_TYPE",
-  166: "JS_BUILTINS_OBJECT_TYPE",
-  167: "JS_GLOBAL_PROXY_TYPE",
-  168: "JS_ARRAY_TYPE",
-  169: "JS_PROXY_TYPE",
-  170: "JS_WEAK_MAP_TYPE",
-  171: "JS_REGEXP_TYPE",
-  172: "JS_FUNCTION_TYPE",
-  173: "JS_FUNCTION_PROXY_TYPE",
-  157: "DEBUG_INFO_TYPE",
-  158: "BREAK_POINT_INFO_TYPE",
+  135: "FREE_SPACE_TYPE",
+  136: "EXTERNAL_BYTE_ARRAY_TYPE",
+  137: "EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE",
+  138: "EXTERNAL_SHORT_ARRAY_TYPE",
+  139: "EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE",
+  140: "EXTERNAL_INT_ARRAY_TYPE",
+  141: "EXTERNAL_UNSIGNED_INT_ARRAY_TYPE",
+  142: "EXTERNAL_FLOAT_ARRAY_TYPE",
+  144: "EXTERNAL_PIXEL_ARRAY_TYPE",
+  146: "FILLER_TYPE",
+  147: "ACCESSOR_INFO_TYPE",
+  148: "ACCESS_CHECK_INFO_TYPE",
+  149: "INTERCEPTOR_INFO_TYPE",
+  150: "CALL_HANDLER_INFO_TYPE",
+  151: "FUNCTION_TEMPLATE_INFO_TYPE",
+  152: "OBJECT_TEMPLATE_INFO_TYPE",
+  153: "SIGNATURE_INFO_TYPE",
+  154: "TYPE_SWITCH_INFO_TYPE",
+  155: "SCRIPT_TYPE",
+  156: "CODE_CACHE_TYPE",
+  157: "POLYMORPHIC_CODE_CACHE_TYPE",
+  160: "FIXED_ARRAY_TYPE",
+  145: "FIXED_DOUBLE_ARRAY_TYPE",
+  161: "SHARED_FUNCTION_INFO_TYPE",
+  162: "JS_MESSAGE_OBJECT_TYPE",
+  165: "JS_VALUE_TYPE",
+  166: "JS_OBJECT_TYPE",
+  167: "JS_CONTEXT_EXTENSION_OBJECT_TYPE",
+  168: "JS_GLOBAL_OBJECT_TYPE",
+  169: "JS_BUILTINS_OBJECT_TYPE",
+  170: "JS_GLOBAL_PROXY_TYPE",
+  171: "JS_ARRAY_TYPE",
+  164: "JS_PROXY_TYPE",
+  174: "JS_WEAK_MAP_TYPE",
+  175: "JS_REGEXP_TYPE",
+  176: "JS_FUNCTION_TYPE",
+  163: "JS_FUNCTION_PROXY_TYPE",
+  158: "DEBUG_INFO_TYPE",
+  159: "BREAK_POINT_INFO_TYPE",
 }
 
 
@@ -652,7 +661,7 @@ class HeapObject(object):
 
 
 class Map(HeapObject):
-  def InstanceTypeOffset():
+  def InstanceTypeOffset(self):
     return self.heap.PointerSize() + self.heap.IntSize()
 
   def __init__(self, heap, map, address):
@@ -886,7 +895,7 @@ class Code(HeapObject):
   def HeaderSize(heap):
     return (heap.PointerSize() + heap.IntSize() + \
         4 * heap.PointerSize() + 3 * heap.IntSize() + \
-        CODE_ALIGNMENT_MASK) & ~CODE_ALIGNMENT_MASK
+        Code.CODE_ALIGNMENT_MASK) & ~Code.CODE_ALIGNMENT_MASK
 
   def __init__(self, heap, map, address):
     HeapObject.__init__(self, heap, map, address)
@@ -916,6 +925,9 @@ class V8Heap(object):
     "EXTERNAL_SYMBOL_TYPE": ExternalString,
     "EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString,
     "EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString,
+    "SHORT_EXTERNAL_SYMBOL_TYPE": ExternalString,
+    "SHORT_EXTERNAL_SYMBOL_WITH_ASCII_DATA_TYPE": ExternalString,
+    "SHORT_EXTERNAL_ASCII_SYMBOL_TYPE": ExternalString,
     "STRING_TYPE": SeqString,
     "ASCII_STRING_TYPE": SeqString,
     "CONS_STRING_TYPE": ConsString,
@@ -945,7 +957,7 @@ class V8Heap(object):
   def FindObject(self, tagged_address):
     if tagged_address in self.objects:
       return self.objects[tagged_address]
-    if (tagged_address & 1) != 1: return None
+    if (tagged_address & self.ObjectAlignmentMask()) != 1: return None
     address = tagged_address - 1
     if not self.reader.IsValidAddress(address): return None
     map_tagged_address = self.reader.ReadUIntPtr(address)
@@ -957,7 +969,7 @@ class V8Heap(object):
       meta_map.map = meta_map
       object = meta_map
     else:
-      map = self.FindObject(map_tagged_address)
+      map = self.FindMap(map_tagged_address)
       if map is None: return None
       instance_type_name = INSTANCE_TYPES.get(map.instance_type)
       if instance_type_name is None: return None
@@ -966,9 +978,27 @@ class V8Heap(object):
     self.objects[tagged_address] = object
     return object
 
+  def FindMap(self, tagged_address):
+    if (tagged_address & self.MapAlignmentMask()) != 1: return None
+    address = tagged_address - 1
+    if not self.reader.IsValidAddress(address): return None
+    object = Map(self, None, address)
+    return object
+
+  def IntSize(self):
+    return 4
+
   def PointerSize(self):
     return self.reader.PointerSize()
 
+  def ObjectAlignmentMask(self):
+    return self.PointerSize() - 1
+
+  def MapAlignmentMask(self):
+    if self.reader.arch == MD_CPU_ARCHITECTURE_AMD64:
+      return (1 << 4) - 1
+    elif self.reader.arch == MD_CPU_ARCHITECTURE_X86:
+      return (1 << 5) - 1
 
 
 EIP_PROXIMITY = 64
index 66a26b5..57e2cbd 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright 2011 the V8 project authors. All rights reserved.
+# 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:
                 ],
               }
             ],
+            ['OS=="netbsd"', {
+                'link_settings': {
+                  'libraries': [
+                    '-L/usr/pkg/lib -Wl,-R/usr/pkg/lib -lexecinfo',
+                ]},
+                'sources': [
+                  '../../src/platform-openbsd.cc',
+                  '../../src/platform-posix.cc'
+                ],
+              }
+            ],
             ['OS=="solaris"', {
                 'sources': [
                   '../../src/platform-solaris.cc',