Browse Source

Upgrade V8 to 3.8.5

v0.7.4-release
Ryan Dahl 13 years ago
parent
commit
8e5674fb5c
  1. 26
      deps/v8/ChangeLog
  2. 6
      deps/v8/LICENSE
  3. 15
      deps/v8/build/common.gypi
  4. 24
      deps/v8/build/standalone.gypi
  5. 20
      deps/v8/include/v8.h
  6. 40
      deps/v8/src/api.cc
  7. 11
      deps/v8/src/arm/builtins-arm.cc
  8. 6
      deps/v8/src/arm/code-stubs-arm.cc
  9. 20
      deps/v8/src/checks.h
  10. 44
      deps/v8/src/collection.js
  11. 3
      deps/v8/src/d8-posix.cc
  12. 4
      deps/v8/src/d8.gyp
  13. 8
      deps/v8/src/flag-definitions.h
  14. 16
      deps/v8/src/heap.cc
  15. 10
      deps/v8/src/heap.h
  16. 3
      deps/v8/src/ia32/builtins-ia32.cc
  17. 22
      deps/v8/src/ia32/code-stubs-ia32.cc
  18. 22
      deps/v8/src/isolate.h
  19. 3
      deps/v8/src/macros.py
  20. 34
      deps/v8/src/math.js
  21. 69
      deps/v8/src/mips/builtins-mips.cc
  22. 16
      deps/v8/src/mips/code-stubs-mips.cc
  23. 12
      deps/v8/src/mips/lithium-codegen-mips.cc
  24. 3
      deps/v8/src/mips/lithium-codegen-mips.h
  25. 18
      deps/v8/src/mips/lithium-gap-resolver-mips.cc
  26. 8
      deps/v8/src/mips/macro-assembler-mips.h
  27. 19
      deps/v8/src/objects-inl.h
  28. 82
      deps/v8/src/objects.cc
  29. 13
      deps/v8/src/objects.h
  30. 21
      deps/v8/src/platform-openbsd.cc
  31. 3
      deps/v8/src/platform-posix.cc
  32. 13
      deps/v8/src/profile-generator.cc
  33. 24
      deps/v8/src/runtime.cc
  34. 37
      deps/v8/src/spaces.cc
  35. 96
      deps/v8/src/store-buffer.cc
  36. 17
      deps/v8/src/store-buffer.h
  37. 39
      deps/v8/src/v8.cc
  38. 6
      deps/v8/src/v8.h
  39. 2
      deps/v8/src/version.cc
  40. 11
      deps/v8/src/x64/builtins-x64.cc
  41. 11
      deps/v8/src/x64/code-stubs-x64.cc
  42. 97
      deps/v8/test/cctest/test-api.cc
  43. 10
      deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js
  44. 12
      deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js
  45. 34
      deps/v8/test/mjsunit/harmony/collections.js
  46. 114
      deps/v8/tools/grokdump.py
  47. 13
      deps/v8/tools/gyp/v8.gyp

26
deps/v8/ChangeLog

@ -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.

6
deps/v8/LICENSE

@ -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:

15
deps/v8/build/common.gypi

@ -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:
@ -215,7 +215,8 @@
},
},
}],
['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' ],
@ -259,7 +260,10 @@
['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' ],
}],
@ -267,7 +271,7 @@
},
'Release': {
'conditions': [
['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="netbsd"', {
'cflags!': [
'-O2',
'-Os',
@ -290,6 +294,9 @@
['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

24
deps/v8/build/standalone.gypi

@ -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:
@ -37,13 +37,16 @@
'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',
@ -96,7 +100,9 @@
}],
],
},
}], # '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': [

20
deps/v8/include/v8.h

@ -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,11 +3036,24 @@ 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.

40
deps/v8/src/api.cc

@ -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();

11
deps/v8/src/arm/builtins-arm.cc

@ -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);
}

6
deps/v8/src/arm/code-stubs-arm.cc

@ -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));
}

20
deps/v8/src/checks.h

@ -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)

44
deps/v8/src/collection.js

@ -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]);
}

3
deps/v8/src/d8-posix.cc

@ -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

4
deps/v8/src/d8.gyp

@ -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"', {

8
deps/v8/src/flag-definitions.h

@ -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,

16
deps/v8/src/heap.cc

@ -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;

10
deps/v8/src/heap.h

@ -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();

3
deps/v8/src/ia32/builtins-ia32.cc

@ -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);

22
deps/v8/src/ia32/code-stubs-ia32.cc

@ -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);

22
deps/v8/src/isolate.h

@ -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())

3
deps/v8/src/macros.py

@ -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');

34
deps/v8/src/math.js

@ -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;
}

69
deps/v8/src/mips/builtins-mips.cc

@ -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);
}

16
deps/v8/src/mips/code-stubs-mips.cc

@ -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;

12
deps/v8/src/mips/lithium-codegen-mips.cc

@ -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());

3
deps/v8/src/mips/lithium-codegen-mips.h

@ -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.

18
deps/v8/src/mips/lithium-gap-resolver-mips.cc

@ -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));
}

8
deps/v8/src/mips/macro-assembler-mips.h

@ -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

19
deps/v8/src/objects-inl.h

@ -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++) {

82
deps/v8/src/objects.cc

@ -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);
}

13
deps/v8/src/objects.h

@ -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;

21
deps/v8/src/platform-openbsd.cc

@ -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);
}

3
deps/v8/src/platform-posix.cc

@ -71,7 +71,8 @@ intptr_t OS::MaxVirtualMemory() {
intptr_t OS::CommitPageSize() {
return 4096;
static intptr_t page_size = getpagesize();
return page_size;
}

13
deps/v8/src/profile-generator.cc

@ -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));

24
deps/v8/src/runtime.cc

@ -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;

37
deps/v8/src/spaces.cc

@ -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;
}

96
deps/v8/src/store-buffer.cc

@ -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;

17
deps/v8/src/store-buffer.h

@ -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,

39
deps/v8/src/v8.cc

@ -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;

6
deps/v8/src/v8.h

@ -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_;
};

2
deps/v8/src/version.cc

@ -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.)

11
deps/v8/src/x64/builtins-x64.cc

@ -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);
}

11
deps/v8/src/x64/code-stubs-x64.cc

@ -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));

97
deps/v8/test/cctest/test-api.cc

@ -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';");
}

10
deps/v8/test/mjsunit/debug-evaluate-locals-optimized-double.js

@ -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));

12
deps/v8/test/mjsunit/debug-evaluate-locals-optimized.js

@ -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;
};
};

34
deps/v8/test/mjsunit/harmony/collections.js

@ -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:

114
deps/v8/tools/grokdump.py

@ -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

13
deps/v8/tools/gyp/v8.gyp

@ -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:
@ -684,6 +684,17 @@
],
}
],
['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',

Loading…
Cancel
Save