Version 3.20.1
Implemented WeakMap.prototype.clear function. (issue 2753)
Ensure CheckInitialized is present independent of define. (Chromium issue 255779)
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@15448 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index 86847e1..e78623d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2013-07-02: Version 3.20.1
+
+ Implemented WeakMap.prototype.clear function. (issue 2753)
+
+ Ensure CheckInitialized is present independent of define.
+ (Chromium issue 255779)
+
+ Performance and stability improvements on all platforms.
+
+
2013-06-28: Version 3.20.0
Migrated several tests from blink to V8 repository.
diff --git a/DEPS b/DEPS
index 8d66960..4f1a5cf 100644
--- a/DEPS
+++ b/DEPS
@@ -5,7 +5,10 @@
deps = {
# Remember to keep the revision in sync with the Makefile.
"v8/build/gyp":
- "http://gyp.googlecode.com/svn/trunk@1501",
+ "http://gyp.googlecode.com/svn/trunk@1656",
+
+ "v8/third_party/icu":
+ "https://src.chromium.org/chrome/trunk/deps/third_party/icu46@205936",
}
deps_os = {
diff --git a/Makefile b/Makefile
index bdd6524..78e22d7 100644
--- a/Makefile
+++ b/Makefile
@@ -391,4 +391,7 @@
# Remember to keep these in sync with the DEPS file.
dependencies:
svn checkout --force http://gyp.googlecode.com/svn/trunk build/gyp \
- --revision 1501
+ --revision 1656
+ svn checkout --force \
+ https://src.chromium.org/chrome/trunk/deps/third_party/icu46 \
+ third_party/icu --revision 205936
diff --git a/build/shim_headers.gypi b/build/shim_headers.gypi
new file mode 100644
index 0000000..940211c
--- /dev/null
+++ b/build/shim_headers.gypi
@@ -0,0 +1,73 @@
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This file is meant to be included into a target to handle shim headers
+# in a consistent manner. To use this the following variables need to be
+# defined:
+# headers_root_path: string: path to directory containing headers
+# header_filenames: list: list of header file names
+
+{
+ 'variables': {
+ 'shim_headers_path': '<(SHARED_INTERMEDIATE_DIR)/shim_headers/<(_target_name)/<(_toolset)',
+ 'shim_generator_additional_args%': [],
+ },
+ 'include_dirs++': [
+ '<(shim_headers_path)',
+ ],
+ 'all_dependent_settings': {
+ 'include_dirs+++': [
+ '<(shim_headers_path)',
+ ],
+ },
+ 'actions': [
+ {
+ 'variables': {
+ 'generator_path': '<(DEPTH)/tools/generate_shim_headers/generate_shim_headers.py',
+ 'generator_args': [
+ '--headers-root', '<(headers_root_path)',
+ '--output-directory', '<(shim_headers_path)',
+ '<@(shim_generator_additional_args)',
+ '<@(header_filenames)',
+ ],
+ },
+ 'action_name': 'generate_<(_target_name)_shim_headers',
+ 'inputs': [
+ '<(generator_path)',
+ ],
+ 'outputs': [
+ '<!@pymod_do_main(generate_shim_headers <@(generator_args) --outputs)',
+ ],
+ 'action': ['python',
+ '<(generator_path)',
+ '<@(generator_args)',
+ '--generate',
+ ],
+ 'message': 'Generating <(_target_name) shim headers.',
+ },
+ ],
+}
diff --git a/build/standalone.gypi b/build/standalone.gypi
index f7ca0a6..b14adfa 100644
--- a/build/standalone.gypi
+++ b/build/standalone.gypi
@@ -30,6 +30,7 @@
{
'variables': {
'component%': 'static_library',
+ 'clang%': 0,
'visibility%': 'hidden',
'v8_enable_backtrace%': 0,
'msvs_multi_core_compile%': '1',
@@ -65,6 +66,13 @@
'target_arch%': '<(target_arch)',
'v8_target_arch%': '<(v8_target_arch)',
'werror%': '-Werror',
+
+ # .gyp files or targets should set v8_code to 1 if they build V8 specific
+ # code, as opposed to external code. This variable is used to control such
+ # things as the set of warnings to enable, and whether warnings are treated
+ # as errors.
+ 'v8_code%': 0,
+
'conditions': [
['(v8_target_arch=="arm" and host_arch!="arm") or \
(v8_target_arch=="mipsel" and host_arch!="mipsel") or \
@@ -74,6 +82,11 @@
}, {
'want_separate_host_toolset': 0,
}],
+ ['OS == "win"', {
+ 'os_posix%': 0,
+ }, {
+ 'os_posix%': 1,
+ }],
],
# Default ARM variable settings.
'armv7%': 'default',
@@ -83,6 +96,9 @@
'arm_thumb': 'default',
},
'target_defaults': {
+ 'variables': {
+ 'v8_code%': '<(v8_code)',
+ },
'default_configuration': 'Debug',
'configurations': {
'Debug': {
@@ -92,6 +108,29 @@
# Xcode insists on this empty entry.
},
},
+ 'target_conditions': [
+ ['v8_code == 0', {
+ 'conditions': [
+ ['os_posix == 1 and OS != "mac"', {
+ 'cflags!': [
+ '-Werror',
+ ],
+ }],
+ ['OS == "mac"', {
+ 'xcode_settings': {
+ 'GCC_TREAT_WARNINGS_AS_ERRORS': 'NO', # -Werror
+ },
+ }],
+ ['OS == "win"', {
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'WarnAsError': 'false',
+ },
+ },
+ }],
+ ],
+ }],
+ ],
},
'conditions': [
['OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris" \
diff --git a/include/v8-profiler.h b/include/v8-profiler.h
index 5338fcd..8e6251a 100644
--- a/include/v8-profiler.h
+++ b/include/v8-profiler.h
@@ -75,6 +75,9 @@
/** Returns function name (empty string for anonymous functions.) */
Handle<String> GetFunctionName() const;
+ /** Returns id of the script where function is located. */
+ int GetScriptId() const;
+
/** Returns resource name for script from where the function originates. */
Handle<String> GetScriptResourceName() const;
diff --git a/include/v8.h b/include/v8.h
index cf01684..3afb835 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -3993,8 +3993,9 @@
HeapProfiler* GetHeapProfiler();
/**
- * Returns CPU profiler for this isolate. Will return NULL until the isolate
- * is initialized.
+ * Returns CPU profiler for this isolate. Will return NULL unless the isolate
+ * is initialized. It is the embedder's responsibility to stop all CPU
+ * profiling activities if it has started any.
*/
CpuProfiler* GetCpuProfiler();
@@ -4823,7 +4824,10 @@
v8::internal::Isolate* isolate_;
void* next_;
void* exception_;
- void* message_;
+ void* message_obj_;
+ void* message_script_;
+ int message_start_pos_;
+ int message_end_pos_;
bool is_verbose_ : 1;
bool can_continue_ : 1;
bool capture_message_ : 1;
@@ -5397,11 +5401,12 @@
static const int kUndefinedOddballKind = 5;
static const int kNullOddballKind = 3;
+ static void CheckInitializedImpl(v8::Isolate* isolate);
+ V8_INLINE(static void CheckInitialized(v8::Isolate* isolate)) {
#ifdef V8_ENABLE_CHECKS
- static void CheckInitialized(v8::Isolate* isolate);
-#else
- static void CheckInitialized(v8::Isolate* isolate) { }
+ CheckInitializedImpl(isolate);
#endif
+ }
V8_INLINE(static bool HasHeapObjectTag(internal::Object* value)) {
return ((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) ==
diff --git a/preparser/preparser.gyp b/preparser/preparser.gyp
index 863a2ff..598f0a5 100644
--- a/preparser/preparser.gyp
+++ b/preparser/preparser.gyp
@@ -26,6 +26,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'variables': {
+ 'v8_code': 1,
+ },
'includes': ['../build/common.gypi'],
'targets': [
{
diff --git a/samples/samples.gyp b/samples/samples.gyp
index 3c720a7..8b1de7e 100644
--- a/samples/samples.gyp
+++ b/samples/samples.gyp
@@ -26,6 +26,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'variables': {
+ 'v8_code': 1,
+ },
'includes': ['../build/common.gypi'],
'target_defaults': {
'type': 'executable',
diff --git a/src/api.cc b/src/api.cc
index edffca1..ee80579 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2092,13 +2092,12 @@
v8::TryCatch::TryCatch()
: isolate_(i::Isolate::Current()),
next_(isolate_->try_catch_handler_address()),
- exception_(isolate_->heap()->the_hole_value()),
- message_(i::Smi::FromInt(0)),
is_verbose_(false),
can_continue_(true),
capture_message_(true),
rethrow_(false),
has_terminated_(false) {
+ Reset();
isolate_->RegisterTryCatchHandler(this);
}
@@ -2108,8 +2107,17 @@
if (rethrow_) {
v8::HandleScope scope(reinterpret_cast<Isolate*>(isolate_));
v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception());
+ if (HasCaught() && capture_message_) {
+ // If an exception was caught and rethrow_ is indicated, the saved
+ // message, script, and location need to be restored to Isolate TLS
+ // for reuse. capture_message_ needs to be disabled so that DoThrow()
+ // does not create a new message.
+ isolate_->thread_local_top()->rethrowing_message_ = true;
+ isolate_->RestorePendingMessageFromTryCatch(this);
+ }
isolate_->UnregisterTryCatchHandler(this);
v8::ThrowException(exc);
+ ASSERT(!isolate_->thread_local_top()->rethrowing_message_);
} else {
isolate_->UnregisterTryCatchHandler(this);
}
@@ -2170,8 +2178,9 @@
v8::Local<v8::Message> v8::TryCatch::Message() const {
ASSERT(isolate_ == i::Isolate::Current());
- if (HasCaught() && message_ != i::Smi::FromInt(0)) {
- i::Object* message = reinterpret_cast<i::Object*>(message_);
+ i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
+ ASSERT(message->IsJSMessageObject() || message->IsTheHole());
+ if (HasCaught() && !message->IsTheHole()) {
return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
} else {
return v8::Local<v8::Message>();
@@ -2181,8 +2190,12 @@
void v8::TryCatch::Reset() {
ASSERT(isolate_ == i::Isolate::Current());
- exception_ = isolate_->heap()->the_hole_value();
- message_ = i::Smi::FromInt(0);
+ i::Object* the_hole = isolate_->heap()->the_hole_value();
+ exception_ = the_hole;
+ message_obj_ = the_hole;
+ message_script_ = the_hole;
+ message_start_pos_ = 0;
+ message_end_pos_ = 0;
}
@@ -2921,14 +2934,12 @@
}
-#ifdef V8_ENABLE_CHECKS
-void i::Internals::CheckInitialized(v8::Isolate* external_isolate) {
+void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
ApiCheck(isolate != NULL && isolate->IsInitialized() && !i::V8::IsDead(),
"v8::internal::Internals::CheckInitialized()",
"Isolate is not initialized or V8 has died");
}
-#endif
void External::CheckCast(v8::Value* that) {
@@ -7315,6 +7326,15 @@
}
+int CpuProfileNode::GetScriptId() const {
+ i::Isolate* isolate = i::Isolate::Current();
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptId");
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
+ const i::CodeEntry* entry = node->entry();
+ return entry->script_id();
+}
+
+
Handle<String> CpuProfileNode::GetScriptResourceName() const {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName");
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc
index c6ea600..89c0a3b 100644
--- a/src/arm/assembler-arm.cc
+++ b/src/arm/assembler-arm.cc
@@ -36,7 +36,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "arm/assembler-arm-inl.h"
#include "serialize.h"
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc
index 6b3caf3..69ba00a 100644
--- a/src/arm/builtins-arm.cc
+++ b/src/arm/builtins-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "codegen.h"
#include "debug.h"
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 8e9237c..6af5cce 100755
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "bootstrapper.h"
#include "code-stubs.h"
@@ -3077,7 +3077,7 @@
__ mov(r0, Operand(r4));
__ mov(r1, Operand(r6));
-#if defined(V8_HOST_ARCH_ARM)
+#if V8_HOST_ARCH_ARM
int frame_alignment = MacroAssembler::ActivationFrameAlignment();
int frame_alignment_mask = frame_alignment - 1;
if (FLAG_debug_code) {
@@ -7125,7 +7125,7 @@
__ and_(sp, sp, Operand(-frame_alignment));
}
-#if defined(V8_HOST_ARCH_ARM)
+#if V8_HOST_ARCH_ARM
int32_t entry_hook =
reinterpret_cast<int32_t>(masm->isolate()->function_entry_hook());
__ mov(ip, Operand(entry_hook));
diff --git a/src/arm/codegen-arm.cc b/src/arm/codegen-arm.cc
index 5b2980a..60de5fc 100644
--- a/src/arm/codegen-arm.cc
+++ b/src/arm/codegen-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "codegen.h"
#include "macro-assembler.h"
diff --git a/src/arm/constants-arm.cc b/src/arm/constants-arm.cc
index a130484..7d59a84 100644
--- a/src/arm/constants-arm.cc
+++ b/src/arm/constants-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "constants-arm.h"
diff --git a/src/arm/cpu-arm.cc b/src/arm/cpu-arm.cc
index 101cd9f..8766a24 100644
--- a/src/arm/cpu-arm.cc
+++ b/src/arm/cpu-arm.cc
@@ -32,7 +32,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "cpu.h"
#include "macro-assembler.h"
diff --git a/src/arm/debug-arm.cc b/src/arm/debug-arm.cc
index 2f0a7c4..7faea08 100644
--- a/src/arm/debug-arm.cc
+++ b/src/arm/debug-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "codegen.h"
#include "debug.h"
diff --git a/src/arm/disasm-arm.cc b/src/arm/disasm-arm.cc
index f55552d..6101bec 100644
--- a/src/arm/disasm-arm.cc
+++ b/src/arm/disasm-arm.cc
@@ -56,7 +56,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "constants-arm.h"
#include "disasm.h"
diff --git a/src/arm/frames-arm.cc b/src/arm/frames-arm.cc
index 72fc5ce..b207180 100644
--- a/src/arm/frames-arm.cc
+++ b/src/arm/frames-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "assembler.h"
#include "assembler-arm.h"
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
index 357f0af..41f02be 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "code-stubs.h"
#include "codegen.h"
diff --git a/src/arm/ic-arm.cc b/src/arm/ic-arm.cc
index cc78151..89ebfde 100644
--- a/src/arm/ic-arm.cc
+++ b/src/arm/ic-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "assembler-arm.h"
#include "code-stubs.h"
diff --git a/src/arm/macro-assembler-arm.cc b/src/arm/macro-assembler-arm.cc
index fb379e2..9e4dc40 100644
--- a/src/arm/macro-assembler-arm.cc
+++ b/src/arm/macro-assembler-arm.cc
@@ -29,7 +29,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "bootstrapper.h"
#include "codegen.h"
@@ -985,19 +985,19 @@
int MacroAssembler::ActivationFrameAlignment() {
-#if defined(V8_HOST_ARCH_ARM)
+#if V8_HOST_ARCH_ARM
// Running on the real platform. Use the alignment as mandated by the local
// environment.
// Note: This will break if we ever start generating snapshots on one ARM
// platform for another ARM platform with a different alignment.
return OS::ActivationFrameAlignment();
-#else // defined(V8_HOST_ARCH_ARM)
+#else // V8_HOST_ARCH_ARM
// If we are using the simulator then we should always align to the expected
// alignment. As the simulator is used to generate snapshots we do not know
// if the target platform will need alignment, so this is controlled from a
// flag.
return FLAG_sim_stack_alignment;
-#endif // defined(V8_HOST_ARCH_ARM)
+#endif // V8_HOST_ARCH_ARM
}
@@ -3403,7 +3403,7 @@
// Make sure that the stack is aligned before calling a C function unless
// running in the simulator. The simulator has its own alignment check which
// provides more information.
-#if defined(V8_HOST_ARCH_ARM)
+#if V8_HOST_ARCH_ARM
if (emit_debug_code()) {
int frame_alignment = OS::ActivationFrameAlignment();
int frame_alignment_mask = frame_alignment - 1;
diff --git a/src/arm/regexp-macro-assembler-arm.cc b/src/arm/regexp-macro-assembler-arm.cc
index f05cba5..0acb737 100644
--- a/src/arm/regexp-macro-assembler-arm.cc
+++ b/src/arm/regexp-macro-assembler-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "unicode.h"
#include "log.h"
diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
index a29d461..238632a 100644
--- a/src/arm/simulator-arm.cc
+++ b/src/arm/simulator-arm.cc
@@ -30,7 +30,7 @@
#include <cstdarg>
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "disasm.h"
#include "assembler.h"
diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
index 21cb802..c154f9a 100644
--- a/src/arm/stub-cache-arm.cc
+++ b/src/arm/stub-cache-arm.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_ARM
#include "ic-inl.h"
#include "codegen.h"
diff --git a/src/assembler.cc b/src/assembler.cc
index 626fd4f..b669e09 100644
--- a/src/assembler.cc
+++ b/src/assembler.cc
@@ -1308,7 +1308,7 @@
ExternalReference ExternalReference::re_check_stack_guard_state(
Isolate* isolate) {
Address function;
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
function = FUNCTION_ADDR(RegExpMacroAssemblerX64::CheckStackGuardState);
#elif V8_TARGET_ARCH_IA32
function = FUNCTION_ADDR(RegExpMacroAssemblerIA32::CheckStackGuardState);
diff --git a/src/ast.h b/src/ast.h
index 6336b3a..b9a98e0 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -1884,6 +1884,9 @@
BailoutId RightId() const { return right_id_; }
TypeFeedbackId BinaryOperationFeedbackId() const { return reuse(id()); }
+ // TODO(rossberg): result_type should be subsumed by lower_type.
+ Handle<Type> result_type() const { return result_type_; }
+ void set_result_type(Handle<Type> type) { result_type_ = type; }
Maybe<int> fixed_right_arg() const { return fixed_right_arg_; }
void set_fixed_right_arg(Maybe<int> arg) { fixed_right_arg_ = arg; }
@@ -1910,6 +1913,7 @@
Expression* right_;
int pos_;
+ Handle<Type> result_type_;
// TODO(rossberg): the fixed arg should probably be represented as a Constant
// type for the RHS.
Maybe<int> fixed_right_arg_;
diff --git a/src/atomicops.h b/src/atomicops.h
index ebca91d..b18b54d 100644
--- a/src/atomicops.h
+++ b/src/atomicops.h
@@ -154,17 +154,17 @@
#if defined(THREAD_SANITIZER)
#include "atomicops_internals_tsan.h"
#elif defined(_MSC_VER) && \
- (defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64))
+ (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
#include "atomicops_internals_x86_msvc.h"
#elif defined(__APPLE__) && \
- (defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64))
+ (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
#include "atomicops_internals_x86_macosx.h"
#elif defined(__GNUC__) && \
- (defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64))
+ (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
#include "atomicops_internals_x86_gcc.h"
-#elif defined(__GNUC__) && defined(V8_HOST_ARCH_ARM)
+#elif defined(__GNUC__) && V8_HOST_ARCH_ARM
#include "atomicops_internals_arm_gcc.h"
-#elif defined(__GNUC__) && defined(V8_HOST_ARCH_MIPS)
+#elif defined(__GNUC__) && V8_HOST_ARCH_MIPS
#include "atomicops_internals_mips_gcc.h"
#else
#error "Atomic operations are not supported on your platform"
diff --git a/src/code-stubs.h b/src/code-stubs.h
index c7076b6..d197c84 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -95,7 +95,7 @@
V(KeyedLoadField)
// List of code stubs only used on ARM platforms.
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
#define CODE_STUB_LIST_ARM(V) \
V(GetProperty) \
V(SetProperty) \
@@ -107,7 +107,7 @@
#endif
// List of code stubs only used on MIPS platforms.
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
#define CODE_STUB_LIST_MIPS(V) \
V(RegExpCEntry) \
V(DirectCEntry)
diff --git a/src/collection.js b/src/collection.js
index 950c7e7..c5604ab 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -295,6 +295,16 @@
}
+function WeakMapClear() {
+ if (!IS_WEAKMAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakMap.prototype.clear', this]);
+ }
+ // Replace the internal table with a new empty table.
+ %WeakMapInitialize(this);
+}
+
+
// -------------------------------------------------------------------
function SetUpWeakMap() {
@@ -309,7 +319,8 @@
"get", WeakMapGet,
"set", WeakMapSet,
"has", WeakMapHas,
- "delete", WeakMapDelete
+ "delete", WeakMapDelete,
+ "clear", WeakMapClear
));
}
diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h
index 4982197..c3cc27c 100644
--- a/src/cpu-profiler-inl.h
+++ b/src/cpu-profiler-inl.h
@@ -56,6 +56,17 @@
}
+void ReportBuiltinEventRecord::UpdateCodeMap(CodeMap* code_map) {
+ CodeEntry* entry = code_map->FindEntry(start);
+ if (!entry) {
+ // Code objects for builtins should already have been added to the map but
+ // some of them have been filtered out by CpuProfiler.
+ return;
+ }
+ entry->SetBuiltinId(builtin_id);
+}
+
+
TickSample* ProfilerEventsProcessor::TickSampleEvent() {
generator_->Tick();
TickSampleEventRecord* evt =
@@ -64,16 +75,6 @@
}
-bool ProfilerEventsProcessor::FilterOutCodeCreateEvent(
- Logger::LogEventsAndTags tag) {
- return FLAG_prof_browser_mode
- && (tag != Logger::CALLBACK_TAG
- && tag != Logger::FUNCTION_TAG
- && tag != Logger::LAZY_COMPILE_TAG
- && tag != Logger::REG_EXP_TAG
- && tag != Logger::SCRIPT_TAG);
-}
-
} } // namespace v8::internal
#endif // V8_CPU_PROFILER_INL_H_
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index 109ddd5..be64dd7 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -45,11 +45,9 @@
static const int kProfilerStackSize = 64 * KB;
-ProfilerEventsProcessor::ProfilerEventsProcessor(
- ProfileGenerator* generator, CpuProfilesCollection* profiles)
+ProfilerEventsProcessor::ProfilerEventsProcessor(ProfileGenerator* generator)
: Thread(Thread::Options("v8:ProfEvntProc", kProfilerStackSize)),
generator_(generator),
- profiles_(profiles),
running_(true),
ticks_buffer_(sizeof(TickSampleEventRecord),
kTickSamplesBufferChunkSize,
@@ -58,120 +56,9 @@
}
-void ProfilerEventsProcessor::CallbackCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix,
- Name* name,
- Address start) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, prefix, name);
- rec->size = 1;
- rec->shared = NULL;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Name* name,
- String* resource_name,
- int line_number,
- Address start,
- unsigned size,
- Address shared,
- CompilationInfo* info) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, name, resource_name, line_number);
- if (info) {
- rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
- }
- rec->size = size;
- rec->shared = shared;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
- const char* name,
- Address start,
- unsigned size) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, name);
- rec->size = size;
- rec->shared = NULL;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::CodeCreateEvent(Logger::LogEventsAndTags tag,
- int args_count,
- Address start,
- unsigned size) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, args_count);
- rec->size = size;
- rec->shared = NULL;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::CodeMoveEvent(Address from, Address to) {
- CodeEventsContainer evt_rec;
- CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
- rec->type = CodeEventRecord::CODE_MOVE;
- rec->order = ++enqueue_order_;
- rec->from = from;
- rec->to = to;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::SharedFunctionInfoMoveEvent(Address from,
- Address to) {
- CodeEventsContainer evt_rec;
- SharedFunctionInfoMoveEventRecord* rec =
- &evt_rec.SharedFunctionInfoMoveEventRecord_;
- rec->type = CodeEventRecord::SHARED_FUNC_MOVE;
- rec->order = ++enqueue_order_;
- rec->from = from;
- rec->to = to;
- events_buffer_.Enqueue(evt_rec);
-}
-
-
-void ProfilerEventsProcessor::RegExpCodeCreateEvent(
- Logger::LogEventsAndTags tag,
- const char* prefix,
- String* name,
- Address start,
- unsigned size) {
- if (FilterOutCodeCreateEvent(tag)) return;
- CodeEventsContainer evt_rec;
- CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
- rec->type = CodeEventRecord::CODE_CREATION;
- rec->order = ++enqueue_order_;
- rec->start = start;
- rec->entry = profiles_->NewCodeEntry(tag, prefix, name);
- rec->size = size;
- events_buffer_.Enqueue(evt_rec);
+void ProfilerEventsProcessor::Enqueue(const CodeEventsContainer& event) {
+ event.generic.order = ++enqueue_order_;
+ events_buffer_.Enqueue(event);
}
@@ -305,30 +192,56 @@
}
+static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag) {
+ return FLAG_prof_browser_mode
+ && (tag != Logger::CALLBACK_TAG
+ && tag != Logger::FUNCTION_TAG
+ && tag != Logger::LAZY_COMPILE_TAG
+ && tag != Logger::REG_EXP_TAG
+ && tag != Logger::SCRIPT_TAG);
+}
+
+
void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
- processor_->CallbackCreateEvent(
- Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
+ if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = entry_point;
+ rec->entry = profiles_->NewCodeEntry(
+ Logger::CALLBACK_TAG,
+ profiles_->GetName(name),
+ TokenEnumerator::kInheritsSecurityToken);
+ rec->size = 1;
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, const char* comment) {
- processor_->CodeCreateEvent(
- tag, comment, code->address(), code->ExecutableSize());
+ Code* code,
+ const char* name) {
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+ rec->size = code->ExecutableSize();
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, Name* name) {
- processor_->CodeCreateEvent(
- tag,
- name,
- isolate_->heap()->empty_string(),
- v8::CpuProfileNode::kNoLineNumberInfo,
- code->address(),
- code->ExecutableSize(),
- NULL,
- NULL);
+ Code* code,
+ Name* name) {
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+ rec->size = code->ExecutableSize();
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
@@ -337,15 +250,22 @@
SharedFunctionInfo* shared,
CompilationInfo* info,
Name* name) {
- processor_->CodeCreateEvent(
- tag,
- name,
- isolate_->heap()->empty_string(),
- v8::CpuProfileNode::kNoLineNumberInfo,
- code->address(),
- code->ExecutableSize(),
- shared->address(),
- info);
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(tag, profiles_->GetFunctionName(name));
+ if (info) {
+ rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
+ }
+ if (shared->script()->IsScript()) {
+ ASSERT(Script::cast(shared->script()));
+ Script* script = Script::cast(shared->script());
+ rec->entry->set_script_id(script->id()->value());
+ }
+ rec->size = code->ExecutableSize();
+ rec->shared = shared->address();
+ processor_->Enqueue(evt_rec);
}
@@ -354,30 +274,53 @@
SharedFunctionInfo* shared,
CompilationInfo* info,
String* source, int line) {
- processor_->CodeCreateEvent(
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(
tag,
- shared->DebugName(),
- source,
- line,
- code->address(),
- code->ExecutableSize(),
- shared->address(),
- info);
+ profiles_->GetFunctionName(shared->DebugName()),
+ TokenEnumerator::kNoSecurityToken,
+ CodeEntry::kEmptyNamePrefix,
+ profiles_->GetName(source),
+ line);
+ if (info) {
+ rec->entry->set_no_frame_ranges(info->ReleaseNoFrameRanges());
+ }
+ ASSERT(Script::cast(shared->script()));
+ Script* script = Script::cast(shared->script());
+ rec->entry->set_script_id(script->id()->value());
+ rec->size = code->ExecutableSize();
+ rec->shared = shared->address();
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, int args_count) {
- processor_->CodeCreateEvent(
+ Code* code,
+ int args_count) {
+ if (FilterOutCodeCreateEvent(tag)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(
tag,
- args_count,
- code->address(),
- code->ExecutableSize());
+ profiles_->GetName(args_count),
+ TokenEnumerator::kInheritsSecurityToken,
+ "args_count: ");
+ rec->size = code->ExecutableSize();
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::CodeMoveEvent(Address from, Address to) {
- processor_->CodeMoveEvent(from, to);
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_MOVE);
+ CodeMoveEventRecord* rec = &evt_rec.CodeMoveEventRecord_;
+ rec->from = from;
+ rec->to = to;
+ processor_->Enqueue(evt_rec);
}
@@ -386,29 +329,59 @@
void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
- processor_->SharedFunctionInfoMoveEvent(from, to);
+ CodeEventsContainer evt_rec(CodeEventRecord::SHARED_FUNC_MOVE);
+ SharedFunctionInfoMoveEventRecord* rec =
+ &evt_rec.SharedFunctionInfoMoveEventRecord_;
+ rec->from = from;
+ rec->to = to;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
- processor_->CallbackCreateEvent(
- Logger::CALLBACK_TAG, "get ", name, entry_point);
+ if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = entry_point;
+ rec->entry = profiles_->NewCodeEntry(
+ Logger::CALLBACK_TAG,
+ profiles_->GetName(name),
+ TokenEnumerator::kInheritsSecurityToken,
+ "get ");
+ rec->size = 1;
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
- processor_->RegExpCodeCreateEvent(
+ if (FilterOutCodeCreateEvent(Logger::REG_EXP_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = code->address();
+ rec->entry = profiles_->NewCodeEntry(
Logger::REG_EXP_TAG,
- "RegExp: ",
- source,
- code->address(),
- code->ExecutableSize());
+ profiles_->GetName(source),
+ TokenEnumerator::kInheritsSecurityToken,
+ "RegExp: ");
+ rec->size = code->ExecutableSize();
+ processor_->Enqueue(evt_rec);
}
void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
- processor_->CallbackCreateEvent(
- Logger::CALLBACK_TAG, "set ", name, entry_point);
+ if (FilterOutCodeCreateEvent(Logger::CALLBACK_TAG)) return;
+ CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
+ CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
+ rec->start = entry_point;
+ rec->entry = profiles_->NewCodeEntry(
+ Logger::CALLBACK_TAG,
+ profiles_->GetName(name),
+ TokenEnumerator::kInheritsSecurityToken,
+ "set ");
+ rec->size = 1;
+ rec->shared = NULL;
+ processor_->Enqueue(evt_rec);
}
@@ -424,7 +397,23 @@
}
+CpuProfiler::CpuProfiler(Isolate* isolate,
+ CpuProfilesCollection* test_profiles,
+ ProfileGenerator* test_generator,
+ ProfilerEventsProcessor* test_processor)
+ : isolate_(isolate),
+ profiles_(test_profiles),
+ next_profile_uid_(1),
+ token_enumerator_(new TokenEnumerator()),
+ generator_(test_generator),
+ processor_(test_processor),
+ need_to_stop_sampler_(false),
+ is_profiling_(false) {
+}
+
+
CpuProfiler::~CpuProfiler() {
+ ASSERT(!is_profiling_);
delete token_enumerator_;
delete profiles_;
}
@@ -450,23 +439,24 @@
void CpuProfiler::StartProcessorIfNotStarted() {
if (processor_ == NULL) {
+ Logger* logger = isolate_->logger();
// Disable logging when using the new implementation.
- saved_logging_nesting_ = isolate_->logger()->logging_nesting_;
- isolate_->logger()->logging_nesting_ = 0;
+ saved_logging_nesting_ = logger->logging_nesting_;
+ logger->logging_nesting_ = 0;
generator_ = new ProfileGenerator(profiles_);
- processor_ = new ProfilerEventsProcessor(generator_, profiles_);
+ processor_ = new ProfilerEventsProcessor(generator_);
is_profiling_ = true;
processor_->StartSynchronously();
// Enumerate stuff we already have in the heap.
- if (isolate_->heap()->HasBeenSetUp()) {
- if (!FLAG_prof_browser_mode) {
- isolate_->logger()->LogCodeObjects();
- }
- isolate_->logger()->LogCompiledFunctions();
- isolate_->logger()->LogAccessorCallbacks();
+ ASSERT(isolate_->heap()->HasBeenSetUp());
+ if (!FLAG_prof_browser_mode) {
+ logger->LogCodeObjects();
}
+ logger->LogCompiledFunctions();
+ logger->LogAccessorCallbacks();
+ LogBuiltins();
// Enable stack sampling.
- Sampler* sampler = isolate_->logger()->sampler();
+ Sampler* sampler = logger->sampler();
sampler->IncreaseProfilingDepth();
if (!sampler->IsActive()) {
sampler->Start();
@@ -525,4 +515,18 @@
}
+void CpuProfiler::LogBuiltins() {
+ Builtins* builtins = isolate_->builtins();
+ ASSERT(builtins->is_initialized());
+ for (int i = 0; i < Builtins::builtin_count; i++) {
+ CodeEventsContainer evt_rec(CodeEventRecord::REPORT_BUILTIN);
+ ReportBuiltinEventRecord* rec = &evt_rec.ReportBuiltinEventRecord_;
+ Builtins::Name id = static_cast<Builtins::Name>(i);
+ rec->start = builtins->builtin(id)->address();
+ rec->builtin_id = id;
+ processor_->Enqueue(evt_rec);
+ }
+}
+
+
} } // namespace v8::internal
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 455c893..61d40f0 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -49,7 +49,8 @@
#define CODE_EVENTS_TYPE_LIST(V) \
V(CODE_CREATION, CodeCreateEventRecord) \
V(CODE_MOVE, CodeMoveEventRecord) \
- V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord)
+ V(SHARED_FUNC_MOVE, SharedFunctionInfoMoveEventRecord) \
+ V(REPORT_BUILTIN, ReportBuiltinEventRecord)
class CodeEventRecord {
@@ -63,7 +64,7 @@
#undef DECLARE_TYPE
Type type;
- unsigned order;
+ mutable unsigned order;
};
@@ -96,6 +97,15 @@
};
+class ReportBuiltinEventRecord : public CodeEventRecord {
+ public:
+ Address start;
+ Builtins::Name builtin_id;
+
+ INLINE(void UpdateCodeMap(CodeMap* code_map));
+};
+
+
class TickSampleEventRecord {
public:
// The parameterless constructor is used when we dequeue data from
@@ -122,41 +132,34 @@
};
+class CodeEventsContainer {
+ public:
+ explicit CodeEventsContainer(
+ CodeEventRecord::Type type = CodeEventRecord::NONE) {
+ generic.type = type;
+ }
+ union {
+ CodeEventRecord generic;
+#define DECLARE_CLASS(ignore, type) type type##_;
+ CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
+#undef DECLARE_TYPE
+ };
+};
+
+
// This class implements both the profile events processor thread and
// methods called by event producers: VM and stack sampler threads.
class ProfilerEventsProcessor : public Thread {
public:
- ProfilerEventsProcessor(ProfileGenerator* generator,
- CpuProfilesCollection* profiles);
+ explicit ProfilerEventsProcessor(ProfileGenerator* generator);
virtual ~ProfilerEventsProcessor() {}
// Thread control.
virtual void Run();
inline void Stop() { running_ = false; }
INLINE(bool running()) { return running_; }
+ void Enqueue(const CodeEventsContainer& event);
- // Events adding methods. Called by VM threads.
- void CallbackCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix, Name* name,
- Address start);
- void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Name* name,
- String* resource_name, int line_number,
- Address start, unsigned size,
- Address shared,
- CompilationInfo* info);
- void CodeCreateEvent(Logger::LogEventsAndTags tag,
- const char* name,
- Address start, unsigned size);
- void CodeCreateEvent(Logger::LogEventsAndTags tag,
- int args_count,
- Address start, unsigned size);
- void CodeMoveEvent(Address from, Address to);
- void CodeDeleteEvent(Address from);
- void SharedFunctionInfoMoveEvent(Address from, Address to);
- void RegExpCodeCreateEvent(Logger::LogEventsAndTags tag,
- const char* prefix, String* name,
- Address start, unsigned size);
// Puts current stack into tick sample events buffer.
void AddCurrentStack();
@@ -167,21 +170,11 @@
INLINE(TickSample* TickSampleEvent());
private:
- union CodeEventsContainer {
- CodeEventRecord generic;
-#define DECLARE_CLASS(ignore, type) type type##_;
- CODE_EVENTS_TYPE_LIST(DECLARE_CLASS)
-#undef DECLARE_TYPE
- };
-
// Called from events processing thread (Run() method.)
bool ProcessCodeEvent(unsigned* dequeue_order);
bool ProcessTicks(unsigned dequeue_order);
- INLINE(static bool FilterOutCodeCreateEvent(Logger::LogEventsAndTags tag));
-
ProfileGenerator* generator_;
- CpuProfilesCollection* profiles_;
bool running_;
UnboundQueue<CodeEventsContainer> events_buffer_;
SamplingCircularQueue ticks_buffer_;
@@ -204,6 +197,12 @@
class CpuProfiler {
public:
explicit CpuProfiler(Isolate* isolate);
+
+ CpuProfiler(Isolate* isolate,
+ CpuProfilesCollection* test_collection,
+ ProfileGenerator* test_generator,
+ ProfilerEventsProcessor* test_processor);
+
~CpuProfiler();
void StartProfiling(const char* title, bool record_samples = false);
@@ -257,6 +256,7 @@
void StopProcessorIfLastProfile(const char* title);
void StopProcessor();
void ResetProfiles();
+ void LogBuiltins();
Isolate* isolate_;
CpuProfilesCollection* profiles_;
diff --git a/src/d8.gyp b/src/d8.gyp
index ea043dc..47a7cc0 100644
--- a/src/d8.gyp
+++ b/src/d8.gyp
@@ -26,12 +26,13 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
- 'includes': ['../build/common.gypi'],
'variables': {
+ 'v8_code': 1,
'console%': '',
# Enable support for Intel VTune. Supported on ia32/x64 only
'v8_enable_vtunejit%': 0,
},
+ 'includes': ['../build/common.gypi'],
'targets': [
{
'target_name': 'd8',
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index 7787312..88efbe2 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -71,6 +71,13 @@
ScriptName: 1,
ScriptRegExp: 2 };
+// The different types of breakpoint position alignments.
+// Must match BreakPositionAlignment in debug.h.
+Debug.BreakPositionAlignment = {
+ Statement: 0,
+ BreakPosition: 1
+};
+
function ScriptTypeFlag(type) {
return (1 << type);
}
@@ -251,7 +258,7 @@
// script name or script id and the break point is represented as line and
// column.
function ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
- opt_groupId) {
+ opt_groupId, opt_position_alignment) {
this.type_ = type;
if (type == Debug.ScriptBreakPointType.ScriptId) {
this.script_id_ = script_id_or_name;
@@ -265,6 +272,8 @@
this.line_ = opt_line || 0;
this.column_ = opt_column;
this.groupId_ = opt_groupId;
+ this.position_alignment_ = IS_UNDEFINED(opt_position_alignment)
+ ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
this.hit_count_ = 0;
this.active_ = true;
this.condition_ = null;
@@ -276,7 +285,8 @@
//Creates a clone of script breakpoint that is linked to another script.
ScriptBreakPoint.prototype.cloneForOtherScript = function (other_script) {
var copy = new ScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
- other_script.id, this.line_, this.column_, this.groupId_);
+ other_script.id, this.line_, this.column_, this.groupId_,
+ this.position_alignment_);
copy.number_ = next_break_point_number++;
script_break_points.push(copy);
@@ -443,7 +453,9 @@
// Create a break point object and set the break point.
break_point = MakeBreakPoint(position, this);
break_point.setIgnoreCount(this.ignoreCount());
- var actual_position = %SetScriptBreakPoint(script, position, break_point);
+ var actual_position = %SetScriptBreakPoint(script, position,
+ this.position_alignment_,
+ break_point);
if (IS_UNDEFINED(actual_position)) {
actual_position = position;
}
@@ -509,9 +521,11 @@
%Break();
};
-Debug.breakLocations = function(f) {
+Debug.breakLocations = function(f, opt_position_aligment) {
if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
- return %GetBreakLocations(f);
+ var position_aligment = IS_UNDEFINED(opt_position_aligment)
+ ? Debug.BreakPositionAlignment.Statement : opt_position_aligment;
+ return %GetBreakLocations(f, position_aligment);
};
// Returns a Script object. If the parameter is a function the return value
@@ -674,7 +688,8 @@
Debug.setBreakPointByScriptIdAndPosition = function(script_id, position,
- condition, enabled)
+ condition, enabled,
+ opt_position_alignment)
{
break_point = MakeBreakPoint(position);
break_point.setCondition(condition);
@@ -682,10 +697,12 @@
break_point.disable();
}
var scripts = this.scripts();
+ var position_alignment = IS_UNDEFINED(opt_position_alignment)
+ ? Debug.BreakPositionAlignment.Statement : opt_position_alignment;
for (var i = 0; i < scripts.length; i++) {
if (script_id == scripts[i].id) {
break_point.actual_position = %SetScriptBreakPoint(scripts[i], position,
- break_point);
+ position_alignment, break_point);
break;
}
}
@@ -780,11 +797,11 @@
// specified source line and column within that line.
Debug.setScriptBreakPoint = function(type, script_id_or_name,
opt_line, opt_column, opt_condition,
- opt_groupId) {
+ opt_groupId, opt_position_alignment) {
// Create script break point object.
var script_break_point =
new ScriptBreakPoint(type, script_id_or_name, opt_line, opt_column,
- opt_groupId);
+ opt_groupId, opt_position_alignment);
// Assign number to the new script break point and add it.
script_break_point.number_ = next_break_point_number++;
@@ -806,10 +823,12 @@
Debug.setScriptBreakPointById = function(script_id,
opt_line, opt_column,
- opt_condition, opt_groupId) {
+ opt_condition, opt_groupId,
+ opt_position_alignment) {
return this.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId,
script_id, opt_line, opt_column,
- opt_condition, opt_groupId);
+ opt_condition, opt_groupId,
+ opt_position_alignment);
};
@@ -893,11 +912,11 @@
return !!%IsBreakOnException(Debug.ExceptionBreak.Uncaught);
};
-Debug.showBreakPoints = function(f, full) {
+Debug.showBreakPoints = function(f, full, opt_position_alignment) {
if (!IS_FUNCTION(f)) throw new Error('Parameters have wrong types.');
var source = full ? this.scriptSource(f) : this.source(f);
var offset = full ? this.sourcePosition(f) : 0;
- var locations = this.breakLocations(f);
+ var locations = this.breakLocations(f, opt_position_alignment);
if (!locations) return source;
locations.sort(function(x, y) { return x - y; });
var result = "";
diff --git a/src/debug.cc b/src/debug.cc
index efb95a0..07c1a0c 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -235,17 +235,30 @@
// Find the break point closest to the supplied source position.
-void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
+void BreakLocationIterator::FindBreakLocationFromPosition(int position,
+ BreakPositionAlignment alignment) {
// Run through all break points to locate the one closest to the source
// position.
int closest_break_point = 0;
int distance = kMaxInt;
+
while (!Done()) {
+ int next_position;
+ switch (alignment) {
+ case STATEMENT_ALIGNED:
+ next_position = this->statement_position();
+ break;
+ case BREAK_POSITION_ALIGNED:
+ next_position = this->position();
+ break;
+ default:
+ UNREACHABLE();
+ next_position = this->statement_position();
+ }
// Check if this break point is closer that what was previously found.
- if (position <= statement_position() &&
- statement_position() - position < distance) {
+ if (position <= next_position && next_position - position < distance) {
closest_break_point = break_point();
- distance = statement_position() - position;
+ distance = next_position - position;
// Check whether we can't get any closer.
if (distance == 0) break;
}
@@ -1190,7 +1203,7 @@
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
- it.FindBreakLocationFromPosition(*source_position);
+ it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
it.SetBreakPoint(break_point_object);
*source_position = it.position();
@@ -1202,7 +1215,8 @@
bool Debug::SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
- int* source_position) {
+ int* source_position,
+ BreakPositionAlignment alignment) {
HandleScope scope(isolate_);
PrepareForBreakPoints();
@@ -1233,7 +1247,7 @@
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
- it.FindBreakLocationFromPosition(position);
+ it.FindBreakLocationFromPosition(position, alignment);
it.SetBreakPoint(break_point_object);
*source_position = it.position() + shared->start_position();
@@ -1687,7 +1701,8 @@
// Simple function for returning the source positions for active break points.
Handle<Object> Debug::GetSourceBreakLocations(
- Handle<SharedFunctionInfo> shared) {
+ Handle<SharedFunctionInfo> shared,
+ BreakPositionAlignment position_alignment) {
Isolate* isolate = Isolate::Current();
Heap* heap = isolate->heap();
if (!HasDebugInfo(shared)) {
@@ -1705,7 +1720,20 @@
BreakPointInfo* break_point_info =
BreakPointInfo::cast(debug_info->break_points()->get(i));
if (break_point_info->GetBreakPointCount() > 0) {
- locations->set(count++, break_point_info->statement_position());
+ Smi* position;
+ switch (position_alignment) {
+ case STATEMENT_ALIGNED:
+ position = break_point_info->statement_position();
+ break;
+ case BREAK_POSITION_ALIGNED:
+ position = break_point_info->source_position();
+ break;
+ default:
+ UNREACHABLE();
+ position = break_point_info->statement_position();
+ }
+
+ locations->set(count++, position);
}
}
}
diff --git a/src/debug.h b/src/debug.h
index 209d8db..67debc7 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -79,6 +79,14 @@
};
+// The different types of breakpoint position alignments.
+// Must match Debug.BreakPositionAlignment in debug-debugger.js
+enum BreakPositionAlignment {
+ STATEMENT_ALIGNED = 0,
+ BREAK_POSITION_ALIGNED = 1
+};
+
+
// Class for iterating through the break points in a function and changing
// them.
class BreakLocationIterator {
@@ -90,7 +98,8 @@
void Next();
void Next(int count);
void FindBreakLocationFromAddress(Address pc);
- void FindBreakLocationFromPosition(int position);
+ void FindBreakLocationFromPosition(int position,
+ BreakPositionAlignment alignment);
void Reset();
bool Done() const;
void SetBreakPoint(Handle<Object> break_point_object);
@@ -241,7 +250,8 @@
int* source_position);
bool SetBreakPointForScript(Handle<Script> script,
Handle<Object> break_point_object,
- int* source_position);
+ int* source_position,
+ BreakPositionAlignment alignment);
void ClearBreakPoint(Handle<Object> break_point_object);
void ClearAllBreakPoints();
void FloodWithOneShot(Handle<JSFunction> function);
@@ -284,7 +294,8 @@
static Handle<Code> FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode);
static Handle<Object> GetSourceBreakLocations(
- Handle<SharedFunctionInfo> shared);
+ Handle<SharedFunctionInfo> shared,
+ BreakPositionAlignment position_aligment);
// Getter for the debug_context.
inline Handle<Context> debug_context() { return debug_context_; }
diff --git a/src/execution.h b/src/execution.h
index 3cdbf63..c6bf63d 100644
--- a/src/execution.h
+++ b/src/execution.h
@@ -253,7 +253,7 @@
void EnableInterrupts();
void DisableInterrupts();
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
static const uintptr_t kInterruptLimit = V8_UINT64_C(0xfffffffffffffffe);
static const uintptr_t kIllegalLimit = V8_UINT64_C(0xfffffffffffffff8);
#else
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 91186de..b07354a 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -214,6 +214,7 @@
DEFINE_bool(use_gvn, true, "use hydrogen global value numbering")
DEFINE_bool(use_canonicalizing, true, "use hydrogen instruction canonicalizing")
DEFINE_bool(use_inlining, true, "use function inlining")
+DEFINE_bool(use_escape_analysis, false, "use hydrogen escape analysis")
DEFINE_int(max_inlined_source_size, 600,
"maximum source size in bytes considered for a single inlining")
DEFINE_int(max_inlined_nodes, 196,
@@ -234,6 +235,7 @@
DEFINE_bool(trace_range, false, "trace range analysis")
DEFINE_bool(trace_gvn, false, "trace global value numbering")
DEFINE_bool(trace_representation, false, "trace representation types")
+DEFINE_bool(trace_escape_analysis, false, "trace hydrogen escape analysis")
DEFINE_bool(trace_track_allocation_sites, false,
"trace the tracking of allocation sites")
DEFINE_bool(trace_migration, false, "trace object migration")
diff --git a/src/flags.cc b/src/flags.cc
index 282bf20..855e207 100644
--- a/src/flags.cc
+++ b/src/flags.cc
@@ -34,7 +34,7 @@
#include "smart-pointers.h"
#include "string-stream.h"
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
#include "arm/assembler-arm-inl.h"
#endif
@@ -520,7 +520,7 @@
// static
void FlagList::PrintHelp() {
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
CpuFeatures::PrintTarget();
CpuFeatures::Probe();
CpuFeatures::PrintFeatures();
diff --git a/src/frames.cc b/src/frames.cc
index edd5ddd..e883c98 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -423,7 +423,7 @@
Address StackFrame::UnpaddedFP() const {
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
if (!is_optimized()) return fp();
int32_t alignment_state = Memory::int32_at(
fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
diff --git a/src/full-codegen.cc b/src/full-codegen.cc
index 7336261..c1350a1 100644
--- a/src/full-codegen.cc
+++ b/src/full-codegen.cc
@@ -940,6 +940,11 @@
}
+void FullCodeGenerator::EmitDebugBreakInOptimizedCode(CallRuntime* expr) {
+ context()->Plug(handle(Smi::FromInt(0), isolate()));
+}
+
+
void FullCodeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
switch (expr->op()) {
case Token::COMMA:
diff --git a/src/full-codegen.h b/src/full-codegen.h
index dc5ac6a..7e64506 100644
--- a/src/full-codegen.h
+++ b/src/full-codegen.h
@@ -332,7 +332,7 @@
// Helper function to split control flow and avoid a branch to the
// fall-through label if it is set up.
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
void Split(Condition cc,
Register lhs,
const Operand& rhs,
diff --git a/src/gdb-jit.cc b/src/gdb-jit.cc
index dee115c..f4a7c2d 100644
--- a/src/gdb-jit.cc
+++ b/src/gdb-jit.cc
@@ -217,7 +217,7 @@
struct MachOSectionHeader {
char sectname[16];
char segname[16];
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
uint32_t addr;
uint32_t size;
#else
@@ -525,7 +525,7 @@
uint32_t ncmds;
uint32_t sizeofcmds;
uint32_t flags;
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
uint32_t reserved;
#endif
};
@@ -534,7 +534,7 @@
uint32_t cmd;
uint32_t cmdsize;
char segname[16];
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
uint32_t vmaddr;
uint32_t vmsize;
uint32_t fileoff;
@@ -560,11 +560,11 @@
Writer::Slot<MachOHeader> WriteHeader(Writer* w) {
ASSERT(w->position() == 0);
Writer::Slot<MachOHeader> header = w->CreateSlotHere<MachOHeader>();
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
header->magic = 0xFEEDFACEu;
header->cputype = 7; // i386
header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
-#elif defined(V8_TARGET_ARCH_X64)
+#elif V8_TARGET_ARCH_X64
header->magic = 0xFEEDFACFu;
header->cputype = 7 | 0x01000000; // i386 | 64-bit ABI
header->cpusubtype = 3; // CPU_SUBTYPE_I386_ALL
@@ -585,7 +585,7 @@
uintptr_t code_size) {
Writer::Slot<MachOSegmentCommand> cmd =
w->CreateSlotHere<MachOSegmentCommand>();
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
cmd->cmd = LC_SEGMENT_32;
#else
cmd->cmd = LC_SEGMENT_64;
@@ -672,10 +672,10 @@
void WriteHeader(Writer* w) {
ASSERT(w->position() == 0);
Writer::Slot<ELFHeader> header = w->CreateSlotHere<ELFHeader>();
-#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM
const uint8_t ident[16] =
{ 0x7f, 'E', 'L', 'F', 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-#elif defined(V8_TARGET_ARCH_X64)
+#elif V8_TARGET_ARCH_X64
const uint8_t ident[16] =
{ 0x7f, 'E', 'L', 'F', 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0};
#else
@@ -683,14 +683,14 @@
#endif
OS::MemCopy(header->ident, ident, 16);
header->type = 1;
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
header->machine = 3;
-#elif defined(V8_TARGET_ARCH_X64)
+#elif V8_TARGET_ARCH_X64
// Processor identification value for x64 is 62 as defined in
// System V ABI, AMD64 Supplement
// http://www.x86-64.org/documentation/abi.pdf
header->machine = 62;
-#elif defined(V8_TARGET_ARCH_ARM)
+#elif V8_TARGET_ARCH_ARM
// Set to EM_ARM, defined as 40, in "ARM ELF File Format" at
// infocenter.arm.com/help/topic/com.arm.doc.dui0101a/DUI0101A_Elf.pdf
header->machine = 40;
@@ -784,7 +784,7 @@
Binding binding() const {
return static_cast<Binding>(info >> 4);
}
-#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_ARM)
+#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_ARM
struct SerializedLayout {
SerializedLayout(uint32_t name,
uintptr_t value,
@@ -807,7 +807,7 @@
uint8_t other;
uint16_t section;
};
-#elif defined(V8_TARGET_ARCH_X64)
+#elif V8_TARGET_ARCH_X64
struct SerializedLayout {
SerializedLayout(uint32_t name,
uintptr_t value,
@@ -921,7 +921,7 @@
class CodeDescription BASE_EMBEDDED {
public:
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
enum StackState {
POST_RBP_PUSH,
POST_RBP_SET,
@@ -984,7 +984,7 @@
lineinfo_ != NULL;
}
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
uintptr_t GetStackStateStartAddress(StackState state) const {
ASSERT(state < STACK_STATE_MAX);
return stack_state_start_addresses_[state];
@@ -1012,7 +1012,7 @@
GDBJITLineInfo* lineinfo_;
GDBJITInterface::CodeTag tag_;
CompilationInfo* info_;
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
uintptr_t stack_state_start_addresses_[STACK_STATE_MAX];
#endif
};
@@ -1106,13 +1106,13 @@
w->Write<intptr_t>(desc_->CodeStart() + desc_->CodeSize());
Writer::Slot<uint32_t> fb_block_size = w->CreateSlotHere<uint32_t>();
uintptr_t fb_block_start = w->position();
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
w->Write<uint8_t>(DW_OP_reg5); // The frame pointer's here on ia32
-#elif defined(V8_TARGET_ARCH_X64)
+#elif V8_TARGET_ARCH_X64
w->Write<uint8_t>(DW_OP_reg6); // and here on x64.
-#elif defined(V8_TARGET_ARCH_ARM)
+#elif V8_TARGET_ARCH_ARM
UNIMPLEMENTED();
-#elif defined(V8_TARGET_ARCH_MIPS)
+#elif V8_TARGET_ARCH_MIPS
UNIMPLEMENTED();
#else
#error Unsupported target architecture.
@@ -1563,7 +1563,7 @@
};
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
class UnwindInfoSection : public DebugSection {
public:
@@ -1797,7 +1797,7 @@
obj->AddSection(new(zone) DebugAbbrevSection(desc), zone);
obj->AddSection(new(zone) DebugLineSection(desc), zone);
}
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
obj->AddSection(new(zone) UnwindInfoSection(desc), zone);
#endif
}
@@ -2015,7 +2015,7 @@
}
static void AddUnwindInfo(CodeDescription* desc) {
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
if (desc->tag() == GDBJITInterface::FUNCTION) {
// To avoid propagating unwinding information through
// compilation pipeline we use an approximation.
diff --git a/src/globals.h b/src/globals.h
index 573e19a..baacf52 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -105,8 +105,8 @@
// Target architecture detection. This may be set externally. If not, detect
// in the same way as the host architecture, that is, target the native
// environment as presented by the compiler.
-#if !defined(V8_TARGET_ARCH_X64) && !defined(V8_TARGET_ARCH_IA32) && \
- !defined(V8_TARGET_ARCH_ARM) && !defined(V8_TARGET_ARCH_MIPS)
+#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && \
+ !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS
#if defined(_M_X64) || defined(__x86_64__)
#define V8_TARGET_ARCH_X64 1
#elif defined(_M_IX86) || defined(__i386__)
@@ -121,18 +121,16 @@
#endif
// Check for supported combinations of host and target architectures.
-#if defined(V8_TARGET_ARCH_IA32) && !defined(V8_HOST_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32 && !V8_HOST_ARCH_IA32
#error Target architecture ia32 is only supported on ia32 host
#endif
-#if defined(V8_TARGET_ARCH_X64) && !defined(V8_HOST_ARCH_X64)
+#if V8_TARGET_ARCH_X64 && !V8_HOST_ARCH_X64
#error Target architecture x64 is only supported on x64 host
#endif
-#if (defined(V8_TARGET_ARCH_ARM) && \
- !(defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_ARM)))
+#if (V8_TARGET_ARCH_ARM && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_ARM))
#error Target architecture arm is only supported on arm and ia32 host
#endif
-#if (defined(V8_TARGET_ARCH_MIPS) && \
- !(defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_MIPS)))
+#if (V8_TARGET_ARCH_MIPS && !(V8_HOST_ARCH_IA32 || V8_HOST_ARCH_MIPS))
#error Target architecture mips is only supported on mips and ia32 host
#endif
@@ -140,22 +138,22 @@
// Setting USE_SIMULATOR explicitly from the build script will force
// the use of a simulated environment.
#if !defined(USE_SIMULATOR)
-#if (defined(V8_TARGET_ARCH_ARM) && !defined(V8_HOST_ARCH_ARM))
+#if (V8_TARGET_ARCH_ARM && !V8_HOST_ARCH_ARM)
#define USE_SIMULATOR 1
#endif
-#if (defined(V8_TARGET_ARCH_MIPS) && !defined(V8_HOST_ARCH_MIPS))
+#if (V8_TARGET_ARCH_MIPS && !V8_HOST_ARCH_MIPS)
#define USE_SIMULATOR 1
#endif
#endif
// Determine architecture endiannes (we only support little-endian).
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#define V8_TARGET_LITTLE_ENDIAN 1
-#elif defined(V8_TARGET_ARCH_X64)
+#elif V8_TARGET_ARCH_X64
#define V8_TARGET_LITTLE_ENDIAN 1
-#elif defined(V8_TARGET_ARCH_ARM)
+#elif V8_TARGET_ARCH_ARM
#define V8_TARGET_LITTLE_ENDIAN 1
-#elif defined(V8_TARGET_ARCH_MIPS)
+#elif V8_TARGET_ARCH_MIPS
#define V8_TARGET_LITTLE_ENDIAN 1
#else
#error Unknown target architecture endiannes
diff --git a/src/heap.cc b/src/heap.cc
index 6196228..3fac601 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -66,7 +66,7 @@
: isolate_(NULL),
// semispace_size_ should be a power of 2 and old_generation_size_ should be
// a multiple of Page::kPageSize.
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#define LUMP_OF_MEMORY (2 * MB)
code_range_size_(512*MB),
#else
diff --git a/src/heap.h b/src/heap.h
index b3a4205..d254b60 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -1955,7 +1955,7 @@
int scan_on_scavenge_pages_;
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
static const int kMaxObjectSizeInNewSpace = 1024*KB;
#else
static const int kMaxObjectSizeInNewSpace = 512*KB;
@@ -2952,6 +2952,10 @@
for (int i = 0; i < kNumberOfCaches; ++i) caches_[i] = NULL;
}
+ ~TranscendentalCache() {
+ for (int i = 0; i < kNumberOfCaches; ++i) delete caches_[i];
+ }
+
// Used to create an external reference.
inline Address cache_array_address();
diff --git a/src/hydrogen-escape-analysis.cc b/src/hydrogen-escape-analysis.cc
new file mode 100644
index 0000000..e852fb8
--- /dev/null
+++ b/src/hydrogen-escape-analysis.cc
@@ -0,0 +1,66 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-escape-analysis.h"
+
+namespace v8 {
+namespace internal {
+
+
+void HEscapeAnalysisPhase::CollectIfNoEscapingUses(HInstruction* instr) {
+ for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) {
+ HValue* use = it.value();
+ if (use->HasEscapingOperandAt(it.index())) {
+ if (FLAG_trace_escape_analysis) {
+ PrintF("#%d (%s) escapes through #%d (%s) @%d\n", instr->id(),
+ instr->Mnemonic(), use->id(), use->Mnemonic(), it.index());
+ }
+ return;
+ }
+ }
+ if (FLAG_trace_escape_analysis) {
+ PrintF("#%d (%s) is being captured\n", instr->id(), instr->Mnemonic());
+ }
+ captured_.Add(instr, zone());
+}
+
+
+void HEscapeAnalysisPhase::CollectCapturedValues() {
+ int block_count = graph()->blocks()->length();
+ for (int i = 0; i < block_count; ++i) {
+ HBasicBlock* block = graph()->blocks()->at(i);
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
+ if (instr->IsAllocate() || instr->IsAllocateObject()) {
+ CollectIfNoEscapingUses(instr);
+ }
+ }
+ }
+}
+
+
+} } // namespace v8::internal
diff --git a/src/hydrogen-escape-analysis.h b/src/hydrogen-escape-analysis.h
new file mode 100644
index 0000000..6ba6e82
--- /dev/null
+++ b/src/hydrogen-escape-analysis.h
@@ -0,0 +1,57 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_ESCAPE_ANALYSIS_H_
+#define V8_HYDROGEN_ESCAPE_ANALYSIS_H_
+
+#include "allocation.h"
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+class HEscapeAnalysisPhase : public HPhase {
+ public:
+ explicit HEscapeAnalysisPhase(HGraph* graph)
+ : HPhase("H_Escape analysis", graph), captured_(0, zone()) { }
+
+ void Run() {
+ CollectCapturedValues();
+ }
+
+ private:
+ void CollectCapturedValues();
+ void CollectIfNoEscapingUses(HInstruction* instr);
+
+ ZoneList<HValue*> captured_;
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_HYDROGEN_ESCAPE_ANALYSIS_H_
diff --git a/src/hydrogen-gvn.cc b/src/hydrogen-gvn.cc
index a277da8..7ea2f16 100644
--- a/src/hydrogen-gvn.cc
+++ b/src/hydrogen-gvn.cc
@@ -394,17 +394,16 @@
for (int i = graph()->blocks()->length() - 1; i >= 0; --i) {
// Compute side effects for the block.
HBasicBlock* block = graph()->blocks()->at(i);
- HInstruction* instr = block->first();
int id = block->block_id();
GVNFlagSet side_effects;
- while (instr != NULL) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
side_effects.Add(instr->ChangesFlags());
if (instr->IsSoftDeoptimize()) {
block_side_effects_[id].RemoveAll();
side_effects.RemoveAll();
break;
}
- instr = instr->next();
}
block_side_effects_[id].Add(side_effects);
diff --git a/src/hydrogen-infer-representation.cc b/src/hydrogen-infer-representation.cc
index 8439ad8..95c3412 100644
--- a/src/hydrogen-infer-representation.cc
+++ b/src/hydrogen-infer-representation.cc
@@ -131,10 +131,9 @@
AddToWorklist(phis->at(j));
}
- HInstruction* current = block->first();
- while (current != NULL) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* current = it.Current();
AddToWorklist(current);
- current = current->next();
}
}
@@ -156,8 +155,8 @@
phi->ChangeRepresentation(Representation::Tagged());
}
}
- for (HInstruction* current = block->first();
- current != NULL; current = current->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* current = it.Current();
if (current->representation().IsNone() &&
current->CheckFlag(HInstruction::kFlexibleRepresentation)) {
if (current->CheckFlag(HInstruction::kCannotBeTagged)) {
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 98fa93f..932fd47 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -1566,7 +1566,7 @@
HValue* new_right =
LChunkBuilder::SimplifiedDivisorForMathFloorOfDiv(right);
if (new_right == NULL &&
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
CpuFeatures::IsSupported(SUDIV) &&
#endif
hdiv->observed_input_representation(2).IsSmiOrInteger32()) {
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index bb74687..ed6ab15 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -1062,6 +1062,9 @@
void RemoveLastAddedRange();
void ComputeInitialRange(Zone* zone);
+ // Escape analysis helpers.
+ virtual bool HasEscapingOperandAt(int index) { return true; }
+
// Representation helpers.
virtual Representation observed_input_representation(int index) {
return Representation::None();
@@ -1433,6 +1436,7 @@
HValue* value() { return OperandAt(0); }
+ virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
@@ -1892,6 +1896,7 @@
virtual int OperandCount() { return values_.length(); }
virtual HValue* OperandAt(int index) const { return values_[index]; }
+ virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
@@ -2801,6 +2806,7 @@
return check_map;
}
+ virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
}
@@ -3228,6 +3234,7 @@
virtual int OperandCount() { return values_.length(); }
virtual HValue* OperandAt(int index) const { return values_[index]; }
+ virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::None();
}
@@ -5431,6 +5438,7 @@
HObjectAccess access() const { return access_; }
Representation field_representation() const { return representation_; }
+ virtual bool HasEscapingOperandAt(int index) { return false; }
virtual Representation RequiredInputRepresentation(int index) {
return Representation::Tagged();
}
@@ -5763,6 +5771,7 @@
DECLARE_CONCRETE_INSTRUCTION(StoreNamedField)
+ virtual bool HasEscapingOperandAt(int index) { return index == 1; }
virtual Representation RequiredInputRepresentation(int index) {
if (FLAG_track_double_fields &&
index == 1 && field_representation_.IsDouble()) {
@@ -5895,6 +5904,7 @@
}
}
+ virtual bool HasEscapingOperandAt(int index) { return index != 0; }
virtual Representation RequiredInputRepresentation(int index) {
// kind_fast: tagged[int32] = tagged
// kind_double: tagged[int32] = double
diff --git a/src/hydrogen-uint32-analysis.cc b/src/hydrogen-uint32-analysis.cc
new file mode 100644
index 0000000..67219f5
--- /dev/null
+++ b/src/hydrogen-uint32-analysis.cc
@@ -0,0 +1,231 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "hydrogen-uint32-analysis.h"
+
+namespace v8 {
+namespace internal {
+
+
+bool HUint32AnalysisPhase::IsSafeUint32Use(HValue* val, HValue* use) {
+ // Operations that operate on bits are safe.
+ if (use->IsBitwise() ||
+ use->IsShl() ||
+ use->IsSar() ||
+ use->IsShr() ||
+ use->IsBitNot()) {
+ return true;
+ } else if (use->IsChange() || use->IsSimulate()) {
+ // Conversions and deoptimization have special support for unt32.
+ return true;
+ } else if (use->IsStoreKeyed()) {
+ HStoreKeyed* store = HStoreKeyed::cast(use);
+ if (store->is_external()) {
+ // Storing a value into an external integer array is a bit level
+ // operation.
+ if (store->value() == val) {
+ // Clamping or a conversion to double should have beed inserted.
+ ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
+ ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
+ ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+// Iterate over all uses and verify that they are uint32 safe: either don't
+// distinguish between int32 and uint32 due to their bitwise nature or
+// have special support for uint32 values.
+// Encountered phis are optimistically treated as safe uint32 uses,
+// marked with kUint32 flag and collected in the phis_ list. A separate
+// pass will be performed later by UnmarkUnsafePhis to clear kUint32 from
+// phis that are not actually uint32-safe (it requires fix point iteration).
+bool HUint32AnalysisPhase::Uint32UsesAreSafe(HValue* uint32val) {
+ bool collect_phi_uses = false;
+ for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
+ HValue* use = it.value();
+
+ if (use->IsPhi()) {
+ if (!use->CheckFlag(HInstruction::kUint32)) {
+ // There is a phi use of this value from a phi that is not yet
+ // collected in phis_ array. Separate pass is required.
+ collect_phi_uses = true;
+ }
+
+ // Optimistically treat phis as uint32 safe.
+ continue;
+ }
+
+ if (!IsSafeUint32Use(uint32val, use)) {
+ return false;
+ }
+ }
+
+ if (collect_phi_uses) {
+ for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
+ HValue* use = it.value();
+
+ // There is a phi use of this value from a phi that is not yet
+ // collected in phis_ array. Separate pass is required.
+ if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) {
+ use->SetFlag(HInstruction::kUint32);
+ phis_.Add(HPhi::cast(use), zone());
+ }
+ }
+ }
+
+ return true;
+}
+
+
+// Check if all operands to the given phi are marked with kUint32 flag.
+bool HUint32AnalysisPhase::CheckPhiOperands(HPhi* phi) {
+ if (!phi->CheckFlag(HInstruction::kUint32)) {
+ // This phi is not uint32 safe. No need to check operands.
+ return false;
+ }
+
+ for (int j = 0; j < phi->OperandCount(); j++) {
+ HValue* operand = phi->OperandAt(j);
+ if (!operand->CheckFlag(HInstruction::kUint32)) {
+ // Lazily mark constants that fit into uint32 range with kUint32 flag.
+ if (operand->IsInteger32Constant() &&
+ operand->GetInteger32Constant() >= 0) {
+ operand->SetFlag(HInstruction::kUint32);
+ continue;
+ }
+
+ // This phi is not safe, some operands are not uint32 values.
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+// Remove kUint32 flag from the phi itself and its operands. If any operand
+// was a phi marked with kUint32 place it into a worklist for
+// transitive clearing of kUint32 flag.
+void HUint32AnalysisPhase::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) {
+ phi->ClearFlag(HInstruction::kUint32);
+ for (int j = 0; j < phi->OperandCount(); j++) {
+ HValue* operand = phi->OperandAt(j);
+ if (operand->CheckFlag(HInstruction::kUint32)) {
+ operand->ClearFlag(HInstruction::kUint32);
+ if (operand->IsPhi()) {
+ worklist->Add(HPhi::cast(operand), zone());
+ }
+ }
+ }
+}
+
+
+void HUint32AnalysisPhase::UnmarkUnsafePhis() {
+ // No phis were collected. Nothing to do.
+ if (phis_.length() == 0) return;
+
+ // Worklist used to transitively clear kUint32 from phis that
+ // are used as arguments to other phis.
+ ZoneList<HPhi*> worklist(phis_.length(), zone());
+
+ // Phi can be used as a uint32 value if and only if
+ // all its operands are uint32 values and all its
+ // uses are uint32 safe.
+
+ // Iterate over collected phis and unmark those that
+ // are unsafe. When unmarking phi unmark its operands
+ // and add it to the worklist if it is a phi as well.
+ // Phis that are still marked as safe are shifted down
+ // so that all safe phis form a prefix of the phis_ array.
+ int phi_count = 0;
+ for (int i = 0; i < phis_.length(); i++) {
+ HPhi* phi = phis_[i];
+
+ if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) {
+ phis_[phi_count++] = phi;
+ } else {
+ UnmarkPhi(phi, &worklist);
+ }
+ }
+
+ // Now phis array contains only those phis that have safe
+ // non-phi uses. Start transitively clearing kUint32 flag
+ // from phi operands of discovered non-safe phis until
+ // only safe phis are left.
+ while (!worklist.is_empty()) {
+ while (!worklist.is_empty()) {
+ HPhi* phi = worklist.RemoveLast();
+ UnmarkPhi(phi, &worklist);
+ }
+
+ // Check if any operands to safe phis were unmarked
+ // turning a safe phi into unsafe. The same value
+ // can flow into several phis.
+ int new_phi_count = 0;
+ for (int i = 0; i < phi_count; i++) {
+ HPhi* phi = phis_[i];
+
+ if (CheckPhiOperands(phi)) {
+ phis_[new_phi_count++] = phi;
+ } else {
+ UnmarkPhi(phi, &worklist);
+ }
+ }
+ phi_count = new_phi_count;
+ }
+}
+
+
+void HUint32AnalysisPhase::Run() {
+ if (!graph()->has_uint32_instructions()) return;
+
+ ZoneList<HInstruction*>* uint32_instructions = graph()->uint32_instructions();
+ for (int i = 0; i < uint32_instructions->length(); ++i) {
+ // Analyze instruction and mark it with kUint32 if all
+ // its uses are uint32 safe.
+ HInstruction* current = uint32_instructions->at(i);
+ if (current->IsLinked() &&
+ current->representation().IsInteger32() &&
+ Uint32UsesAreSafe(current)) {
+ current->SetFlag(HInstruction::kUint32);
+ }
+ }
+
+ // Some phis might have been optimistically marked with kUint32 flag.
+ // Remove this flag from those phis that are unsafe and propagate
+ // this information transitively potentially clearing kUint32 flag
+ // from some non-phi operations that are used as operands to unsafe phis.
+ UnmarkUnsafePhis();
+}
+
+
+} } // namespace v8::internal
diff --git a/src/hydrogen-uint32-analysis.h b/src/hydrogen-uint32-analysis.h
new file mode 100644
index 0000000..59739d1
--- /dev/null
+++ b/src/hydrogen-uint32-analysis.h
@@ -0,0 +1,59 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_HYDROGEN_UINT32_ANALYSIS_H_
+#define V8_HYDROGEN_UINT32_ANALYSIS_H_
+
+#include "hydrogen.h"
+
+namespace v8 {
+namespace internal {
+
+
+// Discover instructions that can be marked with kUint32 flag allowing
+// them to produce full range uint32 values.
+class HUint32AnalysisPhase : public HPhase {
+ public:
+ explicit HUint32AnalysisPhase(HGraph* graph)
+ : HPhase("H_Compute safe UInt32 operations", graph), phis_(4, zone()) { }
+
+ void Run();
+
+ private:
+ INLINE(bool IsSafeUint32Use(HValue* val, HValue* use));
+ INLINE(bool Uint32UsesAreSafe(HValue* uint32val));
+ INLINE(bool CheckPhiOperands(HPhi* phi));
+ INLINE(void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist));
+ INLINE(void UnmarkUnsafePhis());
+
+ ZoneList<HPhi*> phis_;
+};
+
+
+} } // namespace v8::internal
+
+#endif // V8_HYDROGEN_UINT32_ANALYSIS_H_
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index d3b9aa8..432a6bc 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -26,7 +26,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "hydrogen.h"
-#include "hydrogen-gvn.h"
#include <algorithm>
@@ -35,7 +34,10 @@
#include "full-codegen.h"
#include "hashmap.h"
#include "hydrogen-environment-liveness.h"
+#include "hydrogen-escape-analysis.h"
#include "hydrogen-infer-representation.h"
+#include "hydrogen-gvn.h"
+#include "hydrogen-uint32-analysis.h"
#include "lithium-allocator.h"
#include "parser.h"
#include "scopeinfo.h"
@@ -2008,10 +2010,8 @@
DisallowHeapAllocation no_gc;
ASSERT(!isolate()->optimizing_compiler_thread()->IsOptimizerThread());
for (int i = 0; i < blocks()->length(); ++i) {
- for (HInstruction* instr = blocks()->at(i)->first();
- instr != NULL;
- instr = instr->next()) {
- instr->FinalizeUniqueValueId();
+ for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
+ it.Current()->FinalizeUniqueValueId();
}
}
}
@@ -2023,24 +2023,22 @@
// We must be careful not to set the flag unnecessarily, because GVN
// cannot identify two instructions when their flag value differs.
for (int i = 0; i < blocks()->length(); ++i) {
- HInstruction* instr = blocks()->at(i)->first();
- while (instr != NULL) {
+ for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
if (instr->IsArithmeticBinaryOperation() &&
instr->representation().IsInteger32() &&
instr->HasAtLeastOneUseWithFlagAndNoneWithout(
HInstruction::kTruncatingToInt32)) {
instr->SetFlag(HInstruction::kAllUsesTruncatingToInt32);
}
- instr = instr->next();
}
}
// Perform actual Canonicalization pass.
for (int i = 0; i < blocks()->length(); ++i) {
- HInstruction* instr = blocks()->at(i)->first();
- while (instr != NULL) {
+ for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
HValue* value = instr->Canonicalize();
if (value != instr) instr->DeleteAndReplaceWith(value);
- instr = instr->next();
}
}
}
@@ -2415,8 +2413,8 @@
}
}
if (all_predecessors_deoptimizing) nullify = true;
- for (HInstruction* instr = block->first(); instr != NULL;
- instr = instr->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
// Leave the basic structure of the graph intact.
if (instr->IsBlockEntry()) continue;
if (instr->IsControlInstruction()) continue;
@@ -2628,10 +2626,8 @@
}
// Go through all instructions of the current block.
- HInstruction* instr = block->first();
- while (instr != block->end()) {
- InferRange(instr);
- instr = instr->next();
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ InferRange(it.Current());
}
// Continue analysis in all dominated blocks.
@@ -2758,13 +2754,11 @@
HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge();
HBasicBlock* dominator = back_edge;
while (true) {
- HInstruction* instr = dominator->first();
- while (instr != NULL) {
- if (instr->IsCall()) {
+ for (HInstructionIterator it(dominator); !it.Done(); it.Advance()) {
+ if (it.Current()->IsCall()) {
block->loop_information()->stack_check()->Eliminate();
break;
}
- instr = instr->next();
}
// Done when the loop header is processed.
@@ -2788,8 +2782,8 @@
// Nasty heuristic: Never remove the first simulate in a block. This
// just so happens to have a beneficial effect on register allocation.
bool first = true;
- for (HInstruction* current = block->first();
- current != NULL; current = current->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* current = it.Current();
if (current->IsLeaveInlined()) {
// Never fold simulates from inlined environments into simulates
// in the outer environment.
@@ -2856,10 +2850,8 @@
phis->at(j)->UpdateInferredType();
}
- HInstruction* current = block->first();
- while (current != NULL) {
- current->UpdateInferredType();
- current = current->next();
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ it.Current()->UpdateInferredType();
}
if (block->IsLoopHeader()) {
@@ -3087,235 +3079,12 @@
}
-// Discover instructions that can be marked with kUint32 flag allowing
-// them to produce full range uint32 values.
-class Uint32Analysis BASE_EMBEDDED {
- public:
- explicit Uint32Analysis(Zone* zone) : zone_(zone), phis_(4, zone) { }
-
- void Analyze(HInstruction* current);
-
- void UnmarkUnsafePhis();
-
- private:
- bool IsSafeUint32Use(HValue* val, HValue* use);
- bool Uint32UsesAreSafe(HValue* uint32val);
- bool CheckPhiOperands(HPhi* phi);
- void UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist);
-
- Zone* zone_;
- ZoneList<HPhi*> phis_;
-};
-
-
-bool Uint32Analysis::IsSafeUint32Use(HValue* val, HValue* use) {
- // Operations that operatate on bits are safe.
- if (use->IsBitwise() ||
- use->IsShl() ||
- use->IsSar() ||
- use->IsShr() ||
- use->IsBitNot()) {
- return true;
- } else if (use->IsChange() || use->IsSimulate()) {
- // Conversions and deoptimization have special support for unt32.
- return true;
- } else if (use->IsStoreKeyed()) {
- HStoreKeyed* store = HStoreKeyed::cast(use);
- if (store->is_external()) {
- // Storing a value into an external integer array is a bit level
- // operation.
- if (store->value() == val) {
- // Clamping or a conversion to double should have beed inserted.
- ASSERT(store->elements_kind() != EXTERNAL_PIXEL_ELEMENTS);
- ASSERT(store->elements_kind() != EXTERNAL_FLOAT_ELEMENTS);
- ASSERT(store->elements_kind() != EXTERNAL_DOUBLE_ELEMENTS);
- return true;
- }
- }
- }
-
- return false;
-}
-
-
-// Iterate over all uses and verify that they are uint32 safe: either don't
-// distinguish between int32 and uint32 due to their bitwise nature or
-// have special support for uint32 values.
-// Encountered phis are optimisitically treated as safe uint32 uses,
-// marked with kUint32 flag and collected in the phis_ list. A separate
-// path will be performed later by UnmarkUnsafePhis to clear kUint32 from
-// phis that are not actually uint32-safe (it requries fix point iteration).
-bool Uint32Analysis::Uint32UsesAreSafe(HValue* uint32val) {
- bool collect_phi_uses = false;
- for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
- HValue* use = it.value();
-
- if (use->IsPhi()) {
- if (!use->CheckFlag(HInstruction::kUint32)) {
- // There is a phi use of this value from a phis that is not yet
- // collected in phis_ array. Separate pass is required.
- collect_phi_uses = true;
- }
-
- // Optimistically treat phis as uint32 safe.
- continue;
- }
-
- if (!IsSafeUint32Use(uint32val, use)) {
- return false;
- }
- }
-
- if (collect_phi_uses) {
- for (HUseIterator it(uint32val->uses()); !it.Done(); it.Advance()) {
- HValue* use = it.value();
-
- // There is a phi use of this value from a phis that is not yet
- // collected in phis_ array. Separate pass is required.
- if (use->IsPhi() && !use->CheckFlag(HInstruction::kUint32)) {
- use->SetFlag(HInstruction::kUint32);
- phis_.Add(HPhi::cast(use), zone_);
- }
- }
- }
-
- return true;
-}
-
-
-// Analyze instruction and mark it with kUint32 if all its uses are uint32
-// safe.
-void Uint32Analysis::Analyze(HInstruction* current) {
- if (Uint32UsesAreSafe(current)) current->SetFlag(HInstruction::kUint32);
-}
-
-
-// Check if all operands to the given phi are marked with kUint32 flag.
-bool Uint32Analysis::CheckPhiOperands(HPhi* phi) {
- if (!phi->CheckFlag(HInstruction::kUint32)) {
- // This phi is not uint32 safe. No need to check operands.
- return false;
- }
-
- for (int j = 0; j < phi->OperandCount(); j++) {
- HValue* operand = phi->OperandAt(j);
- if (!operand->CheckFlag(HInstruction::kUint32)) {
- // Lazyly mark constants that fit into uint32 range with kUint32 flag.
- if (operand->IsInteger32Constant() &&
- operand->GetInteger32Constant() >= 0) {
- operand->SetFlag(HInstruction::kUint32);
- continue;
- }
-
- // This phi is not safe, some operands are not uint32 values.
- return false;
- }
- }
-
- return true;
-}
-
-
-// Remove kUint32 flag from the phi itself and its operands. If any operand
-// was a phi marked with kUint32 place it into a worklist for
-// transitive clearing of kUint32 flag.
-void Uint32Analysis::UnmarkPhi(HPhi* phi, ZoneList<HPhi*>* worklist) {
- phi->ClearFlag(HInstruction::kUint32);
- for (int j = 0; j < phi->OperandCount(); j++) {
- HValue* operand = phi->OperandAt(j);
- if (operand->CheckFlag(HInstruction::kUint32)) {
- operand->ClearFlag(HInstruction::kUint32);
- if (operand->IsPhi()) {
- worklist->Add(HPhi::cast(operand), zone_);
- }
- }
- }
-}
-
-
-void Uint32Analysis::UnmarkUnsafePhis() {
- // No phis were collected. Nothing to do.
- if (phis_.length() == 0) return;
-
- // Worklist used to transitively clear kUint32 from phis that
- // are used as arguments to other phis.
- ZoneList<HPhi*> worklist(phis_.length(), zone_);
-
- // Phi can be used as a uint32 value if and only if
- // all its operands are uint32 values and all its
- // uses are uint32 safe.
-
- // Iterate over collected phis and unmark those that
- // are unsafe. When unmarking phi unmark its operands
- // and add it to the worklist if it is a phi as well.
- // Phis that are still marked as safe are shifted down
- // so that all safe phis form a prefix of the phis_ array.
- int phi_count = 0;
- for (int i = 0; i < phis_.length(); i++) {
- HPhi* phi = phis_[i];
-
- if (CheckPhiOperands(phi) && Uint32UsesAreSafe(phi)) {
- phis_[phi_count++] = phi;
- } else {
- UnmarkPhi(phi, &worklist);
- }
- }
-
- // Now phis array contains only those phis that have safe
- // non-phi uses. Start transitively clearing kUint32 flag
- // from phi operands of discovered non-safe phies until
- // only safe phies are left.
- while (!worklist.is_empty()) {
- while (!worklist.is_empty()) {
- HPhi* phi = worklist.RemoveLast();
- UnmarkPhi(phi, &worklist);
- }
-
- // Check if any operands to safe phies were unmarked
- // turning a safe phi into unsafe. The same value
- // can flow into several phis.
- int new_phi_count = 0;
- for (int i = 0; i < phi_count; i++) {
- HPhi* phi = phis_[i];
-
- if (CheckPhiOperands(phi)) {
- phis_[new_phi_count++] = phi;
- } else {
- UnmarkPhi(phi, &worklist);
- }
- }
- phi_count = new_phi_count;
- }
-}
-
-
-void HGraph::ComputeSafeUint32Operations() {
- HPhase phase("H_Compute safe UInt32 operations", this);
- if (uint32_instructions_ == NULL) return;
-
- Uint32Analysis analysis(zone());
- for (int i = 0; i < uint32_instructions_->length(); ++i) {
- HInstruction* current = uint32_instructions_->at(i);
- if (current->IsLinked() && current->representation().IsInteger32()) {
- analysis.Analyze(current);
- }
- }
-
- // Some phis might have been optimistically marked with kUint32 flag.
- // Remove this flag from those phis that are unsafe and propagate
- // this information transitively potentially clearing kUint32 flag
- // from some non-phi operations that are used as operands to unsafe phis.
- analysis.UnmarkUnsafePhis();
-}
-
-
void HGraph::ComputeMinusZeroChecks() {
HPhase phase("H_Compute minus zero checks", this);
BitVector visited(GetMaximumValueID(), zone());
for (int i = 0; i < blocks_.length(); ++i) {
- for (HInstruction* current = blocks_[i]->first();
- current != NULL;
- current = current->next()) {
+ for (HInstructionIterator it(blocks_[i]); !it.Done(); it.Advance()) {
+ HInstruction* current = it.Current();
if (current->IsChange()) {
HChange* change = HChange::cast(current);
// Propagate flags for negative zero checks upwards from conversions
@@ -3821,15 +3590,17 @@
// Must be performed before canonicalization to ensure that Canonicalize
// will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
// zero.
- if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations();
+ if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
if (FLAG_use_canonicalizing) Canonicalize();
+ if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
+
if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
if (FLAG_use_range) {
- HRangeAnalysis rangeAnalysis(this);
- rangeAnalysis.Analyze();
+ HRangeAnalysis range_analysis(this);
+ range_analysis.Analyze();
}
ComputeMinusZeroChecks();
@@ -3861,7 +3632,8 @@
ASSERT(!phi->IsInformativeDefinition());
}
- for (HInstruction* i = block->first(); i != NULL; i = i->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
i->AddInformativeDefinitions();
i->SetFlag(HValue::kIDefsProcessingDone);
i->UpdateRedefinedUsesWhileSettingUpInformativeDefinitions();
@@ -3879,7 +3651,8 @@
SetupInformativeDefinitionsRecursively(block->dominated_blocks()->at(i));
}
- for (HInstruction* i = block->first(); i != NULL; i = i->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
if (i->IsBoundsCheck()) {
HBoundsCheck* check = HBoundsCheck::cast(i);
check->ApplyIndexChange();
@@ -4182,7 +3955,8 @@
BoundsCheckTable* table) {
BoundsCheckBbData* bb_data_list = NULL;
- for (HInstruction* i = bb->first(); i != NULL; i = i->next()) {
+ for (HInstructionIterator it(bb); !it.Done(); it.Advance()) {
+ HInstruction* i = it.Current();
if (!i->IsBoundsCheck()) continue;
HBoundsCheck* check = HBoundsCheck::cast(i);
@@ -4304,9 +4078,8 @@
void HGraph::DehoistSimpleArrayIndexComputations() {
HPhase phase("H_Dehoist index computations", this);
for (int i = 0; i < blocks()->length(); ++i) {
- for (HInstruction* instr = blocks()->at(i)->first();
- instr != NULL;
- instr = instr->next()) {
+ for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
ArrayInstructionInterface* array_instruction = NULL;
if (instr->IsLoadKeyed()) {
HLoadKeyed* op = HLoadKeyed::cast(instr);
@@ -4336,9 +4109,8 @@
// Mark initial root instructions for dead code elimination.
for (int i = 0; i < blocks()->length(); ++i) {
HBasicBlock* block = blocks()->at(i);
- for (HInstruction* instr = block->first();
- instr != NULL;
- instr = instr->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
if (instr->CannotBeEliminated()) MarkLive(NULL, instr, &worklist);
}
for (int j = 0; j < block->phis()->length(); j++) {
@@ -4384,9 +4156,8 @@
// Remove any instruction not marked kIsLive.
for (int i = 0; i < blocks()->length(); ++i) {
HBasicBlock* block = blocks()->at(i);
- for (HInstruction* instr = block->first();
- instr != NULL;
- instr = instr->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instr = it.Current();
if (!instr->CheckFlag(HValue::kIsLive)) {
// Instruction has not been marked live; assume it is dead and remove.
// TODO(titzer): we don't remove constants because some special ones
@@ -4431,9 +4202,8 @@
}
#endif
- for (HInstruction* instruction = block->first();
- instruction != NULL;
- instruction = instruction->next()) {
+ for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
if (instruction->ActualValue() != instruction) {
ASSERT(instruction->IsInformativeDefinition());
if (instruction->IsPurelyInformativeDefinition()) {
@@ -7632,7 +7402,7 @@
return false;
}
-#if !defined(V8_TARGET_ARCH_IA32)
+#if !V8_TARGET_ARCH_IA32
// Target must be able to use caller's context.
CompilationInfo* outer_info = current_info();
if (target->context() != outer_info->closure()->context() ||
@@ -7781,7 +7551,7 @@
undefined,
function_state()->inlining_kind(),
undefined_receiver);
-#ifdef V8_TARGET_ARCH_IA32
+#if V8_TARGET_ARCH_IA32
// IA32 only, overwrite the caller's context in the deoptimization
// environment with the correct one.
//
@@ -9127,7 +8897,7 @@
HValue* context = environment()->LookupContext();
Handle<Type> left_type = expr->left()->lower_type();
Handle<Type> right_type = expr->right()->lower_type();
- Handle<Type> result_type = expr->lower_type();
+ Handle<Type> result_type = expr->result_type();
Maybe<int> fixed_right_arg = expr->fixed_right_arg();
Representation left_rep = ToRepresentation(left_type);
Representation right_rep = ToRepresentation(right_type);
@@ -10635,6 +10405,13 @@
}
+void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
+ CallRuntime* call) {
+ AddInstruction(new(zone()) HDebugBreak());
+ return ast_context()->ReturnValue(graph()->GetConstant0());
+}
+
+
#undef CHECK_BAILOUT
#undef CHECK_ALIVE
@@ -11045,8 +10822,8 @@
{
Tag HIR_tag(this, "HIR");
- HInstruction* instruction = current->first();
- while (instruction != NULL) {
+ for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
+ HInstruction* instruction = it.Current();
int bci = 0;
int uses = instruction->UseCount();
PrintIndent();
@@ -11055,7 +10832,6 @@
trace_.Add(" ");
instruction->PrintTo(&trace_);
trace_.Add(" <|@\n");
- instruction = instruction->next();
}
}
diff --git a/src/hydrogen.h b/src/hydrogen.h
index 7442b5f..3ea3262 100644
--- a/src/hydrogen.h
+++ b/src/hydrogen.h
@@ -230,6 +230,19 @@
};
+class HInstructionIterator BASE_EMBEDDED {
+ public:
+ explicit HInstructionIterator(HBasicBlock* block) : instr_(block->first()) { }
+
+ bool Done() { return instr_ == NULL; }
+ HInstruction* Current() { return instr_; }
+ void Advance() { instr_ = instr_->next(); }
+
+ private:
+ HInstruction* instr_;
+};
+
+
class HLoopInformation: public ZoneObject {
public:
HLoopInformation(HBasicBlock* loop_header, Zone* zone)
@@ -283,7 +296,6 @@
void InsertRepresentationChanges();
void MarkDeoptimizeOnUndefined();
void ComputeMinusZeroChecks();
- void ComputeSafeUint32Operations();
bool ProcessArgumentsObject();
void EliminateRedundantPhis();
void Canonicalize();
@@ -416,7 +428,18 @@
return depends_on_empty_array_proto_elements_;
}
+ bool has_uint32_instructions() {
+ ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
+ return uint32_instructions_ != NULL;
+ }
+
+ ZoneList<HInstruction*>* uint32_instructions() {
+ ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
+ return uint32_instructions_;
+ }
+
void RecordUint32Instruction(HInstruction* instr) {
+ ASSERT(uint32_instructions_ == NULL || !uint32_instructions_->is_empty());
if (uint32_instructions_ == NULL) {
uint32_instructions_ = new(zone()) ZoneList<HInstruction*>(4, zone());
}
diff --git a/src/ia32/assembler-ia32.cc b/src/ia32/assembler-ia32.cc
index c0b2abd..7bb643a 100644
--- a/src/ia32/assembler-ia32.cc
+++ b/src/ia32/assembler-ia32.cc
@@ -36,7 +36,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "disassembler.h"
#include "macro-assembler.h"
diff --git a/src/ia32/builtins-ia32.cc b/src/ia32/builtins-ia32.cc
index 93400ae..8aa6e4a 100644
--- a/src/ia32/builtins-ia32.cc
+++ b/src/ia32/builtins-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "codegen.h"
#include "deoptimizer.h"
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 8cd4685..29a4be2 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "bootstrapper.h"
#include "code-stubs.h"
diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
index d562238..da32c50 100644
--- a/src/ia32/codegen-ia32.cc
+++ b/src/ia32/codegen-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "codegen.h"
#include "heap.h"
diff --git a/src/ia32/cpu-ia32.cc b/src/ia32/cpu-ia32.cc
index 2d83cab..77ff169 100644
--- a/src/ia32/cpu-ia32.cc
+++ b/src/ia32/cpu-ia32.cc
@@ -33,7 +33,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "cpu.h"
#include "macro-assembler.h"
diff --git a/src/ia32/debug-ia32.cc b/src/ia32/debug-ia32.cc
index a4c6bcc..db1d5a6 100644
--- a/src/ia32/debug-ia32.cc
+++ b/src/ia32/debug-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "codegen.h"
#include "debug.h"
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc
index 16befa9..6af2445 100644
--- a/src/ia32/deoptimizer-ia32.cc
+++ b/src/ia32/deoptimizer-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "codegen.h"
#include "deoptimizer.h"
diff --git a/src/ia32/disasm-ia32.cc b/src/ia32/disasm-ia32.cc
index 9eb0d29..14e5800 100644
--- a/src/ia32/disasm-ia32.cc
+++ b/src/ia32/disasm-ia32.cc
@@ -31,7 +31,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "disasm.h"
diff --git a/src/ia32/frames-ia32.cc b/src/ia32/frames-ia32.cc
index 61d6876..5570811 100644
--- a/src/ia32/frames-ia32.cc
+++ b/src/ia32/frames-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "assembler.h"
#include "assembler-ia32.h"
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
index d04fdd4..cf3132d 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "code-stubs.h"
#include "codegen.h"
diff --git a/src/ia32/ic-ia32.cc b/src/ia32/ic-ia32.cc
index 10d6c86..eb6ccd9 100644
--- a/src/ia32/ic-ia32.cc
+++ b/src/ia32/ic-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "codegen.h"
#include "ic-inl.h"
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
index 694ae13..96fb98e 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "ia32/lithium-codegen-ia32.h"
#include "ic.h"
diff --git a/src/ia32/lithium-gap-resolver-ia32.cc b/src/ia32/lithium-gap-resolver-ia32.cc
index 3da8f32..86bfe2f 100644
--- a/src/ia32/lithium-gap-resolver-ia32.cc
+++ b/src/ia32/lithium-gap-resolver-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "ia32/lithium-gap-resolver-ia32.h"
#include "ia32/lithium-codegen-ia32.h"
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 04b8934..c01cf8c 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "lithium-allocator-inl.h"
#include "ia32/lithium-ia32.h"
diff --git a/src/ia32/macro-assembler-ia32.cc b/src/ia32/macro-assembler-ia32.cc
index 31e9e53..63477aa 100644
--- a/src/ia32/macro-assembler-ia32.cc
+++ b/src/ia32/macro-assembler-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "bootstrapper.h"
#include "codegen.h"
diff --git a/src/ia32/regexp-macro-assembler-ia32.cc b/src/ia32/regexp-macro-assembler-ia32.cc
index 9a166d7..54fe8bf 100644
--- a/src/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/ia32/regexp-macro-assembler-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "unicode.h"
#include "log.h"
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc
index 1a51016..28e043d 100644
--- a/src/ia32/stub-cache-ia32.cc
+++ b/src/ia32/stub-cache-ia32.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
#include "ic-inl.h"
#include "codegen.h"
diff --git a/src/isolate.cc b/src/isolate.cc
index 2383399..fec3dc6 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -29,6 +29,7 @@
#include "v8.h"
+#include "allocation-inl.h"
#include "ast.h"
#include "bootstrapper.h"
#include "codegen.h"
@@ -107,6 +108,7 @@
// is complete.
pending_exception_ = NULL;
has_pending_message_ = false;
+ rethrowing_message_ = false;
pending_message_obj_ = NULL;
pending_message_script_ = NULL;
scheduled_exception_ = NULL;
@@ -116,7 +118,7 @@
void ThreadLocalTop::Initialize() {
InitializeInternal();
#ifdef USE_SIMULATOR
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
simulator_ = Simulator::current(isolate_);
#elif V8_TARGET_ARCH_MIPS
simulator_ = Simulator::current(isolate_);
@@ -486,7 +488,8 @@
block != NULL;
block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
v->VisitPointer(BitCast<Object**>(&(block->exception_)));
- v->VisitPointer(BitCast<Object**>(&(block->message_)));
+ v->VisitPointer(BitCast<Object**>(&(block->message_obj_)));
+ v->VisitPointer(BitCast<Object**>(&(block->message_script_)));
}
// Iterate over pointers on native execution stack.
@@ -1162,6 +1165,22 @@
}
+void Isolate::RestorePendingMessageFromTryCatch(v8::TryCatch* handler) {
+ ASSERT(handler == try_catch_handler());
+ ASSERT(handler->HasCaught());
+ ASSERT(handler->rethrow_);
+ ASSERT(handler->capture_message_);
+ Object* message = reinterpret_cast<Object*>(handler->message_obj_);
+ Object* script = reinterpret_cast<Object*>(handler->message_script_);
+ ASSERT(message->IsJSMessageObject() || message->IsTheHole());
+ ASSERT(script->IsScript() || script->IsTheHole());
+ thread_local_top()->pending_message_obj_ = message;
+ thread_local_top()->pending_message_script_ = script;
+ thread_local_top()->pending_message_start_pos_ = handler->message_start_pos_;
+ thread_local_top()->pending_message_end_pos_ = handler->message_end_pos_;
+}
+
+
Failure* Isolate::PromoteScheduledException() {
MaybeObject* thrown = scheduled_exception();
clear_scheduled_exception();
@@ -1280,9 +1299,12 @@
ShouldReportException(&can_be_caught_externally, catchable_by_javascript);
bool report_exception = catchable_by_javascript && should_report_exception;
bool try_catch_needs_message =
- can_be_caught_externally && try_catch_handler()->capture_message_;
+ can_be_caught_externally && try_catch_handler()->capture_message_ &&
+ !thread_local_top()->rethrowing_message_;
bool bootstrapping = bootstrapper()->IsActive();
+ thread_local_top()->rethrowing_message_ = false;
+
#ifdef ENABLE_DEBUGGER_SUPPORT
// Notify debugger of exception.
if (catchable_by_javascript) {
@@ -1464,8 +1486,9 @@
HandleScope scope(this);
Handle<Object> message_obj(thread_local_top_.pending_message_obj_,
this);
- if (thread_local_top_.pending_message_script_ != NULL) {
- Handle<Script> script(thread_local_top_.pending_message_script_);
+ if (!thread_local_top_.pending_message_script_->IsTheHole()) {
+ Handle<Script> script(
+ Script::cast(thread_local_top_.pending_message_script_));
int start_pos = thread_local_top_.pending_message_start_pos_;
int end_pos = thread_local_top_.pending_message_end_pos_;
MessageLocation location(script, start_pos, end_pos);
@@ -1487,8 +1510,9 @@
thread_local_top_.pending_exception_ != heap()->termination_exception() &&
thread_local_top_.has_pending_message_ &&
!thread_local_top_.pending_message_obj_->IsTheHole() &&
- thread_local_top_.pending_message_script_ != NULL) {
- Handle<Script> script(thread_local_top_.pending_message_script_);
+ !thread_local_top_.pending_message_obj_->IsTheHole()) {
+ Handle<Script> script(
+ Script::cast(thread_local_top_.pending_message_script_));
int start_pos = thread_local_top_.pending_message_start_pos_;
int end_pos = thread_local_top_.pending_message_end_pos_;
return MessageLocation(script, start_pos, end_pos);
@@ -1625,7 +1649,7 @@
// This might be just paranoia, but it seems to be needed in case a
// thread_local_top_ is restored on a separate OS thread.
#ifdef USE_SIMULATOR
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
thread_local_top()->simulator_ = Simulator::current(this);
#elif V8_TARGET_ARCH_MIPS
thread_local_top()->simulator_ = Simulator::current(this);
@@ -1776,8 +1800,8 @@
thread_manager_ = new ThreadManager();
thread_manager_->isolate_ = this;
-#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
- defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
+#if V8_TARGET_ARCH_ARM && !defined(__arm__) || \
+ V8_TARGET_ARCH_MIPS && !defined(__mips__)
simulator_initialized_ = false;
simulator_i_cache_ = NULL;
simulator_redirection_ = NULL;
@@ -1936,6 +1960,15 @@
Isolate::~Isolate() {
TRACE_ISOLATE(destructor);
+ // The entry stack must be empty when we get here,
+ // except for the default isolate, where it can
+ // still contain up to one entry stack item
+ ASSERT(entry_stack_ == NULL || this == default_isolate_);
+ ASSERT(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
+
+ delete entry_stack_;
+ entry_stack_ = NULL;
+
delete[] assembler_spare_buffer_;
assembler_spare_buffer_ = NULL;
@@ -2002,6 +2035,9 @@
delete global_handles_;
global_handles_ = NULL;
+ delete string_stream_debug_object_cache_;
+ string_stream_debug_object_cache_ = NULL;
+
delete external_reference_table_;
external_reference_table_ = NULL;
@@ -2039,15 +2075,24 @@
try_catch_handler()->has_terminated_ = true;
try_catch_handler()->exception_ = heap()->null_value();
} else {
+ v8::TryCatch* handler = try_catch_handler();
// At this point all non-object (failure) exceptions have
// been dealt with so this shouldn't fail.
ASSERT(!pending_exception()->IsFailure());
- try_catch_handler()->can_continue_ = true;
- try_catch_handler()->has_terminated_ = false;
- try_catch_handler()->exception_ = pending_exception();
- if (!thread_local_top_.pending_message_obj_->IsTheHole()) {
- try_catch_handler()->message_ = thread_local_top_.pending_message_obj_;
- }
+ ASSERT(thread_local_top_.pending_message_obj_->IsJSMessageObject() ||
+ thread_local_top_.pending_message_obj_->IsTheHole());
+ ASSERT(thread_local_top_.pending_message_script_->IsScript() ||
+ thread_local_top_.pending_message_script_->IsTheHole());
+ handler->can_continue_ = true;
+ handler->has_terminated_ = false;
+ handler->exception_ = pending_exception();
+ // Propagate to the external try-catch only if we got an actual message.
+ if (thread_local_top_.pending_message_obj_->IsTheHole()) return;
+
+ handler->message_obj_ = thread_local_top_.pending_message_obj_;
+ handler->message_script_ = thread_local_top_.pending_message_script_;
+ handler->message_start_pos_ = thread_local_top_.pending_message_start_pos_;
+ handler->message_end_pos_ = thread_local_top_.pending_message_end_pos_;
}
}
@@ -2134,7 +2179,7 @@
// Initialize other runtime facilities
#if defined(USE_SIMULATOR)
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
Simulator::Initialize(this);
#endif
#endif
diff --git a/src/isolate.h b/src/isolate.h
index 981f81c..f7d40dd 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -101,8 +101,8 @@
class DebuggerAgent;
#endif
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
- !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
+ !defined(__mips__) && V8_TARGET_ARCH_MIPS
class Redirection;
class Simulator;
#endif
@@ -246,8 +246,9 @@
ThreadId thread_id_;
MaybeObject* pending_exception_;
bool has_pending_message_;
+ bool rethrowing_message_;
Object* pending_message_obj_;
- Script* pending_message_script_;
+ Object* pending_message_script_;
int pending_message_start_pos_;
int pending_message_end_pos_;
// Use a separate value for scheduled exceptions to preserve the
@@ -263,7 +264,7 @@
Address handler_; // try-blocks are chained through the stack
#ifdef USE_SIMULATOR
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
Simulator* simulator_;
#endif
#endif // USE_SIMULATOR
@@ -391,8 +392,8 @@
thread_id_(thread_id),
stack_limit_(0),
thread_state_(NULL),
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
- !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
+ !defined(__mips__) && V8_TARGET_ARCH_MIPS
simulator_(NULL),
#endif
next_(NULL),
@@ -404,8 +405,8 @@
ThreadState* thread_state() const { return thread_state_; }
void set_thread_state(ThreadState* value) { thread_state_ = value; }
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
- !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
+ !defined(__mips__) && V8_TARGET_ARCH_MIPS
Simulator* simulator() const { return simulator_; }
void set_simulator(Simulator* simulator) {
simulator_ = simulator;
@@ -422,8 +423,8 @@
uintptr_t stack_limit_;
ThreadState* thread_state_;
-#if !defined(__arm__) && defined(V8_TARGET_ARCH_ARM) || \
- !defined(__mips__) && defined(V8_TARGET_ARCH_MIPS)
+#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
+ !defined(__mips__) && V8_TARGET_ARCH_MIPS
Simulator* simulator_;
#endif
@@ -582,7 +583,7 @@
void clear_pending_message() {
thread_local_top_.has_pending_message_ = false;
thread_local_top_.pending_message_obj_ = heap_.the_hole_value();
- thread_local_top_.pending_message_script_ = NULL;
+ thread_local_top_.pending_message_script_ = heap_.the_hole_value();
}
v8::TryCatch* try_catch_handler() {
return thread_local_top_.TryCatchHandler();
@@ -760,6 +761,9 @@
// originally.
Failure* ReThrow(MaybeObject* exception);
void ScheduleThrow(Object* exception);
+ // Re-set pending message, script and positions reported to the TryCatch
+ // back to the TLS for re-use when rethrowing.
+ void RestorePendingMessageFromTryCatch(v8::TryCatch* handler);
void ReportPendingMessages();
// Return pending location if any or unfilled structure.
MessageLocation GetMessageLocation();
@@ -994,8 +998,8 @@
int* code_kind_statistics() { return code_kind_statistics_; }
#endif
-#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
- defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
+#if V8_TARGET_ARCH_ARM && !defined(__arm__) || \
+ V8_TARGET_ARCH_MIPS && !defined(__mips__)
bool simulator_initialized() { return simulator_initialized_; }
void set_simulator_initialized(bool initialized) {
simulator_initialized_ = initialized;
@@ -1301,8 +1305,8 @@
// Time stamp at initialization.
double time_millis_at_init_;
-#if defined(V8_TARGET_ARCH_ARM) && !defined(__arm__) || \
- defined(V8_TARGET_ARCH_MIPS) && !defined(__mips__)
+#if V8_TARGET_ARCH_ARM && !defined(__arm__) || \
+ V8_TARGET_ARCH_MIPS && !defined(__mips__)
bool simulator_initialized_;
HashMap* simulator_i_cache_;
Redirection* simulator_redirection_;
diff --git a/src/marking-thread.cc b/src/marking-thread.cc
index 574485a..ac9f944 100644
--- a/src/marking-thread.cc
+++ b/src/marking-thread.cc
@@ -73,6 +73,7 @@
Release_Store(&stop_thread_, static_cast<AtomicWord>(true));
start_marking_semaphore_->Signal();
stop_semaphore_->Wait();
+ Join();
}
diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
index eee79a2..c4fefcc 100644
--- a/src/mips/assembler-mips.cc
+++ b/src/mips/assembler-mips.cc
@@ -35,7 +35,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "mips/assembler-mips-inl.h"
#include "serialize.h"
@@ -1475,7 +1475,7 @@
void Assembler::stop(const char* msg, uint32_t code) {
ASSERT(code > kMaxWatchpointCode);
ASSERT(code <= kMaxStopCode);
-#if defined(V8_HOST_ARCH_MIPS)
+#if V8_HOST_ARCH_MIPS
break_(0x54321);
#else // V8_HOST_ARCH_MIPS
BlockTrampolinePoolFor(2);
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index dddf045..fd35a35 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -29,7 +29,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "codegen.h"
#include "debug.h"
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 3e42309..69b957a 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "bootstrapper.h"
#include "code-stubs.h"
@@ -7530,12 +7530,16 @@
const int32_t kReturnAddressDistanceFromFunctionStart =
Assembler::kCallTargetAddressOffset + (2 * Assembler::kInstrSize);
- // Save live volatile registers.
+ // This should contain all kJSCallerSaved registers.
+ const RegList kSavedRegs =
+ kJSCallerSaved | // Caller saved registers.
+ s5.bit(); // Saved stack pointer.
+
// We also save ra, so the count here is one higher than the mask indicates.
- const int32_t kNumSavedRegs = kNumJSCallerSaved + 1;
+ const int32_t kNumSavedRegs = kNumJSCallerSaved + 2;
// Save all caller-save registers as this may be called from anywhere.
- __ MultiPush(kJSCallerSaved | ra.bit());
+ __ MultiPush(kSavedRegs | ra.bit());
// Compute the function's address for the first argument.
__ Subu(a0, ra, Operand(kReturnAddressDistanceFromFunctionStart));
@@ -7547,7 +7551,7 @@
// Align the stack if necessary.
int frame_alignment = masm->ActivationFrameAlignment();
if (frame_alignment > kPointerSize) {
- __ mov(t1, sp);
+ __ mov(s5, sp);
ASSERT(IsPowerOf2(frame_alignment));
__ And(sp, sp, Operand(-frame_alignment));
}
@@ -7568,11 +7572,11 @@
// Restore the stack pointer if needed.
if (frame_alignment > kPointerSize) {
- __ mov(sp, t1);
+ __ mov(sp, s5);
}
// Also pop ra to get Ret(0).
- __ MultiPop(kJSCallerSaved | ra.bit());
+ __ MultiPop(kSavedRegs | ra.bit());
__ Ret();
}
diff --git a/src/mips/codegen-mips.cc b/src/mips/codegen-mips.cc
index 72eb00b..7a95bc4 100644
--- a/src/mips/codegen-mips.cc
+++ b/src/mips/codegen-mips.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "codegen.h"
#include "macro-assembler.h"
diff --git a/src/mips/constants-mips.cc b/src/mips/constants-mips.cc
index ddfa891..a20ec54 100644
--- a/src/mips/constants-mips.cc
+++ b/src/mips/constants-mips.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "constants-mips.h"
diff --git a/src/mips/cpu-mips.cc b/src/mips/cpu-mips.cc
index 93ebeda..d13b233 100644
--- a/src/mips/cpu-mips.cc
+++ b/src/mips/cpu-mips.cc
@@ -36,7 +36,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "cpu.h"
#include "macro-assembler.h"
diff --git a/src/mips/debug-mips.cc b/src/mips/debug-mips.cc
index 0ae0187..30cc4db 100644
--- a/src/mips/debug-mips.cc
+++ b/src/mips/debug-mips.cc
@@ -29,7 +29,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "codegen.h"
#include "debug.h"
diff --git a/src/mips/disasm-mips.cc b/src/mips/disasm-mips.cc
index b787f13..708df39 100644
--- a/src/mips/disasm-mips.cc
+++ b/src/mips/disasm-mips.cc
@@ -56,7 +56,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "mips/constants-mips.h"
#include "disasm.h"
diff --git a/src/mips/frames-mips.cc b/src/mips/frames-mips.cc
index d070b56..1bd5116 100644
--- a/src/mips/frames-mips.cc
+++ b/src/mips/frames-mips.cc
@@ -28,7 +28,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "assembler.h"
#include "assembler-mips.h"
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index d416a3b..032c1f5 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
// Note on Mips implementation:
//
diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc
index 8a00f60..896e030 100644
--- a/src/mips/ic-mips.cc
+++ b/src/mips/ic-mips.cc
@@ -29,7 +29,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "codegen.h"
#include "code-stubs.h"
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index 3e3314a..5890347 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -29,7 +29,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "bootstrapper.h"
#include "codegen.h"
@@ -4723,19 +4723,19 @@
int MacroAssembler::ActivationFrameAlignment() {
-#if defined(V8_HOST_ARCH_MIPS)
+#if V8_HOST_ARCH_MIPS
// Running on the real platform. Use the alignment as mandated by the local
// environment.
// Note: This will break if we ever start generating snapshots on one Mips
// platform for another Mips platform with a different alignment.
return OS::ActivationFrameAlignment();
-#else // defined(V8_HOST_ARCH_MIPS)
+#else // V8_HOST_ARCH_MIPS
// If we are using the simulator then we should always align to the expected
// alignment. As the simulator is used to generate snapshots we do not know
// if the target platform will need alignment, so this is controlled from a
// flag.
return FLAG_sim_stack_alignment;
-#endif // defined(V8_HOST_ARCH_MIPS)
+#endif // V8_HOST_ARCH_MIPS
}
@@ -5066,7 +5066,7 @@
// The argument stots are presumed to have been set up by
// PrepareCallCFunction. The C function must be called via t9, for mips ABI.
-#if defined(V8_HOST_ARCH_MIPS)
+#if V8_HOST_ARCH_MIPS
if (emit_debug_code()) {
int frame_alignment = OS::ActivationFrameAlignment();
int frame_alignment_mask = frame_alignment - 1;
diff --git a/src/mips/regexp-macro-assembler-mips.cc b/src/mips/regexp-macro-assembler-mips.cc
index 2961519..7b67a7b 100644
--- a/src/mips/regexp-macro-assembler-mips.cc
+++ b/src/mips/regexp-macro-assembler-mips.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "unicode.h"
#include "log.h"
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index 8771bd2..914a758 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -31,7 +31,7 @@
#include <cstdarg>
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "cpu.h"
#include "disasm.h"
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index caddb76..5221190 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_MIPS
#include "ic-inl.h"
#include "codegen.h"
diff --git a/src/optimizing-compiler-thread.cc b/src/optimizing-compiler-thread.cc
index dbf9ad7..21ef237 100644
--- a/src/optimizing-compiler-thread.cc
+++ b/src/optimizing-compiler-thread.cc
@@ -115,8 +115,11 @@
InstallOptimizedFunctions();
} else {
OptimizingCompiler* optimizing_compiler;
+ // The optimizing compiler is allocated in the CompilationInfo's zone.
while (input_queue_.Dequeue(&optimizing_compiler)) {
- // The optimizing compiler is allocated in the CompilationInfo's zone.
+ delete optimizing_compiler->info();
+ }
+ while (output_queue_.Dequeue(&optimizing_compiler)) {
delete optimizing_compiler->info();
}
}
@@ -127,6 +130,8 @@
double percentage = (compile_time * 100) / total_time;
PrintF(" ** Compiler thread did %.2f%% useful work\n", percentage);
}
+
+ Join();
}
diff --git a/src/optimizing-compiler-thread.h b/src/optimizing-compiler-thread.h
index 59c94cb..699c76d 100644
--- a/src/optimizing-compiler-thread.h
+++ b/src/optimizing-compiler-thread.h
@@ -83,8 +83,12 @@
#endif
~OptimizingCompilerThread() {
+ delete install_mutex_;
delete input_queue_semaphore_;
delete stop_semaphore_;
+#ifdef DEBUG
+ delete thread_id_mutex_;
+#endif
}
private:
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 4a9bb7e..2c6a36c 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -295,7 +295,7 @@
int OS::ActivationFrameAlignment() {
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
// On EABI ARM targets this is required for fp correctness in the
// runtime system.
return 8;
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index b21166d..21e9c7f 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -583,7 +583,7 @@
if (kernel_version_major < 11) {
// 8.x.x (Tiger), 9.x.x (Leopard), 10.x.x (Snow Leopard) have the
// same offsets.
-#if defined(V8_HOST_ARCH_IA32)
+#if V8_HOST_ARCH_IA32
kMacTlsBaseOffset = 0x48;
#else
kMacTlsBaseOffset = 0x60;
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index f2d9dd4..b722e31 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -79,7 +79,7 @@
// CpuFeatures::Probe. We don't care about randomization in this case because
// the code page is immediately freed.
if (isolate != NULL) {
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
uint64_t rnd1 = V8::RandomPrivate(isolate);
uint64_t rnd2 = V8::RandomPrivate(isolate);
uint64_t raw_addr = (rnd1 << 32) ^ rnd2;
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index f76ec44..e72a5d9 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -105,7 +105,7 @@
// CpuFeatures::Probe. We don't care about randomization in this case because
// the code page is immediately freed.
if (isolate != NULL) {
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
uint64_t rnd1 = V8::RandomPrivate(isolate);
uint64_t rnd2 = V8::RandomPrivate(isolate);
uint64_t raw_addr = (rnd1 << 32) ^ rnd2;
@@ -321,7 +321,7 @@
}
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
static void MemMoveWrapper(void* dest, const void* src, size_t size) {
memmove(dest, src, size);
}
@@ -344,7 +344,7 @@
void POSIXPostSetUp() {
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
OS::MemMoveFunction generated_memmove = CreateMemMoveFunction();
if (generated_memmove != NULL) {
memmove_function = generated_memmove;
diff --git a/src/platform-tls-mac.h b/src/platform-tls-mac.h
index 728524e..d1c5907 100644
--- a/src/platform-tls-mac.h
+++ b/src/platform-tls-mac.h
@@ -33,7 +33,7 @@
namespace v8 {
namespace internal {
-#if defined(V8_HOST_ARCH_IA32) || defined(V8_HOST_ARCH_X64)
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
#define V8_FAST_TLS_SUPPORTED 1
@@ -43,7 +43,7 @@
inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
intptr_t result;
-#if defined(V8_HOST_ARCH_IA32)
+#if V8_HOST_ARCH_IA32
asm("movl %%gs:(%1,%2,4), %0;"
:"=r"(result) // Output must be a writable register.
:"r"(kMacTlsBaseOffset), "r"(index));
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 600962e..1913760 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -147,7 +147,7 @@
static Mutex* limit_mutex = NULL;
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
static void MemMoveWrapper(void* dest, const void* src, size_t size) {
memmove(dest, src, size);
}
@@ -580,7 +580,7 @@
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
-#if defined(V8_TARGET_ARCH_IA32)
+#if V8_TARGET_ARCH_IA32
OS::MemMoveFunction generated_memmove = CreateMemMoveFunction();
if (generated_memmove != NULL) {
memmove_function = generated_memmove;
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index 6f9a601..20c1aec 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -44,17 +44,19 @@
CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix,
const char* name,
int security_token_id,
+ const char* name_prefix,
const char* resource_name,
int line_number)
: tag_(tag),
+ builtin_id_(Builtins::builtin_count),
name_prefix_(name_prefix),
name_(name),
resource_name_(resource_name),
line_number_(line_number),
shared_id_(0),
+ script_id_(v8::Script::kNoScriptId),
security_token_id_(security_token_id),
no_frame_ranges_(NULL) {
}
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 8505b5b..aeb80a3 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -235,6 +235,12 @@
}
+void CodeEntry::SetBuiltinId(Builtins::Name id) {
+ tag_ = Logger::BUILTIN_TAG;
+ builtin_id_ = id;
+}
+
+
ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
HashMap::Entry* map_entry =
children_.Lookup(entry, CodeEntryHash(entry), false);
@@ -267,12 +273,13 @@
void ProfileNode::Print(int indent) {
- OS::Print("%5u %5u %*c %s%s [%d] #%d",
+ OS::Print("%5u %5u %*c %s%s [%d] #%d %d",
total_ticks_, self_ticks_,
indent, ' ',
entry_->name_prefix(),
entry_->name(),
entry_->security_token_id(),
+ entry_->script_id(),
id());
if (entry_->resource_name()[0] != '\0')
OS::Print(" %s:%d", entry_->resource_name(), entry_->line_number());
@@ -298,7 +305,7 @@
ProfileTree::ProfileTree()
- : root_entry_(Logger::FUNCTION_TAG, "", "(root)"),
+ : root_entry_(Logger::FUNCTION_TAG, "(root)"),
next_node_id_(1),
root_(new ProfileNode(this, &root_entry_)) {
}
@@ -787,54 +794,6 @@
}
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- Name* name,
- String* resource_name,
- int line_number) {
- CodeEntry* entry = new CodeEntry(tag,
- CodeEntry::kEmptyNamePrefix,
- GetFunctionName(name),
- TokenEnumerator::kNoSecurityToken,
- GetName(resource_name),
- line_number);
- code_entries_.Add(entry);
- return entry;
-}
-
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name) {
- CodeEntry* entry = new CodeEntry(tag,
- CodeEntry::kEmptyNamePrefix,
- GetFunctionName(name));
- code_entries_.Add(entry);
- return entry;
-}
-
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix,
- Name* name) {
- CodeEntry* entry = new CodeEntry(tag,
- name_prefix,
- GetName(name),
- TokenEnumerator::kInheritsSecurityToken);
- code_entries_.Add(entry);
- return entry;
-}
-
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(Logger::LogEventsAndTags tag,
- int args_count) {
- CodeEntry* entry = new CodeEntry(tag,
- "args_count: ",
- GetName(args_count),
- TokenEnumerator::kInheritsSecurityToken);
- code_entries_.Add(entry);
- return entry;
-}
-
-
void CpuProfilesCollection::AddPathToCurrentProfiles(
const Vector<CodeEntry*>& path) {
// As starting / stopping profiles is rare relatively to this
@@ -848,6 +807,24 @@
}
+CodeEntry* CpuProfilesCollection::NewCodeEntry(
+ Logger::LogEventsAndTags tag,
+ const char* name,
+ int security_token_id,
+ const char* name_prefix,
+ const char* resource_name,
+ int line_number) {
+ CodeEntry* code_entry = new CodeEntry(tag,
+ name,
+ security_token_id,
+ name_prefix,
+ resource_name,
+ line_number);
+ code_entries_.Add(code_entry);
+ return code_entry;
+}
+
+
void SampleRateCalculator::Tick() {
if (--wall_time_query_countdown_ == 0)
UpdateMeasurements(OS::TimeCurrentMillis());
@@ -877,6 +854,8 @@
"(program)";
const char* const ProfileGenerator::kGarbageCollectorEntryName =
"(garbage collector)";
+const char* const ProfileGenerator::kUnresolvedFunctionName =
+ "(unresolved function)";
ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
@@ -885,7 +864,10 @@
profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
gc_entry_(
profiles->NewCodeEntry(Logger::BUILTIN_TAG,
- kGarbageCollectorEntryName)) {
+ kGarbageCollectorEntryName)),
+ unresolved_entry_(
+ profiles->NewCodeEntry(Logger::FUNCTION_TAG,
+ kUnresolvedFunctionName)) {
}
@@ -897,33 +879,40 @@
CodeEntry** entry = entries.start();
memset(entry, 0, entries.length() * sizeof(*entry));
if (sample.pc != NULL) {
- Address start;
- CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
- // If pc is in the function code before it set up stack frame or after the
- // frame was destroyed SafeStackFrameIterator incorrectly thinks that
- // ebp contains return address of the current function and skips caller's
- // frame. Check for this case and just skip such samples.
- if (pc_entry) {
- List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
- if (ranges) {
- Code* code = Code::cast(HeapObject::FromAddress(start));
- int pc_offset = static_cast<int>(sample.pc - code->instruction_start());
- for (int i = 0; i < ranges->length(); i++) {
- OffsetRange& range = ranges->at(i);
- if (range.from <= pc_offset && pc_offset < range.to) {
- return;
- }
- }
- }
- }
- *entry++ = pc_entry;
-
if (sample.has_external_callback) {
// Don't use PC when in external callback code, as it can point
// inside callback's code, and we will erroneously report
// that a callback calls itself.
- *(entries.start()) = NULL;
*entry++ = code_map_.FindEntry(sample.external_callback);
+ } else {
+ Address start;
+ CodeEntry* pc_entry = code_map_.FindEntry(sample.pc, &start);
+ // If pc is in the function code before it set up stack frame or after the
+ // frame was destroyed SafeStackFrameIterator incorrectly thinks that
+ // ebp contains return address of the current function and skips caller's
+ // frame. Check for this case and just skip such samples.
+ if (pc_entry) {
+ List<OffsetRange>* ranges = pc_entry->no_frame_ranges();
+ if (ranges) {
+ Code* code = Code::cast(HeapObject::FromAddress(start));
+ int pc_offset = static_cast<int>(
+ sample.pc - code->instruction_start());
+ for (int i = 0; i < ranges->length(); i++) {
+ OffsetRange& range = ranges->at(i);
+ if (range.from <= pc_offset && pc_offset < range.to) {
+ return;
+ }
+ }
+ }
+ *entry++ = pc_entry;
+
+ if (pc_entry->builtin_id() == Builtins::kFunctionCall) {
+ // When current function is FunctionCall builtin tos is sometimes
+ // address of the function that invoked it but sometimes it's one
+ // of the arguments. We simply replace the frame with 'unknown' entry.
+ *entry++ = unresolved_entry_;
+ }
+ }
}
for (const Address* stack_pos = sample.stack,
diff --git a/src/profile-generator.h b/src/profile-generator.h
index f8534e4..411cbdb 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -97,9 +97,9 @@
public:
// CodeEntry doesn't own name strings, just references them.
INLINE(CodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix,
const char* name,
int security_token_id = TokenEnumerator::kNoSecurityToken,
+ const char* name_prefix = CodeEntry::kEmptyNamePrefix,
const char* resource_name = CodeEntry::kEmptyResourceName,
int line_number = v8::CpuProfileNode::kNoLineNumberInfo));
~CodeEntry();
@@ -111,6 +111,8 @@
INLINE(const char* resource_name() const) { return resource_name_; }
INLINE(int line_number() const) { return line_number_; }
INLINE(void set_shared_id(int shared_id)) { shared_id_ = shared_id; }
+ INLINE(int script_id() const) { return script_id_; }
+ INLINE(void set_script_id(int script_id)) { script_id_ = script_id; }
INLINE(int security_token_id() const) { return security_token_id_; }
INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
@@ -120,6 +122,9 @@
no_frame_ranges_ = ranges;
}
+ void SetBuiltinId(Builtins::Name id);
+ Builtins::Name builtin_id() const { return builtin_id_; }
+
void CopyData(const CodeEntry& source);
uint32_t GetCallUid() const;
bool IsSameAs(CodeEntry* entry) const;
@@ -128,12 +133,14 @@
static const char* const kEmptyResourceName;
private:
- Logger::LogEventsAndTags tag_;
+ Logger::LogEventsAndTags tag_ : 8;
+ Builtins::Name builtin_id_ : 8;
const char* name_prefix_;
const char* name_;
const char* resource_name_;
int line_number_;
int shared_id_;
+ int script_id_;
int security_token_id_;
List<OffsetRange>* no_frame_ranges_;
@@ -318,18 +325,24 @@
const char* GetName(int args_count) {
return function_and_resource_names_.GetName(args_count);
}
+ const char* GetFunctionName(Name* name) {
+ return function_and_resource_names_.GetFunctionName(name);
+ }
+ const char* GetFunctionName(const char* name) {
+ return function_and_resource_names_.GetFunctionName(name);
+ }
CpuProfile* GetProfile(int security_token_id, unsigned uid);
bool IsLastProfile(const char* title);
void RemoveProfile(CpuProfile* profile);
bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- Name* name, String* resource_name, int line_number);
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, const char* name);
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
- const char* name_prefix, Name* name);
- CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, int args_count);
- CodeEntry* NewCodeEntry(int security_token_id);
+ CodeEntry* NewCodeEntry(
+ Logger::LogEventsAndTags tag,
+ const char* name,
+ int security_token_id = TokenEnumerator::kNoSecurityToken,
+ const char* name_prefix = CodeEntry::kEmptyNamePrefix,
+ const char* resource_name = CodeEntry::kEmptyResourceName,
+ int line_number = v8::CpuProfileNode::kNoLineNumberInfo);
// Called from profile generator thread.
void AddPathToCurrentProfiles(const Vector<CodeEntry*>& path);
@@ -338,12 +351,6 @@
static const int kMaxSimultaneousProfiles = 100;
private:
- const char* GetFunctionName(Name* name) {
- return function_and_resource_names_.GetFunctionName(name);
- }
- const char* GetFunctionName(const char* name) {
- return function_and_resource_names_.GetFunctionName(name);
- }
int GetProfileIndex(unsigned uid);
List<CpuProfile*>* GetProfilesList(int security_token_id);
int TokenToIndex(int security_token_id);
@@ -422,6 +429,9 @@
static const char* const kAnonymousFunctionName;
static const char* const kProgramEntryName;
static const char* const kGarbageCollectorEntryName;
+ // Used to represent frames for which we have no reliable way to
+ // detect function.
+ static const char* const kUnresolvedFunctionName;
private:
INLINE(CodeEntry* EntryForVMState(StateTag tag));
@@ -430,6 +440,7 @@
CodeMap code_map_;
CodeEntry* program_entry_;
CodeEntry* gc_entry_;
+ CodeEntry* unresolved_entry_;
SampleRateCalculator sample_rate_calc_;
DISALLOW_COPY_AND_ASSIGN(ProfileGenerator);
diff --git a/src/runtime.cc b/src/runtime.cc
index 081774f..4691e18 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8314,8 +8314,13 @@
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (FLAG_parallel_recompilation && V8::UseCrankshaft()) {
- // While function is in optimization pipeline, it is marked with builtins.
- while (function->code()->kind() == Code::BUILTIN) {
+ // While function is in optimization pipeline, it is marked accordingly.
+ // Note that if the debugger is activated during parallel recompilation,
+ // the function will be marked with the lazy-recompile builtin, which is
+ // not related to parallel recompilation.
+ while (function->IsMarkedForParallelRecompilation() ||
+ function->IsInRecompileQueue() ||
+ function->IsMarkedForInstallingRecompiledCode()) {
isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
OS::Sleep(50);
}
@@ -12097,14 +12102,28 @@
}
+static bool IsPositionAlignmentCodeCorrect(int alignment) {
+ return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
HandleScope scope(isolate);
- ASSERT(args.length() == 1);
+ ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
+ CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
+
+ if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
+ return isolate->ThrowIllegalOperation();
+ }
+ BreakPositionAlignment alignment =
+ static_cast<BreakPositionAlignment>(statement_aligned_code);
+
Handle<SharedFunctionInfo> shared(fun->shared());
// Find the number of break points
- Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
+ Handle<Object> break_locations =
+ Debug::GetSourceBreakLocations(shared, alignment);
if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
// Return array as JS array
return *isolate->factory()->NewJSArrayWithElements(
@@ -12137,14 +12156,22 @@
// GetScriptFromScriptData.
// args[0]: script to set break point in
// args[1]: number: break source position (within the script source)
-// args[2]: number: break point object
+// args[2]: number, breakpoint position alignment
+// args[3]: number: break point object
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
HandleScope scope(isolate);
- ASSERT(args.length() == 3);
+ ASSERT(args.length() == 4);
CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
RUNTIME_ASSERT(source_position >= 0);
- Handle<Object> break_point_object_arg = args.at<Object>(2);
+ CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
+ Handle<Object> break_point_object_arg = args.at<Object>(3);
+
+ if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
+ return isolate->ThrowIllegalOperation();
+ }
+ BreakPositionAlignment alignment =
+ static_cast<BreakPositionAlignment>(statement_aligned_code);
// Get the script from the script wrapper.
RUNTIME_ASSERT(wrapper->value()->IsScript());
@@ -12152,7 +12179,8 @@
// Set break point.
if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
- &source_position)) {
+ &source_position,
+ alignment)) {
return isolate->heap()->undefined_value();
}
diff --git a/src/runtime.h b/src/runtime.h
index 4928e78..70568f9 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -499,9 +499,9 @@
F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2, 1) \
F(SetDisableBreak, 1, 1) \
- F(GetBreakLocations, 1, 1) \
+ F(GetBreakLocations, 2, 1) \
F(SetFunctionBreakPoint, 3, 1) \
- F(SetScriptBreakPoint, 3, 1) \
+ F(SetScriptBreakPoint, 4, 1) \
F(ClearBreakPoint, 1, 1) \
F(ChangeBreakOnException, 2, 1) \
F(IsBreakOnException, 1, 1) \
@@ -597,7 +597,8 @@
F(GetCachedArrayIndex, 1, 1) \
F(FastAsciiArrayJoin, 2, 1) \
F(GeneratorNext, 2, 1) \
- F(GeneratorThrow, 2, 1)
+ F(GeneratorThrow, 2, 1) \
+ F(DebugBreakInOptimizedCode, 0, 1)
// ----------------------------------------------------------------------------
diff --git a/src/strtod.cc b/src/strtod.cc
index dfe2fb7..a1774b6 100644
--- a/src/strtod.cc
+++ b/src/strtod.cc
@@ -175,7 +175,7 @@
static bool DoubleStrtod(Vector<const char> trimmed,
int exponent,
double* result) {
-#if (defined(V8_TARGET_ARCH_IA32) || defined(USE_SIMULATOR)) \
+#if (V8_TARGET_ARCH_IA32 || defined(USE_SIMULATOR)) \
&& !defined(_MSC_VER)
// On x86 the floating-point stack can be 64 or 80 bits wide. If it is
// 80 bits wide (as is the case on Linux) then double-rounding occurs and the
diff --git a/src/sweeper-thread.cc b/src/sweeper-thread.cc
index 099f5d1..ede567a 100644
--- a/src/sweeper-thread.cc
+++ b/src/sweeper-thread.cc
@@ -93,6 +93,7 @@
Release_Store(&stop_thread_, static_cast<AtomicWord>(true));
start_sweeping_semaphore_->Signal();
stop_semaphore_->Wait();
+ Join();
}
diff --git a/src/third_party/vtune/v8vtune.gyp b/src/third_party/vtune/v8vtune.gyp
index cabd37a..6c3de3e 100644
--- a/src/third_party/vtune/v8vtune.gyp
+++ b/src/third_party/vtune/v8vtune.gyp
@@ -26,6 +26,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'variables': {
+ 'v8_code': 1,
+ },
'includes': ['../../../build/common.gypi'],
'targets': [
{
diff --git a/src/type-info.h b/src/type-info.h
index aa1f509..a1c1f54 100644
--- a/src/type-info.h
+++ b/src/type-info.h
@@ -303,9 +303,9 @@
Maybe<int>* fixed_right_arg);
void CompareType(TypeFeedbackId id,
- Handle<Type>* left,
- Handle<Type>* right,
- Handle<Type>* combined);
+ Handle<Type>* left_type,
+ Handle<Type>* right_type,
+ Handle<Type>* combined_type);
Handle<Type> ClauseType(TypeFeedbackId id);
diff --git a/src/typing.cc b/src/typing.cc
index 3f3ff60..7c11612 100644
--- a/src/typing.cc
+++ b/src/typing.cc
@@ -432,13 +432,13 @@
CHECK_ALIVE(Visit(expr->right()));
// Collect type feedback.
- Handle<Type> type, left_type, right_type;
+ Handle<Type> left_type, right_type, result_type;
Maybe<int> fixed_right_arg;
oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
- &left_type, &right_type, &type, &fixed_right_arg);
- MergeLowerType(expr, type);
+ &left_type, &right_type, &result_type, &fixed_right_arg);
MergeLowerType(expr->left(), left_type);
MergeLowerType(expr->right(), right_type);
+ expr->set_result_type(result_type);
expr->set_fixed_right_arg(fixed_right_arg);
if (expr->op() == Token::OR || expr->op() == Token::AND) {
expr->left()->RecordToBooleanTypeFeedback(oracle());
diff --git a/src/v8utils.h b/src/v8utils.h
index 8661f9b..ff9f8f2 100644
--- a/src/v8utils.h
+++ b/src/v8utils.h
@@ -257,9 +257,9 @@
a = b; // Fake assignment to check assignability.
USE(a);
#endif // DEBUG
-#if defined(V8_HOST_ARCH_IA32)
+#if V8_HOST_ARCH_IA32
#define STOS "stosl"
-#elif defined(V8_HOST_ARCH_X64)
+#elif V8_HOST_ARCH_X64
#define STOS "stosq"
#endif
#if defined(__native_client__)
diff --git a/src/version.cc b/src/version.cc
index 84cafc8..c634509 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,8 +34,8 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 20
-#define BUILD_NUMBER 0
-#define PATCH_LEVEL 1
+#define BUILD_NUMBER 1
+#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
#define IS_CANDIDATE_VERSION 0
diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc
index f547e79..3a3ee9c 100644
--- a/src/x64/assembler-x64.cc
+++ b/src/x64/assembler-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "macro-assembler.h"
#include "serialize.h"
diff --git a/src/x64/builtins-x64.cc b/src/x64/builtins-x64.cc
index 9376cc7..378217b 100644
--- a/src/x64/builtins-x64.cc
+++ b/src/x64/builtins-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "codegen.h"
#include "deoptimizer.h"
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index 1be60ab..9774638 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "bootstrapper.h"
#include "code-stubs.h"
@@ -1558,7 +1558,8 @@
char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
// Two uint_32's and a pointer per element.
- CHECK_EQ(16, static_cast<int>(elem2_start - elem_start));
+ CHECK_EQ(2 * kIntSize + 1 * kPointerSize,
+ static_cast<int>(elem2_start - elem_start));
CHECK_EQ(0, static_cast<int>(elem_in0 - elem_start));
CHECK_EQ(kIntSize, static_cast<int>(elem_in1 - elem_start));
CHECK_EQ(2 * kIntSize, static_cast<int>(elem_out - elem_start));
@@ -5111,17 +5112,17 @@
// Don't enter the rep movs if there are less than 4 bytes to copy.
Label last_bytes;
- __ testl(count, Immediate(~7));
+ __ testl(count, Immediate(~(kPointerSize - 1)));
__ j(zero, &last_bytes, Label::kNear);
// Copy from edi to esi using rep movs instruction.
__ movl(kScratchRegister, count);
- __ shr(count, Immediate(3)); // Number of doublewords to copy.
+ __ shr(count, Immediate(kPointerSizeLog2)); // Number of doublewords to copy.
__ repmovsq();
// Find number of bytes left.
__ movl(count, kScratchRegister);
- __ and_(count, Immediate(7));
+ __ and_(count, Immediate(kPointerSize - 1));
// Check if there are more bytes to copy.
__ bind(&last_bytes);
diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc
index 7a7ec7b..9643872 100644
--- a/src/x64/codegen-x64.cc
+++ b/src/x64/codegen-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "codegen.h"
#include "macro-assembler.h"
@@ -735,7 +735,11 @@
Code* stub = GetCodeAgeStub(age, parity);
CodePatcher patcher(sequence, young_length);
patcher.masm()->call(stub->instruction_start());
- patcher.masm()->nop();
+ for (int i = 0;
+ i < kNoCodeAgeSequenceLength - Assembler::kShortCallInstructionLength;
+ i++) {
+ patcher.masm()->nop();
+ }
}
}
diff --git a/src/x64/cpu-x64.cc b/src/x64/cpu-x64.cc
index 80e22c6..96c5330 100644
--- a/src/x64/cpu-x64.cc
+++ b/src/x64/cpu-x64.cc
@@ -33,7 +33,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "cpu.h"
#include "macro-assembler.h"
diff --git a/src/x64/debug-x64.cc b/src/x64/debug-x64.cc
index 750d929..a337b0d 100644
--- a/src/x64/debug-x64.cc
+++ b/src/x64/debug-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "assembler.h"
#include "codegen.h"
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc
index 60e676a..f2f7ed0 100644
--- a/src/x64/deoptimizer-x64.cc
+++ b/src/x64/deoptimizer-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "codegen.h"
#include "deoptimizer.h"
diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc
index fb0914d..d787775 100644
--- a/src/x64/disasm-x64.cc
+++ b/src/x64/disasm-x64.cc
@@ -31,7 +31,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "disasm.h"
#include "lazy-instance.h"
diff --git a/src/x64/frames-x64.cc b/src/x64/frames-x64.cc
index 21cb79c..5cc27a6 100644
--- a/src/x64/frames-x64.cc
+++ b/src/x64/frames-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "assembler.h"
#include "assembler-x64.h"
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
index 7732a1d..9ad7f58 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "code-stubs.h"
#include "codegen.h"
diff --git a/src/x64/ic-x64.cc b/src/x64/ic-x64.cc
index 82112a0..a0f3ead 100644
--- a/src/x64/ic-x64.cc
+++ b/src/x64/ic-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "codegen.h"
#include "ic-inl.h"
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index f3045d5..c97475a 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "x64/lithium-codegen-x64.h"
#include "code-stubs.h"
diff --git a/src/x64/lithium-gap-resolver-x64.cc b/src/x64/lithium-gap-resolver-x64.cc
index fd74e0a..aed4f36 100644
--- a/src/x64/lithium-gap-resolver-x64.cc
+++ b/src/x64/lithium-gap-resolver-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "x64/lithium-gap-resolver-x64.h"
#include "x64/lithium-codegen-x64.h"
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 7a475a7..9c2373a 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "lithium-allocator-inl.h"
#include "x64/lithium-x64.h"
diff --git a/src/x64/macro-assembler-x64.cc b/src/x64/macro-assembler-x64.cc
index a4d64b9..fdeee31 100644
--- a/src/x64/macro-assembler-x64.cc
+++ b/src/x64/macro-assembler-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "bootstrapper.h"
#include "codegen.h"
@@ -4216,12 +4216,12 @@
// we keep source aligned for the rep movs operation by copying the odd bytes
// at the end of the ranges.
movq(scratch, length);
- shrl(length, Immediate(3));
+ shrl(length, Immediate(kPointerSizeLog2));
repmovsq();
// Move remaining bytes of length.
- andl(scratch, Immediate(0x7));
- movq(length, Operand(source, scratch, times_1, -8));
- movq(Operand(destination, scratch, times_1, -8), length);
+ andl(scratch, Immediate(kPointerSize - 1));
+ movq(length, Operand(source, scratch, times_1, -kPointerSize));
+ movq(Operand(destination, scratch, times_1, -kPointerSize), length);
addq(destination, scratch);
if (min_length <= kLongStringLimit) {
diff --git a/src/x64/regexp-macro-assembler-x64.cc b/src/x64/regexp-macro-assembler-x64.cc
index efb2a65..e1d4a2d 100644
--- a/src/x64/regexp-macro-assembler-x64.cc
+++ b/src/x64/regexp-macro-assembler-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "serialize.h"
#include "unicode.h"
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
index 9dddd79..1a992b4 100644
--- a/src/x64/stub-cache-x64.cc
+++ b/src/x64/stub-cache-x64.cc
@@ -27,7 +27,7 @@
#include "v8.h"
-#if defined(V8_TARGET_ARCH_X64)
+#if V8_TARGET_ARCH_X64
#include "ic-inl.h"
#include "codegen.h"
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 0811093..a65de86 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -26,10 +26,11 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
- 'includes': ['../../build/common.gypi'],
'variables': {
+ 'v8_code': 1,
'generated_file': '<(SHARED_INTERMEDIATE_DIR)/resources.cc',
},
+ 'includes': ['../../build/common.gypi'],
'targets': [
{
'target_name': 'cctest',
diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc
index 90a9389..f8b492b 100644
--- a/test/cctest/test-api.cc
+++ b/test/cctest/test-api.cc
@@ -4502,6 +4502,47 @@
}
+void TryCatchMixedNestingCheck(v8::TryCatch* try_catch) {
+ CHECK(try_catch->HasCaught());
+ Handle<Message> message = try_catch->Message();
+ Handle<Value> resource = message->GetScriptResourceName();
+ CHECK_EQ(0, strcmp(*v8::String::Utf8Value(resource), "inner"));
+ CHECK_EQ(0, strcmp(*v8::String::Utf8Value(message->Get()),
+ "Uncaught Error: a"));
+ CHECK_EQ(1, message->GetLineNumber());
+ CHECK_EQ(6, message->GetStartColumn());
+}
+
+
+void TryCatchMixedNestingHelper(
+ const v8::FunctionCallbackInfo<v8::Value>& args) {
+ ApiTestFuzzer::Fuzz();
+ v8::TryCatch try_catch;
+ CompileRunWithOrigin("throw new Error('a');\n", "inner", 0, 0);
+ CHECK(try_catch.HasCaught());
+ TryCatchMixedNestingCheck(&try_catch);
+ try_catch.ReThrow();
+}
+
+
+// This test ensures that an outer TryCatch in the following situation:
+// C++/TryCatch -> JS -> C++/TryCatch -> JS w/ SyntaxError
+// does not clobber the Message object generated for the inner TryCatch.
+// This exercises the ability of TryCatch.ReThrow() to restore the
+// inner pending Message before throwing the exception again.
+TEST(TryCatchMixedNesting) {
+ v8::HandleScope scope(v8::Isolate::GetCurrent());
+ v8::V8::Initialize();
+ v8::TryCatch try_catch;
+ Local<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->Set(v8_str("TryCatchMixedNestingHelper"),
+ v8::FunctionTemplate::New(TryCatchMixedNestingHelper));
+ LocalContext context(0, templ);
+ CompileRunWithOrigin("TryCatchMixedNestingHelper();\n", "outer", 1, 1);
+ TryCatchMixedNestingCheck(&try_catch);
+}
+
+
THREADED_TEST(Equality) {
LocalContext context;
v8::Isolate* isolate = context->GetIsolate();
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 9a2496a..223f5fc 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -31,6 +31,7 @@
#include "v8.h"
#include "cpu-profiler-inl.h"
#include "cctest.h"
+#include "platform.h"
#include "utils.h"
#include "../include/v8-profiler.h"
#undef V8_DISABLE_DEPRECATIONS
@@ -50,7 +51,7 @@
TEST(StartStop) {
CpuProfilesCollection profiles;
ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
+ ProfilerEventsProcessor processor(&generator);
processor.Start();
processor.Stop();
processor.Join();
@@ -97,64 +98,89 @@
} // namespace
+
+i::Code* CreateCode(LocalContext* env) {
+ static int counter = 0;
+ i::EmbeddedVector<char, 256> script;
+ i::EmbeddedVector<char, 32> name;
+
+ i::OS::SNPrintF(name, "function_%d", ++counter);
+ const char* name_start = name.start();
+ i::OS::SNPrintF(script,
+ "function %s() {\n"
+ "var counter = 0;\n"
+ "for (var i = 0; i < %d; ++i) counter += i;\n"
+ "return '%s_' + counter;\n"
+ "}\n"
+ "%s();\n", name_start, counter, name_start, name_start);
+ CompileRun(script.start());
+ i::Handle<i::JSFunction> fun = v8::Utils::OpenHandle(
+ *v8::Local<v8::Function>::Cast(
+ (*env)->Global()->Get(v8_str(name_start))));
+ return fun->code();
+}
+
+
TEST(CodeEvents) {
CcTest::InitializeVM();
+ LocalContext env;
i::Isolate* isolate = i::Isolate::Current();
- i::Heap* heap = isolate->heap();
i::Factory* factory = isolate->factory();
TestSetup test_setup;
- CpuProfilesCollection profiles;
- profiles.StartProfiling("", 1, false);
- ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
+
+ i::HandleScope scope(isolate);
+
+ i::Code* aaa_code = CreateCode(&env);
+ i::Code* comment_code = CreateCode(&env);
+ i::Code* args5_code = CreateCode(&env);
+ i::Code* comment2_code = CreateCode(&env);
+ i::Code* moved_code = CreateCode(&env);
+ i::Code* args3_code = CreateCode(&env);
+ i::Code* args4_code = CreateCode(&env);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection;
+ profiles->StartProfiling("", 1, false);
+ ProfileGenerator generator(profiles);
+ ProfilerEventsProcessor processor(&generator);
processor.Start();
+ CpuProfiler profiler(isolate, profiles, &generator, &processor);
// Enqueue code creation events.
- i::HandleScope scope(isolate);
const char* aaa_str = "aaa";
i::Handle<i::String> aaa_name = factory->NewStringFromAscii(
i::Vector<const char>(aaa_str, i::StrLength(aaa_str)));
- processor.CodeCreateEvent(i::Logger::FUNCTION_TAG,
- *aaa_name,
- heap->empty_string(),
- 0,
- ToAddress(0x1000),
- 0x100,
- ToAddress(0x10000),
- NULL);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "bbb",
- ToAddress(0x1200),
- 0x80);
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "ddd",
- ToAddress(0x1400),
- 0x80);
- processor.CodeMoveEvent(ToAddress(0x1400), ToAddress(0x1500));
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 3, ToAddress(0x1600), 0x10);
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 4, ToAddress(0x1605), 0x10);
+ profiler.CodeCreateEvent(i::Logger::FUNCTION_TAG, aaa_code, *aaa_name);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment_code, "comment");
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, args5_code, 5);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, comment2_code, "comment2");
+ profiler.CodeMoveEvent(comment2_code->address(), moved_code->address());
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, args3_code, 3);
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, args4_code, 4);
+
// Enqueue a tick event to enable code events processing.
- EnqueueTickSampleEvent(&processor, ToAddress(0x1000));
+ EnqueueTickSampleEvent(&processor, aaa_code->address());
processor.Stop();
processor.Join();
// Check the state of profile generator.
- CodeEntry* entry1 = generator.code_map()->FindEntry(ToAddress(0x1000));
- CHECK_NE(NULL, entry1);
- CHECK_EQ(aaa_str, entry1->name());
- CodeEntry* entry2 = generator.code_map()->FindEntry(ToAddress(0x1200));
- CHECK_NE(NULL, entry2);
- CHECK_EQ("bbb", entry2->name());
- CodeEntry* entry3 = generator.code_map()->FindEntry(ToAddress(0x1300));
- CHECK_NE(NULL, entry3);
- CHECK_EQ("5", entry3->name());
- CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1400)));
- CodeEntry* entry4 = generator.code_map()->FindEntry(ToAddress(0x1500));
- CHECK_NE(NULL, entry4);
- CHECK_EQ("ddd", entry4->name());
- CHECK_EQ(NULL, generator.code_map()->FindEntry(ToAddress(0x1600)));
+ CodeEntry* aaa = generator.code_map()->FindEntry(aaa_code->address());
+ CHECK_NE(NULL, aaa);
+ CHECK_EQ(aaa_str, aaa->name());
+
+ CodeEntry* comment = generator.code_map()->FindEntry(comment_code->address());
+ CHECK_NE(NULL, comment);
+ CHECK_EQ("comment", comment->name());
+
+ CodeEntry* args5 = generator.code_map()->FindEntry(args5_code->address());
+ CHECK_NE(NULL, args5);
+ CHECK_EQ("5", args5->name());
+
+ CHECK_EQ(NULL, generator.code_map()->FindEntry(comment2_code->address()));
+
+ CodeEntry* comment2 = generator.code_map()->FindEntry(moved_code->address());
+ CHECK_NE(NULL, comment2);
+ CHECK_EQ("comment2", comment2->name());
}
@@ -165,32 +191,40 @@
TEST(TickEvents) {
TestSetup test_setup;
- CpuProfilesCollection profiles;
- profiles.StartProfiling("", 1, false);
- ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
- processor.Start();
+ LocalContext env;
+ i::Isolate* isolate = i::Isolate::Current();
+ i::HandleScope scope(isolate);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "bbb",
- ToAddress(0x1200),
- 0x80);
- processor.CodeCreateEvent(i::Logger::STUB_TAG, 5, ToAddress(0x1300), 0x10);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "ddd",
- ToAddress(0x1400),
- 0x80);
- EnqueueTickSampleEvent(&processor, ToAddress(0x1210));
- EnqueueTickSampleEvent(&processor, ToAddress(0x1305), ToAddress(0x1220));
- EnqueueTickSampleEvent(&processor,
- ToAddress(0x1404),
- ToAddress(0x1305),
- ToAddress(0x1230));
+ i::Code* frame1_code = CreateCode(&env);
+ i::Code* frame2_code = CreateCode(&env);
+ i::Code* frame3_code = CreateCode(&env);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection;
+ profiles->StartProfiling("", 1, false);
+ ProfileGenerator generator(profiles);
+ ProfilerEventsProcessor processor(&generator);
+ processor.Start();
+ CpuProfiler profiler(isolate, profiles, &generator, &processor);
+
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame1_code, "bbb");
+ profiler.CodeCreateEvent(i::Logger::STUB_TAG, frame2_code, 5);
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, frame3_code, "ddd");
+
+ EnqueueTickSampleEvent(&processor, frame1_code->instruction_start());
+ EnqueueTickSampleEvent(
+ &processor,
+ frame2_code->instruction_start() + frame2_code->ExecutableSize() / 2,
+ frame1_code->instruction_start() + frame2_code->ExecutableSize() / 2);
+ EnqueueTickSampleEvent(
+ &processor,
+ frame3_code->instruction_end() - 1,
+ frame2_code->instruction_end() - 1,
+ frame1_code->instruction_end() - 1);
processor.Stop();
processor.Join();
CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
CHECK_NE(NULL, profile);
// Check call trees.
@@ -229,29 +263,33 @@
// Long stacks (exceeding max frames limit) must not be erased.
TEST(Issue1398) {
TestSetup test_setup;
- CpuProfilesCollection profiles;
- profiles.StartProfiling("", 1, false);
- ProfileGenerator generator(&profiles);
- ProfilerEventsProcessor processor(&generator, &profiles);
- processor.Start();
+ LocalContext env;
+ i::Isolate* isolate = i::Isolate::Current();
+ i::HandleScope scope(isolate);
- processor.CodeCreateEvent(i::Logger::BUILTIN_TAG,
- "bbb",
- ToAddress(0x1200),
- 0x80);
+ i::Code* code = CreateCode(&env);
+
+ CpuProfilesCollection* profiles = new CpuProfilesCollection;
+ profiles->StartProfiling("", 1, false);
+ ProfileGenerator generator(profiles);
+ ProfilerEventsProcessor processor(&generator);
+ processor.Start();
+ CpuProfiler profiler(isolate, profiles, &generator, &processor);
+
+ profiler.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
i::TickSample* sample = processor.TickSampleEvent();
- sample->pc = ToAddress(0x1200);
+ sample->pc = code->address();
sample->tos = 0;
sample->frames_count = i::TickSample::kMaxFramesCount;
for (int i = 0; i < sample->frames_count; ++i) {
- sample->stack[i] = ToAddress(0x1200);
+ sample->stack[i] = code->address();
}
processor.Stop();
processor.Join();
CpuProfile* profile =
- profiles.StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
+ profiles->StopProfiling(TokenEnumerator::kNoSecurityToken, "", 1);
CHECK_NE(NULL, profile);
int actual_depth = 0;
@@ -412,6 +450,26 @@
}
+TEST(GetProfilerWhenIsolateIsNotInitialized) {
+ v8::Isolate* isolate = v8::Isolate::GetCurrent();
+ CHECK(i::Isolate::Current()->IsDefaultIsolate());
+ CHECK(!i::Isolate::Current()->IsInitialized());
+ CHECK_EQ(NULL, isolate->GetCpuProfiler());
+ {
+ v8::Isolate::Scope isolateScope(isolate);
+ LocalContext env;
+ v8::HandleScope scope(isolate);
+ CHECK_NE(NULL, isolate->GetCpuProfiler());
+ isolate->GetCpuProfiler()->StartCpuProfiling(v8::String::New("Test"));
+ isolate->GetCpuProfiler()->StopCpuProfiling(v8::String::New("Test"));
+ }
+ CHECK(i::Isolate::Current()->IsInitialized());
+ CHECK_NE(NULL, isolate->GetCpuProfiler());
+ isolate->Dispose();
+ CHECK_EQ(NULL, isolate->GetCpuProfiler());
+}
+
+
static bool ContainsString(v8::Handle<v8::String> string,
const Vector<v8::Handle<v8::String> >& vector) {
for (int i = 0; i < vector.length(); i++) {
@@ -965,3 +1023,85 @@
cpu_profiler->DeleteAllCpuProfiles();
}
+
+
+static const char* call_function_test_source = "function bar(iterations) {\n"
+"}\n"
+"function start(duration) {\n"
+" var start = Date.now();\n"
+" while (Date.now() - start < duration) {\n"
+" try {\n"
+" bar.call(this, 10 * 1000);\n"
+" } catch(e) {}\n"
+" }\n"
+"}";
+
+
+// Test that if we sampled thread when it was inside FunctionCall buitin then
+// its caller frame will be '(unresolved function)' as we have no reliable way
+// to resolve it.
+//
+// [Top down]:
+// 96 0 (root) [-1] #1
+// 1 1 (garbage collector) [-1] #4
+// 5 0 (unresolved function) [-1] #5
+// 5 5 call [-1] #6
+// 71 70 start [-1] #3
+// 1 1 bar [-1] #7
+// 19 19 (program) [-1] #2
+TEST(FunctionCallSample) {
+ LocalContext env;
+ v8::HandleScope scope(env->GetIsolate());
+
+ v8::Script::Compile(v8::String::New(call_function_test_source))->Run();
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(
+ env->Global()->Get(v8::String::New("start")));
+
+ v8::CpuProfiler* cpu_profiler = env->GetIsolate()->GetCpuProfiler();
+ v8::Local<v8::String> profile_name = v8::String::New("my_profile");
+
+ cpu_profiler->StartCpuProfiling(profile_name);
+ int32_t duration_ms = 100;
+#if defined(_WIN32) || defined(_WIN64)
+ // 100ms is not enough on Windows. See
+ // https://code.google.com/p/v8/issues/detail?id=2628
+ duration_ms = 400;
+#endif
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(duration_ms) };
+ function->Call(env->Global(), ARRAY_SIZE(args), args);
+ const v8::CpuProfile* profile = cpu_profiler->StopCpuProfiling(profile_name);
+
+ CHECK_NE(NULL, profile);
+ // Dump collected profile to have a better diagnostic in case of failure.
+ reinterpret_cast<i::CpuProfile*>(
+ const_cast<v8::CpuProfile*>(profile))->Print();
+
+ const v8::CpuProfileNode* root = profile->GetTopDownRoot();
+ {
+ ScopedVector<v8::Handle<v8::String> > names(4);
+ names[0] = v8::String::New(ProfileGenerator::kGarbageCollectorEntryName);
+ names[1] = v8::String::New(ProfileGenerator::kProgramEntryName);
+ names[2] = v8::String::New("start");
+ names[3] = v8::String::New(i::ProfileGenerator::kUnresolvedFunctionName);
+ // Don't allow |bar| and |call| nodes to be at the top level.
+ CheckChildrenNames(root, names);
+ }
+
+ const v8::CpuProfileNode* startNode = GetChild(root, "start");
+ {
+ ScopedVector<v8::Handle<v8::String> > names(1);
+ names[0] = v8::String::New("bar");
+ CheckChildrenNames(startNode, names);
+ }
+
+ const v8::CpuProfileNode* unresolvedNode =
+ FindChild(root, i::ProfileGenerator::kUnresolvedFunctionName);
+ if (unresolvedNode) {
+ ScopedVector<v8::Handle<v8::String> > names(1);
+ names[0] = v8::String::New("call");
+ CheckChildrenNames(unresolvedNode, names);
+ }
+
+ cpu_profiler->DeleteAllCpuProfiles();
+}
+
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index 617e692..788f7af 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -509,7 +509,7 @@
Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
CHECK(Debug::HasDebugInfo(shared));
TestBreakLocationIterator it1(Debug::GetDebugInfo(shared));
- it1.FindBreakLocationFromPosition(position);
+ it1.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
v8::internal::RelocInfo::Mode actual_mode = it1.it()->rinfo()->rmode();
if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
actual_mode = v8::internal::RelocInfo::CODE_TARGET;
@@ -528,7 +528,7 @@
CHECK(!debug->HasDebugInfo(shared));
CHECK(debug->EnsureDebugInfo(shared, fun));
TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
- it2.FindBreakLocationFromPosition(position);
+ it2.FindBreakLocationFromPosition(position, v8::internal::STATEMENT_ALIGNED);
actual_mode = it2.it()->rinfo()->rmode();
if (actual_mode == v8::internal::RelocInfo::CODE_TARGET_WITH_ID) {
actual_mode = v8::internal::RelocInfo::CODE_TARGET;
diff --git a/test/cctest/test-hashing.cc b/test/cctest/test-hashing.cc
index 4906296..6536269 100644
--- a/test/cctest/test-hashing.cc
+++ b/test/cctest/test-hashing.cc
@@ -51,7 +51,7 @@
// GenerateHashInit takes the first character as an argument so it can't
// handle the zero length string.
ASSERT(string.length() > 0);
-#ifdef V8_TARGET_ARCH_IA32
+#if V8_TARGET_ARCH_IA32
__ push(ebx);
__ push(ecx);
__ mov(eax, Immediate(0));
@@ -116,7 +116,7 @@
void generate(MacroAssembler* masm, uint32_t key) {
-#ifdef V8_TARGET_ARCH_IA32
+#if V8_TARGET_ARCH_IA32
__ push(ebx);
__ mov(eax, Immediate(key));
__ GetNumberHash(eax, ebx);
diff --git a/test/cctest/test-lockers.cc b/test/cctest/test-lockers.cc
index 9d24535..072bbff 100644
--- a/test/cctest/test-lockers.cc
+++ b/test/cctest/test-lockers.cc
@@ -207,7 +207,7 @@
// Run many threads all locking on the same isolate
TEST(IsolateLockingStress) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -244,7 +244,7 @@
// Run many threads each accessing its own isolate without locking
TEST(MultithreadedParallelIsolates) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 10;
#else
const int kNThreads = 50;
@@ -282,7 +282,7 @@
// Run many threads with nested locks
TEST(IsolateNestedLocking) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -323,7 +323,7 @@
// Run parallel threads that lock and access different isolates in parallel
TEST(SeparateIsolatesLocksNonexclusive) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -399,7 +399,7 @@
// Use unlocker inside of a Locker, multiple threads.
TEST(LockerUnlocker) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -452,7 +452,7 @@
// Use Unlocker inside two Lockers.
TEST(LockTwiceAndUnlock) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -573,7 +573,7 @@
// Locker inside an Unlocker inside a Locker.
TEST(LockUnlockLockMultithreaded) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -628,7 +628,7 @@
// Locker inside an Unlocker inside a Locker for default isolate.
TEST(LockUnlockLockDefaultIsolateMultithreaded) {
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
const int kNThreads = 50;
#else
const int kNThreads = 100;
@@ -699,7 +699,7 @@
// Test installing extensions in separate isolates concurrently.
// http://code.google.com/p/v8/issues/detail?id=1821
TEST(ExtensionsRegistration) {
-#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_MIPS)
+#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS
const int kNThreads = 10;
#else
const int kNThreads = 40;
diff --git a/test/cctest/test-macro-assembler-x64.cc b/test/cctest/test-macro-assembler-x64.cc
index d4d0edb..3945f1b 100755
--- a/test/cctest/test-macro-assembler-x64.cc
+++ b/test/cctest/test-macro-assembler-x64.cc
@@ -1131,7 +1131,7 @@
void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
bool division_by_zero = (y == 0);
bool negative_zero = (x == 0 && y < 0);
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
#else
bool overflow = (x == Smi::kMinValue && y == -1);
diff --git a/test/cctest/test-mark-compact.cc b/test/cctest/test-mark-compact.cc
index a01c5df..8be72d3 100644
--- a/test/cctest/test-mark-compact.cc
+++ b/test/cctest/test-mark-compact.cc
@@ -566,4 +566,25 @@
}
}
+
+intptr_t ShortLivingIsolate() {
+ v8::Isolate* isolate = v8::Isolate::New();
+ { v8::Isolate::Scope isolate_scope(isolate);
+ v8::Locker lock(isolate);
+ v8::HandleScope handle_scope;
+ v8::Local<v8::Context> context = v8::Context::New(isolate);
+ CHECK(!context.IsEmpty());
+ }
+ isolate->Dispose();
+ return MemoryInUse();
+}
+
+
+TEST(RegressJoinThreadsOnIsolateDeinit) {
+ intptr_t size_limit = ShortLivingIsolate() * 2;
+ for (int i = 0; i < 10; i++) {
+ CHECK_GT(size_limit, ShortLivingIsolate());
+ }
+}
+
#endif // __linux__ and !USE_SIMULATOR
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index 17c9dd9..dfcc75c 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -87,17 +87,17 @@
TEST(ProfileNodeFindOrAddChild) {
ProfileTree tree;
ProfileNode node(&tree, NULL);
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
ProfileNode* childNode2 = node.FindOrAddChild(&entry2);
CHECK_NE(NULL, childNode2);
CHECK_NE(childNode1, childNode2);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
CHECK_EQ(childNode2, node.FindOrAddChild(&entry2));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileNode* childNode3 = node.FindOrAddChild(&entry3);
CHECK_NE(NULL, childNode3);
CHECK_NE(childNode1, childNode3);
@@ -109,19 +109,18 @@
TEST(ProfileNodeFindOrAddChildForSameFunction) {
- const char* empty = "";
const char* aaa = "aaa";
ProfileTree tree;
ProfileNode node(&tree, NULL);
- CodeEntry entry1(i::Logger::FUNCTION_TAG, empty, aaa);
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, aaa);
ProfileNode* childNode1 = node.FindOrAddChild(&entry1);
CHECK_NE(NULL, childNode1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry1));
// The same function again.
- CodeEntry entry2(i::Logger::FUNCTION_TAG, empty, aaa);
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, aaa);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry2));
// Now with a different security token.
- CodeEntry entry3(i::Logger::FUNCTION_TAG, empty, aaa,
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, aaa,
TokenEnumerator::kNoSecurityToken + 1);
CHECK_EQ(childNode1, node.FindOrAddChild(&entry3));
}
@@ -157,9 +156,9 @@
} // namespace
TEST(ProfileTreeAddPathFromStart) {
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
@@ -224,9 +223,9 @@
TEST(ProfileTreeAddPathFromEnd) {
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
ProfileTree tree;
ProfileTreeTestHelper helper(&tree);
CHECK_EQ(NULL, helper.Walk(&entry1));
@@ -304,7 +303,7 @@
CHECK_EQ(1, empty_tree.root()->total_ticks());
CHECK_EQ(1, empty_tree.root()->self_ticks());
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* e1_path[] = {&entry1};
Vector<CodeEntry*> e1_path_vec(
e1_path, sizeof(e1_path) / sizeof(e1_path[0]));
@@ -325,7 +324,7 @@
CHECK_EQ(1, node1->total_ticks());
CHECK_EQ(1, node1->self_ticks());
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* e1_e2_path[] = {&entry1, &entry2};
Vector<CodeEntry*> e1_e2_path_vec(
e1_e2_path, sizeof(e1_e2_path) / sizeof(e1_e2_path[0]));
@@ -360,7 +359,7 @@
CodeEntry* e2_path[] = {&entry2};
Vector<CodeEntry*> e2_path_vec(
e2_path, sizeof(e2_path) / sizeof(e2_path[0]));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
CodeEntry* e3_path[] = {&entry3};
Vector<CodeEntry*> e3_path_vec(
e3_path, sizeof(e3_path) / sizeof(e3_path[0]));
@@ -418,10 +417,10 @@
TEST(ProfileTreeFilteredClone) {
ProfileTree source_tree;
const int token0 = 0, token1 = 1, token2 = 2;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", token0);
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb", token1);
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc", token0);
- CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd",
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa", token0);
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb", token1);
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc", token0);
+ CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd",
TokenEnumerator::kInheritsSecurityToken);
{
@@ -519,10 +518,10 @@
TEST(CodeMapAddCode) {
CodeMap code_map;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
- CodeEntry entry4(i::Logger::FUNCTION_TAG, "", "ddd");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
+ CodeEntry entry4(i::Logger::FUNCTION_TAG, "ddd");
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
code_map.AddCode(ToAddress(0x1900), &entry3, 0x50);
@@ -549,8 +548,8 @@
TEST(CodeMapMoveAndDeleteCode) {
CodeMap code_map;
- CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa");
- CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "bbb");
+ CodeEntry entry1(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry entry2(i::Logger::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), &entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), &entry2, 0x100);
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1500)));
@@ -558,7 +557,7 @@
code_map.MoveCode(ToAddress(0x1500), ToAddress(0x1700)); // Deprecate bbb.
CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1500)));
CHECK_EQ(&entry1, code_map.FindEntry(ToAddress(0x1700)));
- CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "ccc");
+ CodeEntry entry3(i::Logger::FUNCTION_TAG, "ccc");
code_map.AddCode(ToAddress(0x1750), &entry3, 0x100);
CHECK_EQ(NULL, code_map.FindEntry(ToAddress(0x1700)));
CHECK_EQ(&entry3, code_map.FindEntry(ToAddress(0x1750)));
@@ -906,3 +905,62 @@
for (int i = 0; i < CpuProfilesCollection::kMaxSimultaneousProfiles; ++i)
i::DeleteArray(titles[i]);
}
+
+
+static const v8::CpuProfileNode* PickChild(const v8::CpuProfileNode* parent,
+ const char* name) {
+ for (int i = 0; i < parent->GetChildrenCount(); ++i) {
+ const v8::CpuProfileNode* child = parent->GetChild(i);
+ v8::String::AsciiValue function_name(child->GetFunctionName());
+ if (strcmp(*function_name, name) == 0) return child;
+ }
+ return NULL;
+}
+
+
+TEST(ProfileNodeScriptId) {
+ // This test does not pass with inlining enabled since inlined functions
+ // don't appear in the stack trace.
+ i::FLAG_use_inlining = false;
+
+ const char* extensions[] = { "v8/profiler" };
+ v8::ExtensionConfiguration config(1, extensions);
+ LocalContext env(&config);
+ v8::HandleScope hs(env->GetIsolate());
+
+ v8::CpuProfiler* profiler = env->GetIsolate()->GetCpuProfiler();
+ CHECK_EQ(0, profiler->GetProfileCount());
+ v8::Handle<v8::Script> script_a = v8::Script::Compile(v8::String::New(
+ "function a() { startProfiling(); }\n"));
+ script_a->Run();
+ v8::Handle<v8::Script> script_b = v8::Script::Compile(v8::String::New(
+ "function b() { a(); }\n"
+ "b();\n"
+ "stopProfiling();\n"));
+ script_b->Run();
+ CHECK_EQ(1, profiler->GetProfileCount());
+ const v8::CpuProfile* profile = profiler->GetCpuProfile(0);
+ const v8::CpuProfileNode* current = profile->GetTopDownRoot();
+ reinterpret_cast<ProfileNode*>(
+ const_cast<v8::CpuProfileNode*>(current))->Print(0);
+ // The tree should look like this:
+ // (root)
+ // (anonymous function)
+ // b
+ // a
+ // There can also be:
+ // startProfiling
+ // if the sampler managed to get a tick.
+ current = PickChild(current, i::ProfileGenerator::kAnonymousFunctionName);
+ CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+
+ current = PickChild(current, "b");
+ CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+ CHECK_EQ(script_b->GetId(), current->GetScriptId());
+
+ current = PickChild(current, "a");
+ CHECK_NE(NULL, const_cast<v8::CpuProfileNode*>(current));
+ CHECK_EQ(script_a->GetId(), current->GetScriptId());
+}
+
+
diff --git a/test/cctest/test-regexp.cc b/test/cctest/test-regexp.cc
index f810fcd..f9eed1f 100644
--- a/test/cctest/test-regexp.cc
+++ b/test/cctest/test-regexp.cc
@@ -44,22 +44,22 @@
#else // V8_INTERPRETED_REGEXP
#include "macro-assembler.h"
#include "code.h"
-#ifdef V8_TARGET_ARCH_ARM
+#if V8_TARGET_ARCH_ARM
#include "arm/assembler-arm.h"
#include "arm/macro-assembler-arm.h"
#include "arm/regexp-macro-assembler-arm.h"
#endif
-#ifdef V8_TARGET_ARCH_MIPS
+#if V8_TARGET_ARCH_MIPS
#include "mips/assembler-mips.h"
#include "mips/macro-assembler-mips.h"
#include "mips/regexp-macro-assembler-mips.h"
#endif
-#ifdef V8_TARGET_ARCH_X64
+#if V8_TARGET_ARCH_X64
#include "x64/assembler-x64.h"
#include "x64/macro-assembler-x64.h"
#include "x64/regexp-macro-assembler-x64.h"
#endif
-#ifdef V8_TARGET_ARCH_IA32
+#if V8_TARGET_ARCH_IA32
#include "ia32/assembler-ia32.h"
#include "ia32/macro-assembler-ia32.h"
#include "ia32/regexp-macro-assembler-ia32.h"
diff --git a/test/mjsunit/array-feedback.js b/test/mjsunit/array-feedback.js
index c602018..d1b3062 100644
--- a/test/mjsunit/array-feedback.js
+++ b/test/mjsunit/array-feedback.js
@@ -179,13 +179,16 @@
a[0] = 3.5;
%OptimizeFunctionOnNextCall(create0);
create0();
- create0();
- b = create0();
- assertKind(elements_kind.fast_smi_only, b);
- b[0] = 3.5;
- c = create0();
- assertKind(elements_kind.fast_double, c);
- assertTrue(2 != %GetOptimizationStatus(create0));
+ // This test only makes sense if crankshaft is allowed
+ if (4 != %GetOptimizationStatus(create0)) {
+ create0();
+ b = create0();
+ assertKind(elements_kind.fast_smi_only, b);
+ b[0] = 3.5;
+ c = create0();
+ assertKind(elements_kind.fast_double, c);
+ assertTrue(2 != %GetOptimizationStatus(create0));
+ }
})();
diff --git a/test/mjsunit/debug-breakpoints.js b/test/mjsunit/debug-breakpoints.js
index 1302034..148acfc 100644
--- a/test/mjsunit/debug-breakpoints.js
+++ b/test/mjsunit/debug-breakpoints.js
@@ -29,7 +29,7 @@
// Get the Debug object exposed from the debug context global object.
Debug = debug.Debug
-function f() {a=1;b=2};
+function f() {a=1;b=2}
function g() {
a=1;
b=2;
@@ -121,13 +121,13 @@
// Tests for setting break points by script id and position.
-function setBreakpointByPosition(f, position)
+function setBreakpointByPosition(f, position, opt_position_alignment)
{
var break_point = Debug.setBreakPointByScriptIdAndPosition(
Debug.findScript(f).id,
position + Debug.sourcePosition(f),
"",
- true);
+ true, opt_position_alignment);
return break_point.number();
}
@@ -204,3 +204,22 @@
//b=2;
//}
assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0);
+
+// Tests for setting break points without statement aligment.
+// (This may be sensitive to compiler break position map generation).
+function h() {a=f(f2(1,2),f3())+f3();b=f3();}
+var scenario = [
+ [5, "{a[B0]=f"],
+ [6, "{a=[B0]f("],
+ [7, "{a=f([B0]f2("],
+ [16, "f2(1,2),[B0]f3()"],
+ [22, "+[B0]f3()"]
+];
+for(var i = 0; i < scenario.length; i++) {
+ bp1 = setBreakpointByPosition(h, scenario[i][0],
+ Debug.BreakPositionAlignment.BreakPosition);
+ assertTrue(Debug.showBreakPoints(h, undefined,
+ Debug.BreakPositionAlignment.BreakPosition).indexOf(scenario[i][1]) > 0);
+ Debug.clearBreakPoint(bp1);
+}
+
diff --git a/test/mjsunit/fuzz-natives-part1.js b/test/mjsunit/fuzz-natives-part1.js
index 6fd2c08..8ca523c 100644
--- a/test/mjsunit/fuzz-natives-part1.js
+++ b/test/mjsunit/fuzz-natives-part1.js
@@ -163,6 +163,8 @@
"ResolvePossiblyDirectEval": true,
"Log": true,
"DeclareGlobals": true,
+ "ArrayConstructor": true,
+ "InternalArrayConstructor": true,
"PromoteScheduledException": true,
"DeleteHandleScopeExtensions": true,
@@ -214,7 +216,9 @@
var currentlyUncallable = {
// We need to find a way to test this without breaking the system.
- "SystemBreak": true
+ "SystemBreak": true,
+ // Inserts an int3/stop instruction when run with --always-opt.
+ "_DebugBreakInOptimizedCode": true
};
function testNatives() {
diff --git a/test/mjsunit/fuzz-natives-part2.js b/test/mjsunit/fuzz-natives-part2.js
index 463bd09..ec84f35 100644
--- a/test/mjsunit/fuzz-natives-part2.js
+++ b/test/mjsunit/fuzz-natives-part2.js
@@ -153,6 +153,7 @@
"ParallelRecompile": true,
"InstallRecompiledCode": true,
"NotifyDeoptimized": true,
+ "NotifyStubFailure": true,
"NotifyOSR": true,
"CreateObjectLiteralBoilerplate": true,
"CloneLiteralBoilerplate": true,
@@ -215,7 +216,9 @@
var currentlyUncallable = {
// We need to find a way to test this without breaking the system.
- "SystemBreak": true
+ "SystemBreak": true,
+ // Inserts an int3/stop instruction when run with --always-opt.
+ "_DebugBreakInOptimizedCode": true
};
function testNatives() {
diff --git a/test/mjsunit/fuzz-natives-part3.js b/test/mjsunit/fuzz-natives-part3.js
index fa64daa..928fb46 100644
--- a/test/mjsunit/fuzz-natives-part3.js
+++ b/test/mjsunit/fuzz-natives-part3.js
@@ -153,6 +153,7 @@
"ParallelRecompile": true,
"InstallRecompiledCode": true,
"NotifyDeoptimized": true,
+ "NotifyStubFailure": true,
"NotifyOSR": true,
"CreateObjectLiteralBoilerplate": true,
"CloneLiteralBoilerplate": true,
@@ -162,6 +163,8 @@
"ResolvePossiblyDirectEval": true,
"Log": true,
"DeclareGlobals": true,
+ "ArrayConstructor": true,
+ "InternalArrayConstructor": true,
"PromoteScheduledException": true,
"DeleteHandleScopeExtensions": true,
@@ -213,7 +216,9 @@
var currentlyUncallable = {
// We need to find a way to test this without breaking the system.
- "SystemBreak": true
+ "SystemBreak": true,
+ // Inserts an int3/stop instruction when run with --always-opt.
+ "_DebugBreakInOptimizedCode": true
};
function testNatives() {
diff --git a/test/mjsunit/fuzz-natives-part4.js b/test/mjsunit/fuzz-natives-part4.js
index 4003df8..d47db34 100644
--- a/test/mjsunit/fuzz-natives-part4.js
+++ b/test/mjsunit/fuzz-natives-part4.js
@@ -153,6 +153,7 @@
"ParallelRecompile": true,
"InstallRecompiledCode": true,
"NotifyDeoptimized": true,
+ "NotifyStubFailure": true,
"NotifyOSR": true,
"CreateObjectLiteralBoilerplate": true,
"CloneLiteralBoilerplate": true,
@@ -162,6 +163,8 @@
"ResolvePossiblyDirectEval": true,
"Log": true,
"DeclareGlobals": true,
+ "ArrayConstructor": true,
+ "InternalArrayConstructor": true,
"PromoteScheduledException": true,
"DeleteHandleScopeExtensions": true,
@@ -213,7 +216,9 @@
var currentlyUncallable = {
// We need to find a way to test this without breaking the system.
- "SystemBreak": true
+ "SystemBreak": true,
+ // Inserts an int3/stop instruction when run with --always-opt.
+ "_DebugBreakInOptimizedCode": true
};
function testNatives() {
diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js
index d60c59c..cf18745 100644
--- a/test/mjsunit/harmony/collections.js
+++ b/test/mjsunit/harmony/collections.js
@@ -377,17 +377,39 @@
assertEquals(i, m.size);
}
-// Test clear
-var a = new Set();
-s.add(42);
-assertTrue(s.has(42));
-s.clear();
-assertFalse(s.has(42));
-assertEquals(0, s.size);
-var m = new Map();
-m.set(42, true);
-assertTrue(m.has(42));
-m.clear();
-assertFalse(m.has(42));
-assertEquals(0, m.size);
+// Test Set clear
+(function() {
+ var s = new Set();
+ s.add(42);
+ assertTrue(s.has(42));
+ assertEquals(1, s.size);
+ s.clear();
+ assertFalse(s.has(42));
+ assertEquals(0, s.size);
+})();
+
+
+// Test Map clear
+(function() {
+ var m = new Map();
+ m.set(42, true);
+ assertTrue(m.has(42));
+ assertEquals(1, m.size);
+ m.clear();
+ assertFalse(m.has(42));
+ assertEquals(0, m.size);
+})();
+
+
+// Test WeakMap clear
+(function() {
+ var k = new Object();
+ var w = new WeakMap();
+ w.set(k, 23);
+ assertTrue(w.has(k));
+ assertEquals(23, w.get(k));
+ w.clear();
+ assertFalse(w.has(k));
+ assertEquals(undefined, w.get(k));
+})();
diff --git a/test/webkit/parse-backslash-before-newline-expected.txt b/test/webkit/parse-backslash-before-newline-expected.txt
deleted file mode 100644
index ed8cba9..0000000
--- a/test/webkit/parse-backslash-before-newline-expected.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2013 the V8 project authors. All rights reserved.
-# Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
-# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-PASS "teststring with CR LF" is "teststring with CR LF"
-PASS "teststring with LF CR" is "teststring with LF CR"
-PASS "teststring with CR" is "teststring with CR"
-PASS "teststring with LF" is "teststring with LF"
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
diff --git a/test/webkit/parse-backslash-before-newline.js b/test/webkit/parse-backslash-before-newline.js
deleted file mode 100644
index d0a6fec..0000000
--- a/test/webkit/parse-backslash-before-newline.js
+++ /dev/null
Binary files differ
diff --git a/tools/blink_tests/TestExpectations b/tools/blink_tests/TestExpectations
index 421bb2c..5c75db0 100644
--- a/tools/blink_tests/TestExpectations
+++ b/tools/blink_tests/TestExpectations
@@ -1,28 +1,19 @@
-# Created by test_result_analyzer.py
-# Date: 2013-06-07 15:09:29.286522
-# Waterfall: v8_blink
-# Revision type: webkit
-# Fail ratio: 0.2
-[ Linux Release x86 ] fast/js/JSON-stringify.html [ Skip ]
-[ Linux Release x86 ] fast/text/atsui-multiple-renderers.html [ Skip ]
-[ Linux Release x86 ] fast/text/international/complex-joining-using-gpos.html [ Skip ]
-[ Linux Release x86 ] fast/text/international/danda-space.html [ Skip ]
-[ Linux Release x86 ] fast/text/international/thai-baht-space.html [ Skip ]
-[ Linux Release x86 ] fast/text/international/thai-line-breaks.html [ Skip ]
-[ Linux Release x86 ] inspector/profiler/memory-instrumentation-external-array.html [ Skip ]
-[ Linux Release x86_64 ] fast/text/atsui-multiple-renderers.html [ Skip ]
-[ Linux Release x86_64 ] fast/text/international/complex-joining-using-gpos.html [ Skip ]
-[ Linux Release x86_64 ] fast/text/international/danda-space.html [ Skip ]
-[ Linux Release x86_64 ] fast/text/international/thai-baht-space.html [ Skip ]
-[ Linux Release x86_64 ] fast/text/international/thai-line-breaks.html [ Skip ]
-[ Linux Release x86_64 ] inspector/profiler/memory-instrumentation-external-array.html [ Skip ]
-[ Linux Debug ] fast/text/atsui-multiple-renderers.html [ Skip ]
-[ Linux Debug ] fast/text/international/complex-joining-using-gpos.html [ Skip ]
-[ Linux Debug ] fast/text/international/danda-space.html [ Skip ]
-[ Linux Debug ] fast/text/international/thai-baht-space.html [ Skip ]
-[ Linux Debug ] fast/text/international/thai-line-breaks.html [ Skip ]
-
-# Manually added tests:
-
-# Fails sometimes on all platforms:
-fast/js/concat-large-strings-crash.html [ Skip ]
+# Tests that sometimes fail only on the V8 waterfall:
+[ Linux Release x86 ] fast/js/JSON-stringify.html [ Pass Failure Slow ]
+[ Linux Release x86 ] fast/text/atsui-multiple-renderers.html [ Pass Failure Slow ]
+[ Linux Release x86 ] fast/text/international/complex-joining-using-gpos.html [ Pass Failure Slow ]
+[ Linux Release x86 ] fast/text/international/danda-space.html [ Pass Failure Slow ]
+[ Linux Release x86 ] fast/text/international/thai-baht-space.html [ Pass Failure Slow ]
+[ Linux Release x86 ] fast/text/international/thai-line-breaks.html [ Pass Failure Slow ]
+[ Linux Release x86 ] inspector/profiler/memory-instrumentation-external-array.html [ Pass Failure Slow ]
+[ Linux Release x86_64 ] fast/text/atsui-multiple-renderers.html [ Pass Failure Slow ]
+[ Linux Release x86_64 ] fast/text/international/complex-joining-using-gpos.html [ Pass Failure Slow ]
+[ Linux Release x86_64 ] fast/text/international/danda-space.html [ Pass Failure Slow ]
+[ Linux Release x86_64 ] fast/text/international/thai-baht-space.html [ Pass Failure Slow ]
+[ Linux Release x86_64 ] fast/text/international/thai-line-breaks.html [ Pass Failure Slow ]
+[ Linux Release x86_64 ] inspector/profiler/memory-instrumentation-external-array.html [ Pass Failure Slow ]
+[ Linux Debug ] fast/text/atsui-multiple-renderers.html [ Pass Failure Slow ]
+[ Linux Debug ] fast/text/international/complex-joining-using-gpos.html [ Pass Failure Slow ]
+[ Linux Debug ] fast/text/international/danda-space.html [ Pass Failure Slow ]
+[ Linux Debug ] fast/text/international/thai-baht-space.html [ Pass Failure Slow ]
+[ Linux Debug ] fast/text/international/thai-line-breaks.html [ Pass Failure Slow ]
diff --git a/tools/generate_shim_headers/generate_shim_headers.py b/tools/generate_shim_headers/generate_shim_headers.py
new file mode 100755
index 0000000..d0e6d06
--- /dev/null
+++ b/tools/generate_shim_headers/generate_shim_headers.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+#
+# Copyright 2013 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+Generates shim headers that mirror the directory structure of bundled headers,
+but just forward to the system ones.
+
+This allows seamless compilation against system headers with no changes
+to our source code.
+"""
+
+
+import optparse
+import os.path
+import sys
+
+
+def GeneratorMain(argv):
+ parser = optparse.OptionParser()
+ parser.add_option('--headers-root', action='append')
+ parser.add_option('--define', action='append')
+ parser.add_option('--output-directory')
+ parser.add_option('--prefix', default='')
+ parser.add_option('--use-include-next', action='store_true')
+ parser.add_option('--outputs', action='store_true')
+ parser.add_option('--generate', action='store_true')
+
+ options, args = parser.parse_args(argv)
+
+ if not options.headers_root:
+ parser.error('Missing --headers-root parameter.')
+ if not options.output_directory:
+ parser.error('Missing --output-directory parameter.')
+ if not args:
+ parser.error('Missing arguments - header file names.')
+
+ source_tree_root = os.path.abspath(
+ os.path.join(os.path.dirname(__file__), '..', '..'))
+
+ for root in options.headers_root:
+ target_directory = os.path.join(
+ options.output_directory,
+ os.path.relpath(root, source_tree_root))
+ if options.generate and not os.path.exists(target_directory):
+ os.makedirs(target_directory)
+
+ for header_spec in args:
+ if ';' in header_spec:
+ (header_filename,
+ include_before,
+ include_after) = header_spec.split(';', 2)
+ else:
+ header_filename = header_spec
+ include_before = ''
+ include_after = ''
+ if options.outputs:
+ yield os.path.join(target_directory, header_filename)
+ if options.generate:
+ with open(os.path.join(target_directory, header_filename), 'w') as f:
+ if options.define:
+ for define in options.define:
+ key, value = define.split('=', 1)
+ # This non-standard push_macro extension is supported
+ # by compilers we support (GCC, clang).
+ f.write('#pragma push_macro("%s")\n' % key)
+ f.write('#undef %s\n' % key)
+ f.write('#define %s %s\n' % (key, value))
+
+ if include_before:
+ for header in include_before.split(':'):
+ f.write('#include %s\n' % header)
+
+ include_target = options.prefix + header_filename
+ if options.use_include_next:
+ f.write('#include_next <%s>\n' % include_target)
+ else:
+ f.write('#include <%s>\n' % include_target)
+
+ if include_after:
+ for header in include_after.split(':'):
+ f.write('#include %s\n' % header)
+
+ if options.define:
+ for define in options.define:
+ key, value = define.split('=', 1)
+ # This non-standard pop_macro extension is supported
+ # by compilers we support (GCC, clang).
+ f.write('#pragma pop_macro("%s")\n' % key)
+
+
+def DoMain(argv):
+ return '\n'.join(GeneratorMain(argv))
+
+
+if __name__ == '__main__':
+ DoMain(sys.argv[1:])
diff --git a/tools/grokdump.py b/tools/grokdump.py
index 1be5cb8..ccdc4b3 100755
--- a/tools/grokdump.py
+++ b/tools/grokdump.py
@@ -31,6 +31,7 @@
import cmd
import codecs
import ctypes
+import datetime
import disasm
import mmap
import optparse
@@ -40,7 +41,6 @@
import sys
import types
-
USAGE="""usage: %prog [OPTIONS] [DUMP-FILE]
Minidump analyzer.
@@ -442,13 +442,29 @@
("threads", lambda t: MINIDUMP_THREAD.ctype * t.thread_count)
])
+MINIDUMP_VS_FIXEDFILEINFO = Descriptor([
+ ("dwSignature", ctypes.c_uint32),
+ ("dwStrucVersion", ctypes.c_uint32),
+ ("dwFileVersionMS", ctypes.c_uint32),
+ ("dwFileVersionLS", ctypes.c_uint32),
+ ("dwProductVersionMS", ctypes.c_uint32),
+ ("dwProductVersionLS", ctypes.c_uint32),
+ ("dwFileFlagsMask", ctypes.c_uint32),
+ ("dwFileFlags", ctypes.c_uint32),
+ ("dwFileOS", ctypes.c_uint32),
+ ("dwFileType", ctypes.c_uint32),
+ ("dwFileSubtype", ctypes.c_uint32),
+ ("dwFileDateMS", ctypes.c_uint32),
+ ("dwFileDateLS", ctypes.c_uint32)
+])
+
MINIDUMP_RAW_MODULE = Descriptor([
("base_of_image", ctypes.c_uint64),
("size_of_image", ctypes.c_uint32),
("checksum", ctypes.c_uint32),
("time_date_stamp", ctypes.c_uint32),
("module_name_rva", ctypes.c_uint32),
- ("version_info", ctypes.c_uint32 * 13),
+ ("version_info", MINIDUMP_VS_FIXEDFILEINFO.ctype),
("cv_record", MINIDUMP_LOCATION_DESCRIPTOR.ctype),
("misc_record", MINIDUMP_LOCATION_DESCRIPTOR.ctype),
("reserved0", ctypes.c_uint32 * 2),
@@ -785,8 +801,9 @@
try:
symfile = os.path.join(self.symdir,
modulename.replace('.', '_') + ".pdb.sym")
- self._LoadSymbolsFrom(symfile, module.base_of_image)
- self.modules_with_symbols.append(module)
+ if os.path.isfile(symfile):
+ self._LoadSymbolsFrom(symfile, module.base_of_image)
+ self.modules_with_symbols.append(module)
except Exception as e:
print " ... failure (%s)" % (e)
@@ -2011,6 +2028,21 @@
print "Available memory regions:"
self.reader.ForEachMemoryRegion(print_region)
+ def do_lm(self, arg):
+ """
+ List details for all loaded modules in the minidump. An argument can
+ be passed to limit the output to only those modules that contain the
+ argument as a substring (case insensitive match).
+ """
+ for module in self.reader.module_list.modules:
+ if arg:
+ name = GetModuleName(self.reader, module).lower()
+ if name.find(arg.lower()) >= 0:
+ PrintModuleDetails(self.reader, module)
+ else:
+ PrintModuleDetails(self.reader, module)
+ print
+
def do_s(self, word):
"""
Search for a given word in available memory regions. The given word
@@ -2069,10 +2101,32 @@
KNOWN_MODULES = {'chrome.exe', 'chrome.dll'}
+def GetVersionString(ms, ls):
+ return "%d.%d.%d.%d" % (ms >> 16, ms & 0xffff, ls >> 16, ls & 0xffff)
+
+
def GetModuleName(reader, module):
name = reader.ReadMinidumpString(module.module_name_rva)
+ # simplify for path manipulation
+ name = name.encode('utf-8')
return str(os.path.basename(str(name).replace("\\", "/")))
+
+def PrintModuleDetails(reader, module):
+ print "%s" % GetModuleName(reader, module)
+ file_version = GetVersionString(module.version_info.dwFileVersionMS,
+ module.version_info.dwFileVersionLS)
+ product_version = GetVersionString(module.version_info.dwProductVersionMS,
+ module.version_info.dwProductVersionLS)
+ print " base: %s" % reader.FormatIntPtr(module.base_of_image)
+ print " end: %s" % reader.FormatIntPtr(module.base_of_image +
+ module.size_of_image)
+ print " file version: %s" % file_version
+ print " product version: %s" % product_version
+ time_date_stamp = datetime.datetime.fromtimestamp(module.time_date_stamp)
+ print " timestamp: %s" % time_date_stamp
+
+
def AnalyzeMinidump(options, minidump_name):
reader = MinidumpReader(options, minidump_name)
heap = None
@@ -2093,14 +2147,13 @@
else:
print " eflags: %s" % bin(reader.exception_context.eflags)[2:]
- # TODO(mstarzinger): Disabled because broken, needs investigation.
- #print
- #print " modules:"
- #for module in reader.module_list.modules:
- # name = GetModuleName(reader, module)
- # if name in KNOWN_MODULES:
- # print " %s at %08X" % (name, module.base_of_image)
- # reader.TryLoadSymbolsFor(name, module)
+ print
+ print " modules:"
+ for module in reader.module_list.modules:
+ name = GetModuleName(reader, module)
+ if name in KNOWN_MODULES:
+ print " %s at %08X" % (name, module.base_of_image)
+ reader.TryLoadSymbolsFor(name, module)
print
stack_top = reader.ExceptionSP()
@@ -2137,12 +2190,15 @@
if options.full:
FullDump(reader, heap)
+ if options.command:
+ InspectionShell(reader, heap).onecmd(options.command)
+
if options.shell:
try:
InspectionShell(reader, heap).cmdloop("type help to get help")
except KeyboardInterrupt:
print "Kthxbye."
- else:
+ elif not options.command:
if reader.exception is not None:
print "Annotated stack (from exception.esp to bottom):"
for slot in xrange(stack_top, stack_bottom, reader.PointerSize()):
@@ -2163,6 +2219,8 @@
parser = optparse.OptionParser(USAGE)
parser.add_option("-s", "--shell", dest="shell", action="store_true",
help="start an interactive inspector shell")
+ parser.add_option("-c", "--command", dest="command", default="",
+ help="run an interactive inspector shell command and exit")
parser.add_option("-f", "--full", dest="full", action="store_true",
help="dump all information contained in the minidump")
parser.add_option("--symdir", dest="symdir", default=".",
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index 34b1faf..26e3299 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -26,6 +26,9 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
+ 'variables': {
+ 'v8_code': 1,
+ },
'includes': ['../../build/common.gypi'],
'targets': [
{
@@ -324,6 +327,8 @@
'../../src/heap.h',
'../../src/hydrogen-environment-liveness.cc',
'../../src/hydrogen-environment-liveness.h',
+ '../../src/hydrogen-escape-analysis.cc',
+ '../../src/hydrogen-escape-analysis.h',
'../../src/hydrogen-instructions.cc',
'../../src/hydrogen-instructions.h',
'../../src/hydrogen.cc',
@@ -332,6 +337,8 @@
'../../src/hydrogen-gvn.h',
'../../src/hydrogen-infer-representation.cc',
'../../src/hydrogen-infer-representation.h',
+ '../../src/hydrogen-uint32-analysis.cc',
+ '../../src/hydrogen-uint32-analysis.h',
'../../src/ic-inl.h',
'../../src/ic.cc',
'../../src/ic.h',
diff --git a/tools/perf_tests/chromium_revision b/tools/perf_tests/chromium_revision
new file mode 100644
index 0000000..9f731f9
--- /dev/null
+++ b/tools/perf_tests/chromium_revision
@@ -0,0 +1 @@
+209619