From ba2d7da5a956fe4b2b23318509d2e635f1cb4e7c Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Mon, 23 Jun 2014 07:10:25 +0000 Subject: [PATCH] Introduce intrinsic to expose debug state to generated code. R=ulan@chromium.org Review URL: https://codereview.chromium.org/332673002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21908 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 11 +++++++++++ src/arm64/full-codegen-arm64.cc | 11 +++++++++++ src/array.js | 14 +++++++------- src/assembler.cc | 6 ++++++ src/assembler.h | 1 + src/collection.js | 4 ++-- src/debug.h | 4 ++++ src/hydrogen-instructions.h | 5 +++++ src/hydrogen.cc | 12 +++++++----- src/ia32/full-codegen-ia32.cc | 10 ++++++++++ src/macros.py | 3 +++ src/runtime.h | 8 ++++---- src/x64/full-codegen-x64.cc | 11 +++++++++++ test/mjsunit/debug-is-active.js | 28 ++++++++++++++++++++++++++++ 14 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 test/mjsunit/debug-is-active.js diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 8b079ed..cce8c05 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -4009,6 +4009,17 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { } +void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); + ExternalReference debug_is_active = + ExternalReference::debug_is_active_address(isolate()); + __ mov(ip, Operand(debug_is_active)); + __ ldrb(r0, MemOperand(ip)); + __ SmiTag(r0); + context()->Plug(r0); +} + + void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->function() != NULL && expr->function()->intrinsic_type == Runtime::INLINE) { diff --git a/src/arm64/full-codegen-arm64.cc b/src/arm64/full-codegen-arm64.cc index 4a44e35..ed62328 100644 --- a/src/arm64/full-codegen-arm64.cc +++ b/src/arm64/full-codegen-arm64.cc @@ -3720,6 +3720,17 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { } +void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); + ExternalReference debug_is_active = + ExternalReference::debug_is_active_address(isolate()); + __ Mov(x10, debug_is_active); + __ Ldrb(x0, MemOperand(x10)); + __ SmiTag(x0); + context()->Plug(x0); +} + + void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->function() != NULL && expr->function()->intrinsic_type == Runtime::INLINE) { diff --git a/src/array.js b/src/array.js index ef7aae4..a16f430 100644 --- a/src/array.js +++ b/src/array.js @@ -1128,7 +1128,7 @@ function ArrayFilter(f, receiver) { var result = new $Array(); var accumulator = new InternalArray(); var accumulator_length = 0; - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); for (var i = 0; i < length; i++) { if (i in array) { var element = array[i]; @@ -1161,7 +1161,7 @@ function ArrayForEach(f, receiver) { receiver = ToObject(receiver); } - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); for (var i = 0; i < length; i++) { if (i in array) { var element = array[i]; @@ -1192,7 +1192,7 @@ function ArraySome(f, receiver) { receiver = ToObject(receiver); } - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); for (var i = 0; i < length; i++) { if (i in array) { var element = array[i]; @@ -1222,7 +1222,7 @@ function ArrayEvery(f, receiver) { receiver = ToObject(receiver); } - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); for (var i = 0; i < length; i++) { if (i in array) { var element = array[i]; @@ -1253,7 +1253,7 @@ function ArrayMap(f, receiver) { var result = new $Array(); var accumulator = new InternalArray(length); - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); for (var i = 0; i < length; i++) { if (i in array) { var element = array[i]; @@ -1400,7 +1400,7 @@ function ArrayReduce(callback, current) { } var receiver = %GetDefaultReceiver(callback); - var stepping = %_DebugCallbackSupportsStepping(callback); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(callback); for (; i < length; i++) { if (i in array) { var element = array[i]; @@ -1437,7 +1437,7 @@ function ArrayReduceRight(callback, current) { } var receiver = %GetDefaultReceiver(callback); - var stepping = %_DebugCallbackSupportsStepping(callback); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(callback); for (; i >= 0; i--) { if (i in array) { var element = array[i]; diff --git a/src/assembler.cc b/src/assembler.cc index 20c73f7..63f9c56 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -1428,6 +1428,12 @@ ExternalReference ExternalReference::cpu_features() { } +ExternalReference ExternalReference::debug_is_active_address( + Isolate* isolate) { + return ExternalReference(isolate->debug()->is_active_address()); +} + + ExternalReference ExternalReference::debug_after_break_target_address( Isolate* isolate) { return ExternalReference(isolate->debug()->after_break_target_address()); diff --git a/src/assembler.h b/src/assembler.h index bbca793..c92706c 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -911,6 +911,7 @@ class ExternalReference BASE_EMBEDDED { static ExternalReference cpu_features(); + static ExternalReference debug_is_active_address(Isolate* isolate); static ExternalReference debug_after_break_target_address(Isolate* isolate); static ExternalReference debug_restarter_frame_function_pointer_address( Isolate* isolate); diff --git a/src/collection.js b/src/collection.js index 0d8dd77..a1342a3 100644 --- a/src/collection.js +++ b/src/collection.js @@ -81,7 +81,7 @@ function SetForEach(f, receiver) { var iterator = new SetIterator(this, ITERATOR_KIND_VALUES); var entry; - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); while (!(entry = %SetIteratorNext(iterator)).done) { if (stepping) %DebugPrepareStepInIfStepping(f); %_CallFunction(receiver, entry.value, entry.value, this, f); @@ -192,7 +192,7 @@ function MapForEach(f, receiver) { var iterator = new MapIterator(this, ITERATOR_KIND_ENTRIES); var entry; - var stepping = %_DebugCallbackSupportsStepping(f); + var stepping = DEBUG_IS_ACTIVE && %DebugCallbackSupportsStepping(f); while (!(entry = %MapIteratorNext(iterator)).done) { if (stepping) %DebugPrepareStepInIfStepping(f); %_CallFunction(receiver, entry.value[1], entry.value[0], this, f); diff --git a/src/debug.h b/src/debug.h index 7f9b1a2..b672940 100644 --- a/src/debug.h +++ b/src/debug.h @@ -505,6 +505,10 @@ class Debug { int break_id() { return thread_local_.break_id_; } // Support for embedding into generated code. + Address is_active_address() { + return reinterpret_cast
(&is_active_); + } + Address after_break_target_address() { return reinterpret_cast
(&after_break_target_); } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 18e3851..c734227 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -6120,6 +6120,11 @@ class HObjectAccess V8_FINAL { Handle::null(), false, false); } + static HObjectAccess ForExternalUInteger8() { + return HObjectAccess(kExternalMemory, 0, Representation::UInteger8(), + Handle::null(), false, false); + } + // Create an access to an offset in a fixed array header. static HObjectAccess ForFixedArrayHeader(int offset); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 9ec9f11..a2f6320 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -11711,11 +11711,13 @@ void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode( } -void HOptimizedGraphBuilder::GenerateDebugCallbackSupportsStepping( - CallRuntime* call) { - ASSERT(call->arguments()->length() == 1); - // Debugging is not supported in optimized code. - return ast_context()->ReturnValue(graph()->GetConstantFalse()); +void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) { + ASSERT(call->arguments()->length() == 0); + HValue* ref = + Add(ExternalReference::debug_is_active_address(isolate())); + HValue* value = Add( + ref, static_cast(NULL), HObjectAccess::ForExternalUInteger8()); + return ast_context()->ReturnValue(value); } diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index 0ea77f0..1007a87 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -3996,6 +3996,16 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { } +void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); + ExternalReference debug_is_active = + ExternalReference::debug_is_active_address(isolate()); + __ movzx_b(eax, Operand::StaticVariable(debug_is_active)); + __ SmiTag(eax); + context()->Plug(eax); +} + + void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->function() != NULL && expr->function()->intrinsic_type == Runtime::INLINE) { diff --git a/src/macros.py b/src/macros.py index 305a693..131df87 100644 --- a/src/macros.py +++ b/src/macros.py @@ -285,3 +285,6 @@ const PROPERTY_ATTRIBUTES_PRIVATE_SYMBOL = 32; const ITERATOR_KIND_KEYS = 1; const ITERATOR_KIND_VALUES = 2; const ITERATOR_KIND_ENTRIES = 3; + +# Check whether debug is active. +const DEBUG_IS_ACTIVE = (%_DebugIsActive() != 0); diff --git a/src/runtime.h b/src/runtime.h index d6ed830..6fad657 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -438,6 +438,7 @@ namespace internal { F(DebugConstructedBy, 2, 1) \ F(DebugGetPrototype, 1, 1) \ F(DebugSetScriptSource, 2, 1) \ + F(DebugCallbackSupportsStepping, 1, 1) \ F(SystemBreak, 0, 1) \ F(DebugDisassembleFunction, 1, 1) \ F(DebugDisassembleConstructor, 1, 1) \ @@ -654,7 +655,8 @@ namespace internal { F(RegExpExec, 4, 1) \ F(RegExpConstructResult, 3, 1) \ F(GetFromCache, 2, 1) \ - F(NumberToString, 1, 1) + F(NumberToString, 1, 1) \ + F(DebugIsActive, 0, 1) // ---------------------------------------------------------------------------- @@ -680,9 +682,7 @@ namespace internal { F(DoubleHi, 1, 1) \ F(DoubleLo, 1, 1) \ F(MathSqrtRT, 1, 1) \ - F(MathLogRT, 1, 1) \ - /* Debugger */ \ - F(DebugCallbackSupportsStepping, 1, 1) + F(MathLogRT, 1, 1) //--------------------------------------------------------------------------- diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index fa1eee6..3190e5a 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -4004,6 +4004,17 @@ void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) { } +void FullCodeGenerator::EmitDebugIsActive(CallRuntime* expr) { + ASSERT(expr->arguments()->length() == 0); + ExternalReference debug_is_active = + ExternalReference::debug_is_active_address(isolate()); + __ Move(kScratchRegister, debug_is_active); + __ movzxbp(rax, Operand(kScratchRegister, 0)); + __ Integer32ToSmi(rax, rax); + context()->Plug(rax); +} + + void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->function() != NULL && expr->function()->intrinsic_type == Runtime::INLINE) { diff --git a/test/mjsunit/debug-is-active.js b/test/mjsunit/debug-is-active.js new file mode 100644 index 0000000..19968f0 --- /dev/null +++ b/test/mjsunit/debug-is-active.js @@ -0,0 +1,28 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-debug-as debug --allow-natives-syntax + +Debug = debug.Debug; + +function f() { return %_DebugIsActive() != 0; } + +assertFalse(f()); +assertFalse(f()); +Debug.setListener(function() {}); +assertTrue(f()); +Debug.setListener(null); +assertFalse(f()); + +%OptimizeFunctionOnNextCall(f); +assertFalse(f()); +assertOptimized(f); + +Debug.setListener(function() {}); +assertTrue(f()); +assertOptimized(f); + +Debug.setListener(null); +assertFalse(f()); +assertOptimized(f); -- 2.7.4