Version 3.27.4 (based on bleeding_edge revision r21317)
Drop thenable coercion cache (Chromium issue 372788).
Skip write barriers when updating the weak hash table (Chromium issue 359401).
Performance and stability improvements on all platforms.
git-svn-id: https://v8.googlecode.com/svn/trunk@21318 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/ChangeLog b/ChangeLog
index b5f7432..e8220f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2014-05-15: Version 3.27.4
+
+ Drop thenable coercion cache (Chromium issue 372788).
+
+ Skip write barriers when updating the weak hash table (Chromium issue
+ 359401).
+
+ Performance and stability improvements on all platforms.
+
+
2014-05-14: Version 3.27.3
Performance and stability improvements on all platforms.
diff --git a/DEPS b/DEPS
index 24b7841..8f7faca 100644
--- a/DEPS
+++ b/DEPS
@@ -2,22 +2,26 @@
# directory and assume that the root of the checkout is in ./v8/, so
# all paths in here must match this assumption.
+vars = {
+ "chromium_trunk": "https://src.chromium.org/svn/trunk",
+}
+
deps = {
# Remember to keep the revision in sync with the Makefile.
"v8/build/gyp":
"http://gyp.googlecode.com/svn/trunk@1831",
"v8/third_party/icu":
- "https://src.chromium.org/svn/trunk/deps/third_party/icu46@258359",
+ Var("chromium_trunk") + "/deps/third_party/icu46@258359",
}
deps_os = {
"win": {
"v8/third_party/cygwin":
- "http://src.chromium.org/svn/trunk/deps/third_party/cygwin@66844",
+ Var("chromium_trunk") + "/deps/third_party/cygwin@66844",
"v8/third_party/python_26":
- "http://src.chromium.org/svn/trunk/tools/third_party/python_26@89111",
+ Var("chromium_trunk") + "/tools/third_party/python_26@89111",
}
}
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 41d79eb..6a836e0 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -110,6 +110,7 @@
'v8_linux64_rel': set(['defaulttests']),
'v8_linux_arm_dbg': set(['defaulttests']),
'v8_linux_arm64_rel': set(['defaulttests']),
+ 'v8_linux_layout_dbg': set(['defaulttests']),
'v8_mac_rel': set(['defaulttests']),
'v8_win_rel': set(['defaulttests']),
},
diff --git a/build/android.gypi b/build/android.gypi
index 73ac93a..6c5ccbd 100644
--- a/build/android.gypi
+++ b/build/android.gypi
@@ -215,6 +215,15 @@
'-fno-stack-protector',
],
}],
+ ['target_arch=="arm64" or target_arch=="x64"', {
+ # TODO(ulan): Enable PIE for other architectures (crbug.com/373219).
+ 'cflags': [
+ '-fPIE',
+ ],
+ 'ldflags': [
+ '-pie',
+ ],
+ }],
],
'target_conditions': [
['_type=="executable"', {
diff --git a/include/v8-debug.h b/include/v8-debug.h
index 48b9657..aea5684 100644
--- a/include/v8-debug.h
+++ b/include/v8-debug.h
@@ -137,7 +137,10 @@
* A EventCallback2 does not take possession of the event data,
* and must not rely on the data persisting after the handler returns.
*/
- typedef void (*EventCallback2)(const EventDetails& event_details);
+ typedef void (*EventCallback)(const EventDetails& event_details);
+
+ // TODO(yangguo) Deprecate this.
+ typedef EventCallback EventCallback2;
/**
* Debug message callback function.
@@ -147,15 +150,24 @@
* A MessageHandler2 does not take possession of the message data,
* and must not rely on the data persisting after the handler returns.
*/
- typedef void (*MessageHandler2)(const Message& message);
+ typedef void (*MessageHandler)(const Message& message);
+
+ // TODO(yangguo) Deprecate this.
+ typedef MessageHandler MessageHandler2;
/**
* Callback function for the host to ensure debug messages are processed.
*/
typedef void (*DebugMessageDispatchHandler)();
+ static bool SetDebugEventListener(EventCallback that,
+ Handle<Value> data = Handle<Value>());
+
+ // TODO(yangguo) Deprecate this.
static bool SetDebugEventListener2(EventCallback2 that,
- Handle<Value> data = Handle<Value>());
+ Handle<Value> data = Handle<Value>()) {
+ return SetDebugEventListener(that, data);
+ }
// Schedule a debugger break to happen when JavaScript code is run
// in the given isolate.
@@ -178,26 +190,17 @@
}
// Message based interface. The message protocol is JSON.
- static void SetMessageHandler2(MessageHandler2 handler);
+ static void SetMessageHandler(MessageHandler handler);
+
+ // TODO(yangguo) Deprecate this.
+ static void SetMessageHandler2(MessageHandler2 handler) {
+ SetMessageHandler(handler);
+ }
static void SendCommand(Isolate* isolate,
const uint16_t* command, int length,
ClientData* client_data = NULL);
- /**
- * Register a callback function to be called when a debug message has been
- * received and is ready to be processed. For the debug messages to be
- * processed V8 needs to be entered, and in certain embedding scenarios this
- * callback can be used to make sure V8 is entered for the debug message to
- * be processed. Note that debug messages will only be processed if there is
- * a V8 break. This can happen automatically by using the option
- * --debugger-auto-break.
- * \param provide_locker requires that V8 acquires v8::Locker for you before
- * calling handler
- */
- static void SetDebugMessageDispatchHandler(
- DebugMessageDispatchHandler handler, bool provide_locker = false);
-
/**
* Run a JavaScript function in the debugger.
* \param fun the function to call
@@ -224,22 +227,6 @@
*/
static Local<Value> GetMirror(v8::Handle<v8::Value> obj);
- /**
- * Enable the V8 builtin debug agent. The debugger agent will listen on the
- * supplied TCP/IP port for remote debugger connection.
- * \param name the name of the embedding application
- * \param port the TCP/IP port to listen on
- * \param wait_for_connection whether V8 should pause on a first statement
- * allowing remote debugger to connect before anything interesting happened
- */
- static bool EnableAgent(const char* name, int port,
- bool wait_for_connection = false);
-
- /**
- * Disable the V8 builtin debug agent. The TCP/IP connection will be closed.
- */
- static void DisableAgent();
-
/**
* Makes V8 process all pending debug messages.
*
@@ -258,10 +245,6 @@
* until V8 gets control again; however, embedding application may improve
* this by manually calling this method.
*
- * It makes sense to call this method whenever a new debug message arrived and
- * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler
- * should help with the former condition.
- *
* Technically this method in many senses is equivalent to executing empty
* script:
* 1. It does nothing except for processing all pending debug messages.
diff --git a/include/v8.h b/include/v8.h
index e089b41..9843933 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1040,9 +1040,9 @@
BufferPolicy buffer_policy;
private:
- // Prevent copying. Not implemented.
- CachedData(const CachedData&);
- CachedData& operator=(const CachedData&);
+ // Prevent copying. Not implemented.
+ CachedData(const CachedData&);
+ CachedData& operator=(const CachedData&);
};
/**
@@ -1065,7 +1065,7 @@
private:
friend class ScriptCompiler;
- // Prevent copying. Not implemented.
+ // Prevent copying. Not implemented.
Source(const Source&);
Source& operator=(const Source&);
@@ -2497,7 +2497,7 @@
public:
V8_INLINE Isolate* GetIsolate() const;
V8_INLINE Local<Value> Data() const;
- V8_INLINE Local<Value> This() const;
+ V8_INLINE Local<Object> This() const;
V8_INLINE Local<Object> Holder() const;
V8_INLINE ReturnValue<T> GetReturnValue() const;
// This shouldn't be public, but the arm compiler needs it.
@@ -6483,8 +6483,8 @@
template<typename T>
-Local<Value> PropertyCallbackInfo<T>::This() const {
- return Local<Value>(reinterpret_cast<Value*>(&args_[kThisIndex]));
+Local<Object> PropertyCallbackInfo<T>::This() const {
+ return Local<Object>(reinterpret_cast<Object*>(&args_[kThisIndex]));
}
diff --git a/samples/lineprocessor.cc b/samples/lineprocessor.cc
index 7e820b3..6f8fd35 100644
--- a/samples/lineprocessor.cc
+++ b/samples/lineprocessor.cc
@@ -109,28 +109,6 @@
v8::Persistent<v8::Context> debug_message_context;
-void DispatchDebugMessages() {
- // We are in some random thread. We should already have v8::Locker acquired
- // (we requested this when registered this callback). We was called
- // because new debug messages arrived; they may have already been processed,
- // but we shouldn't worry about this.
- //
- // All we have to do is to set context and call ProcessDebugMessages.
- //
- // We should decide which V8 context to use here. This is important for
- // "evaluate" command, because it must be executed some context.
- // In our sample we have only one context, so there is nothing really to
- // think about.
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> context =
- v8::Local<v8::Context>::New(isolate, debug_message_context);
- v8::Context::Scope scope(context);
-
- v8::Debug::ProcessDebugMessages();
-}
-
-
int RunMain(int argc, char* argv[]) {
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::Isolate* isolate = v8::Isolate::New();
@@ -142,10 +120,6 @@
v8::Handle<v8::Value> script_name;
int script_param_counter = 0;
- int port_number = -1;
- bool wait_for_connection = false;
- bool support_callback = false;
-
MainCycleType cycle_type = CycleInCpp;
for (int i = 1; i < argc; i++) {
@@ -158,13 +132,6 @@
cycle_type = CycleInCpp;
} else if (strcmp(str, "--main-cycle-in-js") == 0) {
cycle_type = CycleInJs;
- } else if (strcmp(str, "--callback") == 0) {
- support_callback = true;
- } else if (strcmp(str, "--wait-for-connection") == 0) {
- wait_for_connection = true;
- } else if (strcmp(str, "-p") == 0 && i + 1 < argc) {
- port_number = atoi(argv[i + 1]); // NOLINT
- i++;
} else if (strncmp(str, "--", 2) == 0) {
printf("Warning: unknown flag %s.\nTry --help for options\n", str);
} else if (strcmp(str, "-e") == 0 && i + 1 < argc) {
@@ -214,14 +181,6 @@
debug_message_context.Reset(isolate, context);
- if (support_callback) {
- v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
- }
-
- if (port_number != -1) {
- v8::Debug::EnableAgent("lineprocessor", port_number, wait_for_connection);
- }
-
bool report_exceptions = true;
v8::Handle<v8::Script> script;
diff --git a/src/accessors.cc b/src/accessors.cc
index 8c8fcdd..f219bed 100644
--- a/src/accessors.cc
+++ b/src/accessors.cc
@@ -20,6 +20,16 @@
namespace internal {
+// We have a slight impedance mismatch between the external API and the way we
+// use callbacks internally: Externally, callbacks can only be used with
+// v8::Object, but internally we even have callbacks on entities which are
+// higher in the hierarchy, so we can only return i::Object here, not
+// i::JSObject.
+Handle<Object> GetThisFrom(const v8::PropertyCallbackInfo<v8::Value>& info) {
+ return Utils::OpenHandle(*v8::Local<v8::Value>(info.This()));
+}
+
+
Handle<AccessorInfo> Accessors::MakeAccessor(
Isolate* isolate,
Handle<String> name,
@@ -146,7 +156,7 @@
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
DisallowHeapAllocation no_allocation;
HandleScope scope(isolate);
- Object* object = *Utils::OpenHandle(*info.This());
+ Object* object = *GetThisFrom(info);
// Traverse the prototype chain until we reach an array.
JSArray* holder = FindInstanceOf<JSArray>(isolate, object);
Object* result;
@@ -229,7 +239,7 @@
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
DisallowHeapAllocation no_allocation;
HandleScope scope(isolate);
- Object* value = *Utils::OpenHandle(*info.This());
+ Object* value = *GetThisFrom(info);
Object* result;
if (value->IsJSValue()) value = JSValue::cast(value)->value();
if (value->IsString()) {
@@ -824,7 +834,7 @@
const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Object> object = GetThisFrom(info);
Handle<Object> result = GetFunctionPrototype(isolate, object);
info.GetReturnValue().Set(Utils::ToLocal(result));
}
@@ -864,7 +874,7 @@
const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Object> object = GetThisFrom(info);
MaybeHandle<JSFunction> maybe_function;
{
@@ -922,7 +932,7 @@
const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Object> object = GetThisFrom(info);
MaybeHandle<JSFunction> maybe_function;
{
@@ -1071,7 +1081,7 @@
const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Object> object = GetThisFrom(info);
MaybeHandle<JSFunction> maybe_function;
{
@@ -1210,7 +1220,7 @@
const v8::PropertyCallbackInfo<v8::Value>& info) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
HandleScope scope(isolate);
- Handle<Object> object = Utils::OpenHandle(*info.This());
+ Handle<Object> object = GetThisFrom(info);
MaybeHandle<JSFunction> maybe_function;
{
DisallowHeapAllocation no_allocation;
diff --git a/src/api.cc b/src/api.cc
index 7f1276d..b559015 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -6778,10 +6778,10 @@
// --- D e b u g S u p p o r t ---
-bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
+bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener2()");
- ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener2()", return false);
+ EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()");
+ ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
ENTER_V8(isolate);
i::HandleScope scope(isolate);
i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
@@ -6811,7 +6811,7 @@
}
-void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
+void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
i::Isolate* isolate = i::Isolate::Current();
EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
ENTER_V8(isolate);
@@ -6824,22 +6824,11 @@
int length,
ClientData* client_data) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
- internal_isolate->debugger()->ProcessCommand(
+ internal_isolate->debugger()->EnqueueCommandMessage(
i::Vector<const uint16_t>(command, length), client_data);
}
-void Debug::SetDebugMessageDispatchHandler(
- DebugMessageDispatchHandler handler, bool provide_locker) {
- i::Isolate* isolate = i::Isolate::Current();
- EnsureInitializedForIsolate(isolate,
- "v8::Debug::SetDebugMessageDispatchHandler");
- ENTER_V8(isolate);
- isolate->debugger()->SetDebugMessageDispatchHandler(
- handler, provide_locker);
-}
-
-
Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
v8::Handle<v8::Value> data) {
i::Isolate* isolate = i::Isolate::Current();
@@ -6891,17 +6880,6 @@
}
-bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
- return i::Isolate::Current()->debugger()->StartAgent(name, port,
- wait_for_connection);
-}
-
-
-void Debug::DisableAgent() {
- return i::Isolate::Current()->debugger()->StopAgent();
-}
-
-
void Debug::ProcessDebugMessages() {
i::Execution::ProcessDebugMessages(i::Isolate::Current(), true);
}
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 2879d64..86aa0b5 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -1435,9 +1435,14 @@
Register result = ToRegister(instr->result());
int32_t divisor = instr->divisor();
+ // If the divisor is 1, return the dividend.
+ if (divisor == 1) {
+ __ Move(result, dividend);
+ return;
+ }
+
// If the divisor is positive, things are easy: There can be no deopts and we
// can simply do an arithmetic right shift.
- if (divisor == 1) return;
int32_t shift = WhichPowerOf2Abs(divisor);
if (divisor > 1) {
__ mov(result, Operand(dividend, ASR, shift));
diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc
index 6bd7c5b..d18808a 100644
--- a/src/arm64/lithium-arm64.cc
+++ b/src/arm64/lithium-arm64.cc
@@ -2009,10 +2009,9 @@
LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) {
- LOperand* lo = UseRegister(instr->lo());
+ LOperand* lo = UseRegisterAndClobber(instr->lo());
LOperand* hi = UseRegister(instr->hi());
- LOperand* temp = TempRegister();
- return DefineAsRegister(new(zone()) LConstructDouble(hi, lo, temp));
+ return DefineAsRegister(new(zone()) LConstructDouble(hi, lo));
}
diff --git a/src/arm64/lithium-arm64.h b/src/arm64/lithium-arm64.h
index 62384c4..85629c4 100644
--- a/src/arm64/lithium-arm64.h
+++ b/src/arm64/lithium-arm64.h
@@ -1041,17 +1041,15 @@
};
-class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+class LConstructDouble V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public:
- LConstructDouble(LOperand* hi, LOperand* lo, LOperand* temp) {
+ LConstructDouble(LOperand* hi, LOperand* lo) {
inputs_[0] = hi;
inputs_[1] = lo;
- temps_[0] = temp;
}
LOperand* hi() { return inputs_[0]; }
LOperand* lo() { return inputs_[1]; }
- LOperand* temp() { return temps_[0]; }
DECLARE_CONCRETE_INSTRUCTION(ConstructDouble, "construct-double")
};
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc
index caa902e..e070146 100644
--- a/src/arm64/lithium-codegen-arm64.cc
+++ b/src/arm64/lithium-codegen-arm64.cc
@@ -2290,7 +2290,7 @@
Register result_reg = ToRegister(instr->result());
if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
__ Fmov(result_reg, value_reg);
- __ Mov(result_reg, Operand(result_reg, LSR, 32));
+ __ Lsr(result_reg, result_reg, 32);
} else {
__ Fmov(result_reg.W(), value_reg.S());
}
@@ -2300,12 +2300,12 @@
void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
Register hi_reg = ToRegister(instr->hi());
Register lo_reg = ToRegister(instr->lo());
- Register temp = ToRegister(instr->temp());
DoubleRegister result_reg = ToDoubleRegister(instr->result());
- __ And(temp, lo_reg, Operand(0xffffffff));
- __ Orr(temp, temp, Operand(hi_reg, LSL, 32));
- __ Fmov(result_reg, temp);
+ // Insert the least significant 32 bits of hi_reg into the most significant
+ // 32 bits of lo_reg, and move to a floating point register.
+ __ Bfi(lo_reg, hi_reg, 32, 32);
+ __ Fmov(result_reg, lo_reg);
}
@@ -2415,8 +2415,8 @@
Register value = ToRegister(instr->value());
__ CheckMap(value, scratch, Heap::kHeapNumberMapRootIndex,
instr->FalseLabel(chunk()), DO_SMI_CHECK);
- __ Ldr(double_scratch(), FieldMemOperand(value, HeapNumber::kValueOffset));
- __ JumpIfMinusZero(double_scratch(), instr->TrueLabel(chunk()));
+ __ Ldr(scratch, FieldMemOperand(value, HeapNumber::kValueOffset));
+ __ JumpIfMinusZero(scratch, instr->TrueLabel(chunk()));
}
EmitGoto(instr->FalseDestination(chunk()));
}
@@ -2524,7 +2524,15 @@
void LCodeGen::DoConstantD(LConstantD* instr) {
ASSERT(instr->result()->IsDoubleRegister());
DoubleRegister result = ToDoubleRegister(instr->result());
- __ Fmov(result, instr->value());
+ if (instr->value() == 0) {
+ if (copysign(1.0, instr->value()) == 1.0) {
+ __ Fmov(result, fp_zero);
+ } else {
+ __ Fneg(result, fp_zero);
+ }
+ } else {
+ __ Fmov(result, instr->value());
+ }
}
@@ -2663,13 +2671,14 @@
// Check for (0 / -x) that will produce negative zero.
HDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
- __ Cmp(dividend, 0);
- DeoptimizeIf(eq, instr->environment());
+ DeoptimizeIfZero(dividend, instr->environment());
}
// Check for (kMinInt / -1).
if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
- __ Cmp(dividend, kMinInt);
- DeoptimizeIf(eq, instr->environment());
+ // Test dividend for kMinInt by subtracting one (cmp) and checking for
+ // overflow.
+ __ Cmp(dividend, 1);
+ DeoptimizeIf(vs, instr->environment());
}
// Deoptimize if remainder will not be 0.
if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
@@ -3870,9 +3879,14 @@
Register result = ToRegister32(instr->result());
int32_t divisor = instr->divisor();
+ // If the divisor is 1, return the dividend.
+ if (divisor == 1) {
+ __ Mov(result, dividend, kDiscardForSameWReg);
+ return;
+ }
+
// If the divisor is positive, things are easy: There can be no deopts and we
// can simply do an arithmetic right shift.
- if (divisor == 1) return;
int32_t shift = WhichPowerOf2Abs(divisor);
if (divisor > 1) {
__ Mov(result, Operand(dividend, ASR, shift));
@@ -3897,14 +3911,8 @@
return;
}
- // Using a conditional data processing instruction would need 1 more register.
- Label not_kmin_int, done;
- __ B(vc, ¬_kmin_int);
- __ Mov(result, kMinInt / divisor);
- __ B(&done);
- __ bind(¬_kmin_int);
- __ Mov(result, Operand(dividend, ASR, shift));
- __ bind(&done);
+ __ Asr(result, dividend, shift);
+ __ Csel(result, result, kMinInt / divisor, vc);
}
@@ -3922,8 +3930,7 @@
// Check for (0 / -x) that will produce negative zero.
HMathFloorOfDiv* hdiv = instr->hydrogen();
if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
- __ Cmp(dividend, 0);
- DeoptimizeIf(eq, instr->environment());
+ DeoptimizeIfZero(dividend, instr->environment());
}
// Easy case: We need no dynamic check for the dividend and the flooring
@@ -3945,12 +3952,12 @@
__ TruncatingDiv(result, dividend, Abs(divisor));
if (divisor < 0) __ Neg(result, result);
__ B(&done);
- __ bind(&needs_adjustment);
+ __ Bind(&needs_adjustment);
__ Add(temp, dividend, Operand(divisor > 0 ? 1 : -1));
__ TruncatingDiv(result, temp, Abs(divisor));
if (divisor < 0) __ Neg(result, result);
__ Sub(result, result, Operand(1));
- __ bind(&done);
+ __ Bind(&done);
}
@@ -4217,8 +4224,7 @@
int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
Label dividend_is_not_negative, done;
if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
- __ Cmp(dividend, 0);
- __ B(pl, ÷nd_is_not_negative);
+ __ Tbz(dividend, kWSignBit, ÷nd_is_not_negative);
// Note that this is correct even for kMinInt operands.
__ Neg(dividend, dividend);
__ And(dividend, dividend, mask);
diff --git a/src/arm64/macro-assembler-arm64.cc b/src/arm64/macro-assembler-arm64.cc
index 7279319..d35e69c 100644
--- a/src/arm64/macro-assembler-arm64.cc
+++ b/src/arm64/macro-assembler-arm64.cc
@@ -2343,6 +2343,16 @@
}
+void MacroAssembler::JumpIfMinusZero(Register input,
+ Label* on_negative_zero) {
+ ASSERT(input.Is64Bits());
+ // Floating point value is in an integer register. Detect -0.0 by subtracting
+ // 1 (cmp), which will cause overflow.
+ Cmp(input, 1);
+ B(vs, on_negative_zero);
+}
+
+
void MacroAssembler::ClampInt32ToUint8(Register output, Register input) {
// Clamp the value to [0..255].
Cmp(input.W(), Operand(input.W(), UXTB));
diff --git a/src/arm64/macro-assembler-arm64.h b/src/arm64/macro-assembler-arm64.h
index c9ebab3..a817958 100644
--- a/src/arm64/macro-assembler-arm64.h
+++ b/src/arm64/macro-assembler-arm64.h
@@ -919,6 +919,10 @@
// Jump to label if the input double register contains -0.0.
void JumpIfMinusZero(DoubleRegister input, Label* on_negative_zero);
+ // Jump to label if the input integer register contains the double precision
+ // floating point representation of -0.0.
+ void JumpIfMinusZero(Register input, Label* on_negative_zero);
+
// Generate code to do a lookup in the number string cache. If the number in
// the register object is found in the cache the generated code falls through
// with the result in the result register. The object and the result register
diff --git a/src/array.js b/src/array.js
index c37f468..5b036e6 100644
--- a/src/array.js
+++ b/src/array.js
@@ -45,7 +45,7 @@
}
-function SparseJoinWithSeparator(array, len, convert, separator) {
+function SparseJoinWithSeparatorJS(array, len, convert, separator) {
var keys = GetSortedArrayKeys(array, %GetArrayKeys(array, len));
var totalLength = 0;
var elements = new InternalArray(keys.length * 2);
@@ -111,7 +111,7 @@
if (separator.length == 0) {
return SparseJoin(array, length, convert);
} else {
- return SparseJoinWithSeparator(array, length, convert, separator);
+ return SparseJoinWithSeparatorJS(array, length, convert, separator);
}
}
@@ -457,7 +457,7 @@
// Returns an array containing the array elements of the object followed
// by the array elements of each argument in order. See ECMA-262,
// section 15.4.4.7.
-function ArrayConcat(arg1) { // length == 1
+function ArrayConcatJS(arg1) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "Array.prototype.concat");
var array = ToObject(this);
@@ -1492,7 +1492,7 @@
"join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop),
"push", getFunction("push", ArrayPush, 1),
- "concat", getFunction("concat", ArrayConcat, 1),
+ "concat", getFunction("concat", ArrayConcatJS, 1),
"reverse", getFunction("reverse", ArrayReverse),
"shift", getFunction("shift", ArrayShift),
"unshift", getFunction("unshift", ArrayUnshift, 1),
@@ -1516,7 +1516,7 @@
// exposed to user code.
// Adding only the functions that are actually used.
SetUpLockedPrototype(InternalArray, $Array(), $Array(
- "concat", getFunction("concat", ArrayConcat),
+ "concat", getFunction("concat", ArrayConcatJS),
"indexOf", getFunction("indexOf", ArrayIndexOf),
"join", getFunction("join", ArrayJoin),
"pop", getFunction("pop", ArrayPop),
diff --git a/src/arraybuffer.js b/src/arraybuffer.js
index 44989f5..d1324bb 100644
--- a/src/arraybuffer.js
+++ b/src/arraybuffer.js
@@ -62,7 +62,7 @@
return result;
}
-function ArrayBufferIsView(obj) {
+function ArrayBufferIsViewJS(obj) {
return %ArrayBufferIsView(obj);
}
@@ -79,7 +79,7 @@
InstallGetter($ArrayBuffer.prototype, "byteLength", ArrayBufferGetByteLen);
InstallFunctions($ArrayBuffer, DONT_ENUM, $Array(
- "isView", ArrayBufferIsView
+ "isView", ArrayBufferIsViewJS
));
InstallFunctions($ArrayBuffer.prototype, DONT_ENUM, $Array(
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index d783d24..480aab1 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1548,7 +1548,7 @@
void Genesis::InstallExperimentalNativeFunctions() {
- INSTALL_NATIVE(JSFunction, "RunMicrotasks", run_microtasks);
+ INSTALL_NATIVE(JSFunction, "RunMicrotasksJS", run_microtasks);
INSTALL_NATIVE(JSFunction, "EnqueueMicrotask", enqueue_microtask);
if (FLAG_harmony_proxies) {
diff --git a/src/builtins.cc b/src/builtins.cc
index b523450..fd0fc81 100644
--- a/src/builtins.cc
+++ b/src/builtins.cc
@@ -995,7 +995,7 @@
JSObject::cast(native_context->array_function()->prototype());
if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) {
AllowHeapAllocation allow_allocation;
- return CallJsBuiltin(isolate, "ArrayConcat", args);
+ return CallJsBuiltin(isolate, "ArrayConcatJS", args);
}
// Iterate through all the arguments performing checks
@@ -1007,7 +1007,7 @@
!JSArray::cast(arg)->HasFastElements() ||
JSArray::cast(arg)->GetPrototype() != array_proto) {
AllowHeapAllocation allow_allocation;
- return CallJsBuiltin(isolate, "ArrayConcat", args);
+ return CallJsBuiltin(isolate, "ArrayConcatJS", args);
}
int len = Smi::cast(JSArray::cast(arg)->length())->value();
@@ -1020,7 +1020,7 @@
if (result_len > FixedDoubleArray::kMaxLength) {
AllowHeapAllocation allow_allocation;
- return CallJsBuiltin(isolate, "ArrayConcat", args);
+ return CallJsBuiltin(isolate, "ArrayConcatJS", args);
}
ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
diff --git a/src/collection.js b/src/collection.js
index f8f3fa9..b201d57 100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -43,7 +43,7 @@
}
-function SetAdd(key) {
+function SetAddJS(key) {
if (!IS_SET(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.add', this]);
@@ -52,7 +52,7 @@
}
-function SetHas(key) {
+function SetHasJS(key) {
if (!IS_SET(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.has', this]);
@@ -61,7 +61,7 @@
}
-function SetDelete(key) {
+function SetDeleteJS(key) {
if (!IS_SET(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.delete', this]);
@@ -76,7 +76,7 @@
}
-function SetGetSize() {
+function SetGetSizeJS() {
if (!IS_SET(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.size', this]);
@@ -85,7 +85,7 @@
}
-function SetClear() {
+function SetClearJS() {
if (!IS_SET(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Set.prototype.clear', this]);
@@ -128,12 +128,12 @@
%FunctionSetLength(SetForEach, 1);
// Set up the non-enumerable functions on the Set prototype object.
- InstallGetter($Set.prototype, "size", SetGetSize);
+ InstallGetter($Set.prototype, "size", SetGetSizeJS);
InstallFunctions($Set.prototype, DONT_ENUM, $Array(
- "add", SetAdd,
- "has", SetHas,
- "delete", SetDelete,
- "clear", SetClear,
+ "add", SetAddJS,
+ "has", SetHasJS,
+ "delete", SetDeleteJS,
+ "clear", SetClearJS,
"forEach", SetForEach
));
}
@@ -153,7 +153,7 @@
}
-function MapGet(key) {
+function MapGetJS(key) {
if (!IS_MAP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.get', this]);
@@ -162,7 +162,7 @@
}
-function MapSet(key, value) {
+function MapSetJS(key, value) {
if (!IS_MAP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.set', this]);
@@ -171,7 +171,7 @@
}
-function MapHas(key) {
+function MapHasJS(key) {
if (!IS_MAP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.has', this]);
@@ -180,7 +180,7 @@
}
-function MapDelete(key) {
+function MapDeleteJS(key) {
if (!IS_MAP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.delete', this]);
@@ -189,7 +189,7 @@
}
-function MapGetSize() {
+function MapGetSizeJS() {
if (!IS_MAP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.size', this]);
@@ -198,7 +198,7 @@
}
-function MapClear() {
+function MapClearJS() {
if (!IS_MAP(this)) {
throw MakeTypeError('incompatible_method_receiver',
['Map.prototype.clear', this]);
@@ -241,13 +241,13 @@
%FunctionSetLength(MapForEach, 1);
// Set up the non-enumerable functions on the Map prototype object.
- InstallGetter($Map.prototype, "size", MapGetSize);
+ InstallGetter($Map.prototype, "size", MapGetSizeJS);
InstallFunctions($Map.prototype, DONT_ENUM, $Array(
- "get", MapGet,
- "set", MapSet,
- "has", MapHas,
- "delete", MapDelete,
- "clear", MapClear,
+ "get", MapGetJS,
+ "set", MapSetJS,
+ "has", MapHasJS,
+ "delete", MapDeleteJS,
+ "clear", MapClearJS,
"forEach", MapForEach
));
}
diff --git a/src/d8-debug.cc b/src/d8-debug.cc
index 7c1beaf..41ec670 100644
--- a/src/d8-debug.cc
+++ b/src/d8-debug.cc
@@ -4,27 +4,16 @@
#include "d8.h"
#include "d8-debug.h"
-#include "debug-agent.h"
-#include "platform/socket.h"
-
namespace v8 {
-static bool was_running = true;
-
void PrintPrompt(bool is_running) {
const char* prompt = is_running? "> " : "dbg> ";
- was_running = is_running;
printf("%s", prompt);
fflush(stdout);
}
-void PrintPrompt() {
- PrintPrompt(was_running);
-}
-
-
void HandleDebugEvent(const Debug::EventDetails& event_details) {
// TODO(svenpanne) There should be a way to retrieve this in the callback.
Isolate* isolate = Isolate::GetCurrent();
@@ -140,208 +129,4 @@
}
}
-
-void RunRemoteDebugger(Isolate* isolate, int port) {
- RemoteDebugger debugger(isolate, port);
- debugger.Run();
-}
-
-
-void RemoteDebugger::Run() {
- bool ok;
-
- // Connect to the debugger agent.
- conn_ = new i::Socket;
- static const int kPortStrSize = 6;
- char port_str[kPortStrSize];
- i::OS::SNPrintF(i::Vector<char>(port_str, kPortStrSize), "%d", port_);
- ok = conn_->Connect("localhost", port_str);
- if (!ok) {
- printf("Unable to connect to debug agent %d\n", i::Socket::GetLastError());
- return;
- }
-
- // Start the receiver thread.
- ReceiverThread receiver(this);
- receiver.Start();
-
- // Start the keyboard thread.
- KeyboardThread keyboard(this);
- keyboard.Start();
- PrintPrompt();
-
- // Process events received from debugged VM and from the keyboard.
- bool terminate = false;
- while (!terminate) {
- event_available_.Wait();
- RemoteDebuggerEvent* event = GetEvent();
- switch (event->type()) {
- case RemoteDebuggerEvent::kMessage:
- HandleMessageReceived(event->data());
- break;
- case RemoteDebuggerEvent::kKeyboard:
- HandleKeyboardCommand(event->data());
- break;
- case RemoteDebuggerEvent::kDisconnect:
- terminate = true;
- break;
-
- default:
- UNREACHABLE();
- }
- delete event;
- }
-
- delete conn_;
- conn_ = NULL;
- // Wait for the receiver thread to end.
- receiver.Join();
-}
-
-
-void RemoteDebugger::MessageReceived(i::SmartArrayPointer<char> message) {
- RemoteDebuggerEvent* event =
- new RemoteDebuggerEvent(RemoteDebuggerEvent::kMessage, message);
- AddEvent(event);
-}
-
-
-void RemoteDebugger::KeyboardCommand(i::SmartArrayPointer<char> command) {
- RemoteDebuggerEvent* event =
- new RemoteDebuggerEvent(RemoteDebuggerEvent::kKeyboard, command);
- AddEvent(event);
-}
-
-
-void RemoteDebugger::ConnectionClosed() {
- RemoteDebuggerEvent* event =
- new RemoteDebuggerEvent(RemoteDebuggerEvent::kDisconnect,
- i::SmartArrayPointer<char>());
- AddEvent(event);
-}
-
-
-void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
- i::LockGuard<i::Mutex> lock_guard(&event_access_);
- if (head_ == NULL) {
- ASSERT(tail_ == NULL);
- head_ = event;
- tail_ = event;
- } else {
- ASSERT(tail_ != NULL);
- tail_->set_next(event);
- tail_ = event;
- }
- event_available_.Signal();
-}
-
-
-RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
- i::LockGuard<i::Mutex> lock_guard(&event_access_);
- ASSERT(head_ != NULL);
- RemoteDebuggerEvent* result = head_;
- head_ = head_->next();
- if (head_ == NULL) {
- ASSERT(tail_ == result);
- tail_ = NULL;
- }
- return result;
-}
-
-
-void RemoteDebugger::HandleMessageReceived(char* message) {
- Locker lock(isolate_);
- HandleScope scope(isolate_);
-
- // Print the event details.
- TryCatch try_catch;
- Handle<Object> details = Shell::DebugMessageDetails(
- isolate_, Handle<String>::Cast(String::NewFromUtf8(isolate_, message)));
- if (try_catch.HasCaught()) {
- Shell::ReportException(isolate_, &try_catch);
- PrintPrompt();
- return;
- }
- String::Utf8Value str(details->Get(String::NewFromUtf8(isolate_, "text")));
- if (str.length() == 0) {
- // Empty string is used to signal not to process this event.
- return;
- }
- if (*str != NULL) {
- printf("%s\n", *str);
- } else {
- printf("???\n");
- }
-
- bool is_running = details->Get(String::NewFromUtf8(isolate_, "running"))
- ->ToBoolean()
- ->Value();
- PrintPrompt(is_running);
-}
-
-
-void RemoteDebugger::HandleKeyboardCommand(char* command) {
- Locker lock(isolate_);
- HandleScope scope(isolate_);
-
- // Convert the debugger command to a JSON debugger request.
- TryCatch try_catch;
- Handle<Value> request = Shell::DebugCommandToJSONRequest(
- isolate_, String::NewFromUtf8(isolate_, command));
- if (try_catch.HasCaught()) {
- Shell::ReportException(isolate_, &try_catch);
- PrintPrompt();
- return;
- }
-
- // If undefined is returned the command was handled internally and there is
- // no JSON to send.
- if (request->IsUndefined()) {
- PrintPrompt();
- return;
- }
-
- // Send the JSON debugger request.
- i::DebuggerAgentUtil::SendMessage(conn_, Handle<String>::Cast(request));
-}
-
-
-void ReceiverThread::Run() {
- // Receive the connect message (with empty body).
- i::SmartArrayPointer<char> message =
- i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
- ASSERT(message.get() == NULL);
-
- while (true) {
- // Receive a message.
- i::SmartArrayPointer<char> message =
- i::DebuggerAgentUtil::ReceiveMessage(remote_debugger_->conn());
- if (message.get() == NULL) {
- remote_debugger_->ConnectionClosed();
- return;
- }
-
- // Pass the message to the main thread.
- remote_debugger_->MessageReceived(message);
- }
-}
-
-
-void KeyboardThread::Run() {
- static const int kBufferSize = 256;
- while (true) {
- // read keyboard input.
- char command[kBufferSize];
- char* str = fgets(command, kBufferSize, stdin);
- if (str == NULL) {
- break;
- }
-
- // Pass the keyboard command to the main thread.
- remote_debugger_->KeyboardCommand(
- i::SmartArrayPointer<char>(i::StrDup(command)));
- }
-}
-
-
} // namespace v8
diff --git a/src/d8-debug.h b/src/d8-debug.h
index c211be7..ab274e9 100644
--- a/src/d8-debug.h
+++ b/src/d8-debug.h
@@ -8,125 +8,12 @@
#include "d8.h"
#include "debug.h"
-#include "platform/socket.h"
namespace v8 {
-
void HandleDebugEvent(const Debug::EventDetails& event_details);
-// Start the remove debugger connecting to a V8 debugger agent on the specified
-// port.
-void RunRemoteDebugger(Isolate* isolate, int port);
-
-// Forward declerations.
-class RemoteDebuggerEvent;
-class ReceiverThread;
-
-
-// Remote debugging class.
-class RemoteDebugger {
- public:
- explicit RemoteDebugger(Isolate* isolate, int port)
- : isolate_(isolate),
- port_(port),
- event_available_(0),
- head_(NULL), tail_(NULL) {}
- void Run();
-
- // Handle events from the subordinate threads.
- void MessageReceived(i::SmartArrayPointer<char> message);
- void KeyboardCommand(i::SmartArrayPointer<char> command);
- void ConnectionClosed();
-
- private:
- // Add new debugger event to the list.
- void AddEvent(RemoteDebuggerEvent* event);
- // Read next debugger event from the list.
- RemoteDebuggerEvent* GetEvent();
-
- // Handle a message from the debugged V8.
- void HandleMessageReceived(char* message);
- // Handle a keyboard command.
- void HandleKeyboardCommand(char* command);
-
- // Get connection to agent in debugged V8.
- i::Socket* conn() { return conn_; }
-
- Isolate* isolate_;
- int port_; // Port used to connect to debugger V8.
- i::Socket* conn_; // Connection to debugger agent in debugged V8.
-
- // Linked list of events from debugged V8 and from keyboard input. Access to
- // the list is guarded by a mutex and a semaphore signals new items in the
- // list.
- i::Mutex event_access_;
- i::Semaphore event_available_;
- RemoteDebuggerEvent* head_;
- RemoteDebuggerEvent* tail_;
-
- friend class ReceiverThread;
-};
-
-
-// Thread reading from debugged V8 instance.
-class ReceiverThread: public i::Thread {
- public:
- explicit ReceiverThread(RemoteDebugger* remote_debugger)
- : Thread("d8:ReceiverThrd"),
- remote_debugger_(remote_debugger) {}
- ~ReceiverThread() {}
-
- void Run();
-
- private:
- RemoteDebugger* remote_debugger_;
-};
-
-
-// Thread reading keyboard input.
-class KeyboardThread: public i::Thread {
- public:
- explicit KeyboardThread(RemoteDebugger* remote_debugger)
- : Thread("d8:KeyboardThrd"),
- remote_debugger_(remote_debugger) {}
- ~KeyboardThread() {}
-
- void Run();
-
- private:
- RemoteDebugger* remote_debugger_;
-};
-
-
-// Events processed by the main deubgger thread.
-class RemoteDebuggerEvent {
- public:
- RemoteDebuggerEvent(int type, i::SmartArrayPointer<char> data)
- : type_(type), data_(data), next_(NULL) {
- ASSERT(type == kMessage || type == kKeyboard || type == kDisconnect);
- }
-
- static const int kMessage = 1;
- static const int kKeyboard = 2;
- static const int kDisconnect = 3;
-
- int type() { return type_; }
- char* data() { return data_.get(); }
-
- private:
- void set_next(RemoteDebuggerEvent* event) { next_ = event; }
- RemoteDebuggerEvent* next() { return next_; }
-
- int type_;
- i::SmartArrayPointer<char> data_;
- RemoteDebuggerEvent* next_;
-
- friend class RemoteDebugger;
-};
-
-
} // namespace v8
diff --git a/src/d8-readline.cc b/src/d8-readline.cc
index cb59f6e..225c6f0 100644
--- a/src/d8-readline.cc
+++ b/src/d8-readline.cc
@@ -83,7 +83,7 @@
Handle<String> ReadLineEditor::Prompt(const char* prompt) {
char* result = NULL;
{ // Release lock for blocking input.
- Unlocker unlock(Isolate::GetCurrent());
+ Unlocker unlock(isolate_);
result = readline(prompt);
}
if (result == NULL) return Handle<String>();
diff --git a/src/d8.cc b/src/d8.cc
index d19247a..8ea77fd 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -638,16 +638,6 @@
}
-void Shell::DispatchDebugMessages() {
- Isolate* isolate = v8::Isolate::GetCurrent();
- HandleScope handle_scope(isolate);
- v8::Local<v8::Context> context =
- v8::Local<v8::Context>::New(isolate, Shell::evaluation_context_);
- v8::Context::Scope context_scope(context);
- v8::Debug::ProcessDebugMessages();
-}
-
-
int32_t* Counter::Bind(const char* name, bool is_histogram) {
int i;
for (i = 0; i < kMaxNameSize - 1 && name[i]; i++)
@@ -796,9 +786,7 @@
script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE));
// Start the in-process debugger if requested.
- if (i::FLAG_debugger && !i::FLAG_debugger_agent) {
- v8::Debug::SetDebugEventListener2(HandleDebugEvent);
- }
+ if (i::FLAG_debugger) v8::Debug::SetDebugEventListener(HandleDebugEvent);
}
#endif // !V8_SHARED
@@ -920,12 +908,6 @@
Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
utility_context_.Reset(isolate,
Context::New(isolate, NULL, global_template));
-
- // Start the debugger agent if requested.
- if (i::FLAG_debugger_agent) {
- v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true);
- v8::Debug::SetDebugMessageDispatchHandler(DispatchDebugMessages, true);
- }
#endif // !V8_SHARED
}
@@ -1552,19 +1534,8 @@
result = RunMain(isolate, argc, argv);
}
-
-#ifndef V8_SHARED
- // Run remote debugger if requested, but never on --test
- if (i::FLAG_remote_debugger && !options.test_shell) {
- InstallUtilityScript(isolate);
- RunRemoteDebugger(isolate, i::FLAG_debugger_port);
- return 0;
- }
-#endif // !V8_SHARED
-
// Run interactive shell if explicitly requested or if no script has been
// executed, but never on --test
-
if (( options.interactive_shell || !options.script_executed )
&& !options.test_shell ) {
#ifndef V8_SHARED
diff --git a/src/d8.h b/src/d8.h
index 75d007f..014bda0 100644
--- a/src/d8.h
+++ b/src/d8.h
@@ -265,7 +265,6 @@
Handle<String> message);
static Local<Value> DebugCommandToJSONRequest(Isolate* isolate,
Handle<String> command);
- static void DispatchDebugMessages();
static void PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args);
#endif // !V8_SHARED
diff --git a/src/debug-agent.cc b/src/debug-agent.cc
deleted file mode 100644
index 94f334b..0000000
--- a/src/debug-agent.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-// Copyright 2012 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.
-
-#include "v8.h"
-#include "debug.h"
-#include "debug-agent.h"
-#include "platform/socket.h"
-
-namespace v8 {
-namespace internal {
-
-// Public V8 debugger API message handler function. This function just delegates
-// to the debugger agent through it's data parameter.
-void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
- Isolate* isolate = reinterpret_cast<Isolate*>(message.GetIsolate());
- DebuggerAgent* agent = isolate->debugger_agent_instance();
- ASSERT(agent != NULL);
- agent->DebuggerMessage(message);
-}
-
-
-DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port)
- : Thread(name),
- isolate_(isolate),
- name_(StrDup(name)),
- port_(port),
- server_(new Socket),
- terminate_(false),
- session_(NULL),
- terminate_now_(0),
- listening_(0) {
- ASSERT(isolate_->debugger_agent_instance() == NULL);
- isolate_->set_debugger_agent_instance(this);
-}
-
-
-DebuggerAgent::~DebuggerAgent() {
- isolate_->set_debugger_agent_instance(NULL);
- delete server_;
-}
-
-
-// Debugger agent main thread.
-void DebuggerAgent::Run() {
- // Allow this socket to reuse port even if still in TIME_WAIT.
- server_->SetReuseAddress(true);
-
- // First bind the socket to the requested port.
- bool bound = false;
- while (!bound && !terminate_) {
- bound = server_->Bind(port_);
-
- // If an error occurred wait a bit before retrying. The most common error
- // would be that the port is already in use so this avoids a busy loop and
- // make the agent take over the port when it becomes free.
- if (!bound) {
- const TimeDelta kTimeout = TimeDelta::FromSeconds(1);
- PrintF("Failed to open socket on port %d, "
- "waiting %d ms before retrying\n", port_,
- static_cast<int>(kTimeout.InMilliseconds()));
- if (!terminate_now_.WaitFor(kTimeout)) {
- if (terminate_) return;
- }
- }
- }
-
- // Accept connections on the bound port.
- while (!terminate_) {
- bool ok = server_->Listen(1);
- listening_.Signal();
- if (ok) {
- // Accept the new connection.
- Socket* client = server_->Accept();
- ok = client != NULL;
- if (ok) {
- // Create and start a new session.
- CreateSession(client);
- }
- }
- }
-}
-
-
-void DebuggerAgent::Shutdown() {
- // Set the termination flag.
- terminate_ = true;
-
- // Signal termination and make the server exit either its listen call or its
- // binding loop. This makes sure that no new sessions can be established.
- terminate_now_.Signal();
- server_->Shutdown();
- Join();
-
- // Close existing session if any.
- CloseSession();
-}
-
-
-void DebuggerAgent::WaitUntilListening() {
- listening_.Wait();
-}
-
-static const char* kCreateSessionMessage =
- "Remote debugging session already active\r\n";
-
-void DebuggerAgent::CreateSession(Socket* client) {
- LockGuard<RecursiveMutex> session_access_guard(&session_access_);
-
- // If another session is already established terminate this one.
- if (session_ != NULL) {
- int len = StrLength(kCreateSessionMessage);
- int res = client->Send(kCreateSessionMessage, len);
- delete client;
- USE(res);
- return;
- }
-
- // Create a new session and hook up the debug message handler.
- session_ = new DebuggerAgentSession(this, client);
- isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler);
- session_->Start();
-}
-
-
-void DebuggerAgent::CloseSession() {
- LockGuard<RecursiveMutex> session_access_guard(&session_access_);
-
- // Terminate the session.
- if (session_ != NULL) {
- session_->Shutdown();
- session_->Join();
- delete session_;
- session_ = NULL;
- }
-}
-
-
-void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
- LockGuard<RecursiveMutex> session_access_guard(&session_access_);
-
- // Forward the message handling to the session.
- if (session_ != NULL) {
- v8::String::Value val(message.GetJSON());
- session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
- val.length()));
- }
-}
-
-
-DebuggerAgentSession::~DebuggerAgentSession() {
- delete client_;
-}
-
-
-void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
- // Don't do anything during termination.
- if (terminate_) {
- return;
- }
-
- // Terminate the session.
- LockGuard<RecursiveMutex> session_access_guard(&session_access_);
- ASSERT(session == session_);
- if (session == session_) {
- session_->Shutdown();
- delete session_;
- session_ = NULL;
- }
-}
-
-
-void DebuggerAgentSession::Run() {
- // Send the hello message.
- bool ok = DebuggerAgentUtil::SendConnectMessage(client_, agent_->name_.get());
- if (!ok) return;
-
- while (true) {
- // Read data from the debugger front end.
- SmartArrayPointer<char> message =
- DebuggerAgentUtil::ReceiveMessage(client_);
-
- const char* msg = message.get();
- bool is_closing_session = (msg == NULL);
-
- if (msg == NULL) {
- // If we lost the connection, then simulate a disconnect msg:
- msg = "{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}";
-
- } else {
- // Check if we're getting a disconnect request:
- const char* disconnectRequestStr =
- "\"type\":\"request\",\"command\":\"disconnect\"}";
- const char* result = strstr(msg, disconnectRequestStr);
- if (result != NULL) {
- is_closing_session = true;
- }
- }
-
- // Convert UTF-8 to UTF-16.
- unibrow::Utf8Decoder<128> decoder(msg, StrLength(msg));
- int utf16_length = decoder.Utf16Length();
- ScopedVector<uint16_t> temp(utf16_length + 1);
- decoder.WriteUtf16(temp.start(), utf16_length);
-
- // Send the request received to the debugger.
- v8::Debug::SendCommand(reinterpret_cast<v8::Isolate*>(agent_->isolate()),
- temp.start(),
- utf16_length,
- NULL);
-
- if (is_closing_session) {
- // Session is closed.
- agent_->OnSessionClosed(this);
- return;
- }
- }
-}
-
-
-void DebuggerAgentSession::DebuggerMessage(Vector<uint16_t> message) {
- DebuggerAgentUtil::SendMessage(client_, message);
-}
-
-
-void DebuggerAgentSession::Shutdown() {
- // Shutdown the socket to end the blocking receive.
- client_->Shutdown();
-}
-
-
-const char* const DebuggerAgentUtil::kContentLength = "Content-Length";
-
-
-SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) {
- int received;
-
- // Read header.
- int content_length = 0;
- while (true) {
- const int kHeaderBufferSize = 80;
- char header_buffer[kHeaderBufferSize];
- int header_buffer_position = 0;
- char c = '\0'; // One character receive buffer.
- char prev_c = '\0'; // Previous character.
-
- // Read until CRLF.
- while (!(c == '\n' && prev_c == '\r')) {
- prev_c = c;
- received = conn->Receive(&c, 1);
- if (received == 0) {
- PrintF("Error %d\n", Socket::GetLastError());
- return SmartArrayPointer<char>();
- }
-
- // Add character to header buffer.
- if (header_buffer_position < kHeaderBufferSize) {
- header_buffer[header_buffer_position++] = c;
- }
- }
-
- // Check for end of header (empty header line).
- if (header_buffer_position == 2) { // Receive buffer contains CRLF.
- break;
- }
-
- // Terminate header.
- ASSERT(header_buffer_position > 1); // At least CRLF is received.
- ASSERT(header_buffer_position <= kHeaderBufferSize);
- header_buffer[header_buffer_position - 2] = '\0';
-
- // Split header.
- char* key = header_buffer;
- char* value = NULL;
- for (int i = 0; header_buffer[i] != '\0'; i++) {
- if (header_buffer[i] == ':') {
- header_buffer[i] = '\0';
- value = header_buffer + i + 1;
- while (*value == ' ') {
- value++;
- }
- break;
- }
- }
-
- // Check that key is Content-Length.
- if (strcmp(key, kContentLength) == 0) {
- // Get the content length value if present and within a sensible range.
- if (value == NULL || strlen(value) > 7) {
- return SmartArrayPointer<char>();
- }
- for (int i = 0; value[i] != '\0'; i++) {
- // Bail out if illegal data.
- if (value[i] < '0' || value[i] > '9') {
- return SmartArrayPointer<char>();
- }
- content_length = 10 * content_length + (value[i] - '0');
- }
- } else {
- // For now just print all other headers than Content-Length.
- PrintF("%s: %s\n", key, value != NULL ? value : "(no value)");
- }
- }
-
- // Return now if no body.
- if (content_length == 0) {
- return SmartArrayPointer<char>();
- }
-
- // Read body.
- char* buffer = NewArray<char>(content_length + 1);
- received = ReceiveAll(conn, buffer, content_length);
- if (received < content_length) {
- PrintF("Error %d\n", Socket::GetLastError());
- return SmartArrayPointer<char>();
- }
- buffer[content_length] = '\0';
-
- return SmartArrayPointer<char>(buffer);
-}
-
-
-bool DebuggerAgentUtil::SendConnectMessage(Socket* conn,
- const char* embedding_host) {
- static const int kBufferSize = 80;
- char buffer[kBufferSize]; // Sending buffer.
- bool ok;
- int len;
-
- // Send the header.
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "Type: connect\r\n");
- ok = conn->Send(buffer, len);
- if (!ok) return false;
-
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "V8-Version: %s\r\n", v8::V8::GetVersion());
- ok = conn->Send(buffer, len);
- if (!ok) return false;
-
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "Protocol-Version: 1\r\n");
- ok = conn->Send(buffer, len);
- if (!ok) return false;
-
- if (embedding_host != NULL) {
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "Embedding-Host: %s\r\n", embedding_host);
- ok = conn->Send(buffer, len);
- if (!ok) return false;
- }
-
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "%s: 0\r\n", kContentLength);
- ok = conn->Send(buffer, len);
- if (!ok) return false;
-
- // Terminate header with empty line.
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
- ok = conn->Send(buffer, len);
- if (!ok) return false;
-
- // No body for connect message.
-
- return true;
-}
-
-
-bool DebuggerAgentUtil::SendMessage(Socket* conn,
- const Vector<uint16_t> message) {
- static const int kBufferSize = 80;
- char buffer[kBufferSize]; // Sending buffer both for header and body.
-
- // Calculate the message size in UTF-8 encoding.
- int utf8_len = 0;
- int previous = unibrow::Utf16::kNoPreviousCharacter;
- for (int i = 0; i < message.length(); i++) {
- uint16_t character = message[i];
- utf8_len += unibrow::Utf8::Length(character, previous);
- previous = character;
- }
-
- // Send the header.
- int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "%s: %d\r\n", kContentLength, utf8_len);
- if (conn->Send(buffer, len) < len) {
- return false;
- }
-
- // Terminate header with empty line.
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
- if (conn->Send(buffer, len) < len) {
- return false;
- }
-
- // Send message body as UTF-8.
- int buffer_position = 0; // Current buffer position.
- previous = unibrow::Utf16::kNoPreviousCharacter;
- for (int i = 0; i < message.length(); i++) {
- // Write next UTF-8 encoded character to buffer.
- uint16_t character = message[i];
- buffer_position +=
- unibrow::Utf8::Encode(buffer + buffer_position, character, previous);
- ASSERT(buffer_position <= kBufferSize);
-
- // Send buffer if full or last character is encoded.
- if (kBufferSize - buffer_position <
- unibrow::Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit ||
- i == message.length() - 1) {
- if (unibrow::Utf16::IsLeadSurrogate(character)) {
- const int kEncodedSurrogateLength =
- unibrow::Utf16::kUtf8BytesToCodeASurrogate;
- ASSERT(buffer_position >= kEncodedSurrogateLength);
- len = buffer_position - kEncodedSurrogateLength;
- if (conn->Send(buffer, len) < len) {
- return false;
- }
- for (int i = 0; i < kEncodedSurrogateLength; i++) {
- buffer[i] = buffer[buffer_position + i];
- }
- buffer_position = kEncodedSurrogateLength;
- } else {
- len = buffer_position;
- if (conn->Send(buffer, len) < len) {
- return false;
- }
- buffer_position = 0;
- }
- }
- previous = character;
- }
-
- return true;
-}
-
-
-bool DebuggerAgentUtil::SendMessage(Socket* conn,
- const v8::Handle<v8::String> request) {
- static const int kBufferSize = 80;
- char buffer[kBufferSize]; // Sending buffer both for header and body.
-
- // Convert the request to UTF-8 encoding.
- v8::String::Utf8Value utf8_request(request);
-
- // Send the header.
- int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
- "Content-Length: %d\r\n", utf8_request.length());
- if (conn->Send(buffer, len) < len) {
- return false;
- }
-
- // Terminate header with empty line.
- len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
- if (conn->Send(buffer, len) < len) {
- return false;
- }
-
- // Send message body as UTF-8.
- len = utf8_request.length();
- if (conn->Send(*utf8_request, len) < len) {
- return false;
- }
-
- return true;
-}
-
-
-// Receive the full buffer before returning unless an error occours.
-int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) {
- int total_received = 0;
- while (total_received < len) {
- int received = conn->Receive(data + total_received, len - total_received);
- if (received == 0) {
- return total_received;
- }
- total_received += received;
- }
- return total_received;
-}
-
-} } // namespace v8::internal
diff --git a/src/debug-agent.h b/src/debug-agent.h
deleted file mode 100644
index 3e3f25a..0000000
--- a/src/debug-agent.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2006-2008 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.
-
-#ifndef V8_DEBUG_AGENT_H_
-#define V8_DEBUG_AGENT_H_
-
-#include "../include/v8-debug.h"
-#include "platform.h"
-
-namespace v8 {
-namespace internal {
-
-// Forward decelrations.
-class DebuggerAgentSession;
-class Socket;
-
-
-// Debugger agent which starts a socket listener on the debugger port and
-// handles connection from a remote debugger.
-class DebuggerAgent: public Thread {
- public:
- DebuggerAgent(Isolate* isolate, const char* name, int port);
- ~DebuggerAgent();
-
- void Shutdown();
- void WaitUntilListening();
-
- Isolate* isolate() { return isolate_; }
-
- private:
- void Run();
- void CreateSession(Socket* socket);
- void DebuggerMessage(const v8::Debug::Message& message);
- void CloseSession();
- void OnSessionClosed(DebuggerAgentSession* session);
-
- Isolate* isolate_;
- SmartArrayPointer<const char> name_; // Name of the embedding application.
- int port_; // Port to use for the agent.
- Socket* server_; // Server socket for listen/accept.
- bool terminate_; // Termination flag.
- RecursiveMutex session_access_; // Mutex guarding access to session_.
- DebuggerAgentSession* session_; // Current active session if any.
- Semaphore terminate_now_; // Semaphore to signal termination.
- Semaphore listening_;
-
- friend class DebuggerAgentSession;
- friend void DebuggerAgentMessageHandler(const v8::Debug::Message& message);
-
- DISALLOW_COPY_AND_ASSIGN(DebuggerAgent);
-};
-
-
-// Debugger agent session. The session receives requests from the remote
-// debugger and sends debugger events/responses to the remote debugger.
-class DebuggerAgentSession: public Thread {
- public:
- DebuggerAgentSession(DebuggerAgent* agent, Socket* client)
- : Thread("v8:DbgAgntSessn"),
- agent_(agent), client_(client) {}
- ~DebuggerAgentSession();
-
- void DebuggerMessage(Vector<uint16_t> message);
- void Shutdown();
-
- private:
- void Run();
-
- void DebuggerMessage(Vector<char> message);
-
- DebuggerAgent* agent_;
- Socket* client_;
-
- DISALLOW_COPY_AND_ASSIGN(DebuggerAgentSession);
-};
-
-
-// Utility methods factored out to be used by the D8 shell as well.
-class DebuggerAgentUtil {
- public:
- static const char* const kContentLength;
-
- static SmartArrayPointer<char> ReceiveMessage(Socket* conn);
- static bool SendConnectMessage(Socket* conn, const char* embedding_host);
- static bool SendMessage(Socket* conn, const Vector<uint16_t> message);
- static bool SendMessage(Socket* conn, const v8::Handle<v8::String> message);
- static int ReceiveAll(Socket* conn, char* data, int len);
-};
-
-} } // namespace v8::internal
-
-#endif // V8_DEBUG_AGENT_H_
diff --git a/src/debug.cc b/src/debug.cc
index 6adb38a..e3cbf32 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -2632,9 +2632,6 @@
never_unload_debugger_(false),
message_handler_(NULL),
debugger_unload_pending_(false),
- debug_message_dispatch_handler_(NULL),
- message_dispatch_helper_thread_(NULL),
- agent_(NULL),
command_queue_(isolate->logger(), kQueueInitialSize),
command_received_(0),
event_command_queue_(isolate->logger(), kQueueInitialSize),
@@ -3180,7 +3177,7 @@
}
-void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
+void Debugger::SetMessageHandler(v8::Debug::MessageHandler handler) {
LockGuard<RecursiveMutex> with(&debugger_access_);
message_handler_ = handler;
@@ -3189,7 +3186,7 @@
// Send an empty command to the debugger if in a break to make JavaScript
// run again if the debugger is closed.
if (isolate_->debug()->InDebugger()) {
- ProcessCommand(Vector<const uint16_t>::empty());
+ EnqueueCommandMessage(Vector<const uint16_t>::empty());
}
}
}
@@ -3211,18 +3208,6 @@
}
-void Debugger::SetDebugMessageDispatchHandler(
- v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
- LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
- debug_message_dispatch_handler_ = handler;
-
- if (provide_locker && message_dispatch_helper_thread_ == NULL) {
- message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_);
- message_dispatch_helper_thread_->Start();
- }
-}
-
-
// Calls the registered debug message handler. This callback is part of the
// public API.
void Debugger::InvokeMessageHandler(MessageImpl message) {
@@ -3238,8 +3223,8 @@
// a copy of the command string managed by the debugger. Up to this
// point, the command data was managed by the API client. Called
// by the API client thread.
-void Debugger::ProcessCommand(Vector<const uint16_t> command,
- v8::Debug::ClientData* client_data) {
+void Debugger::EnqueueCommandMessage(Vector<const uint16_t> command,
+ v8::Debug::ClientData* client_data) {
// Need to cast away const.
CommandMessage message = CommandMessage::New(
Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
@@ -3253,18 +3238,6 @@
if (!isolate_->debug()->InDebugger()) {
isolate_->stack_guard()->RequestDebugCommand();
}
-
- MessageDispatchHelperThread* dispatch_thread;
- {
- LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
- dispatch_thread = message_dispatch_helper_thread_;
- }
-
- if (dispatch_thread == NULL) {
- CallMessageDispatchHandler();
- } else {
- dispatch_thread->Schedule();
- }
}
@@ -3312,60 +3285,6 @@
}
-static void StubMessageHandler2(const v8::Debug::Message& message) {
- // Simply ignore message.
-}
-
-
-bool Debugger::StartAgent(const char* name, int port,
- bool wait_for_connection) {
- if (wait_for_connection) {
- // Suspend V8 if it is already running or set V8 to suspend whenever
- // it starts.
- // Provide stub message handler; V8 auto-continues each suspend
- // when there is no message handler; we doesn't need it.
- // Once become suspended, V8 will stay so indefinitely long, until remote
- // debugger connects and issues "continue" command.
- Debugger::message_handler_ = StubMessageHandler2;
- v8::Debug::DebugBreak(reinterpret_cast<v8::Isolate*>(isolate_));
- }
-
- if (agent_ == NULL) {
- agent_ = new DebuggerAgent(isolate_, name, port);
- agent_->Start();
- }
- return true;
-}
-
-
-void Debugger::StopAgent() {
- if (agent_ != NULL) {
- agent_->Shutdown();
- agent_->Join();
- delete agent_;
- agent_ = NULL;
- }
-}
-
-
-void Debugger::WaitForAgent() {
- if (agent_ != NULL)
- agent_->WaitUntilListening();
-}
-
-
-void Debugger::CallMessageDispatchHandler() {
- v8::Debug::DebugMessageDispatchHandler handler;
- {
- LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
- handler = Debugger::debug_message_dispatch_handler_;
- }
- if (handler != NULL) {
- handler();
- }
-}
-
-
EnterDebugger::EnterDebugger(Isolate* isolate)
: isolate_(isolate),
prev_(isolate_->debug()->debugger_entry()),
@@ -3703,38 +3622,4 @@
queue_.Clear();
}
-
-MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
- : Thread("v8:MsgDispHelpr"),
- isolate_(isolate), sem_(0),
- already_signalled_(false) {
-}
-
-
-void MessageDispatchHelperThread::Schedule() {
- {
- LockGuard<Mutex> lock_guard(&mutex_);
- if (already_signalled_) {
- return;
- }
- already_signalled_ = true;
- }
- sem_.Signal();
-}
-
-
-void MessageDispatchHelperThread::Run() {
- while (true) {
- sem_.Wait();
- {
- LockGuard<Mutex> lock_guard(&mutex_);
- already_signalled_ = false;
- }
- {
- Locker locker(reinterpret_cast<v8::Isolate*>(isolate_));
- isolate_->debugger()->CallMessageDispatchHandler();
- }
- }
-}
-
} } // namespace v8::internal
diff --git a/src/debug.h b/src/debug.h
index 54e285e..35b29c0 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -8,7 +8,6 @@
#include "allocation.h"
#include "arguments.h"
#include "assembler.h"
-#include "debug-agent.h"
#include "execution.h"
#include "factory.h"
#include "flags.h"
@@ -782,17 +781,11 @@
Handle<JSObject> event_data,
bool auto_continue);
void SetEventListener(Handle<Object> callback, Handle<Object> data);
- void SetMessageHandler(v8::Debug::MessageHandler2 handler);
- void SetDebugMessageDispatchHandler(
- v8::Debug::DebugMessageDispatchHandler handler,
- bool provide_locker);
-
- // Invoke the message handler function.
- void InvokeMessageHandler(MessageImpl message);
+ void SetMessageHandler(v8::Debug::MessageHandler handler);
// Add a debugger command to the command queue.
- void ProcessCommand(Vector<const uint16_t> command,
- v8::Debug::ClientData* client_data = NULL);
+ void EnqueueCommandMessage(Vector<const uint16_t> command,
+ v8::Debug::ClientData* client_data = NULL);
// Check whether there are commands in the command queue.
bool HasCommands();
@@ -803,18 +796,6 @@
MUST_USE_RESULT MaybeHandle<Object> Call(Handle<JSFunction> fun,
Handle<Object> data);
- // Start the debugger agent listening on the provided port.
- bool StartAgent(const char* name, int port,
- bool wait_for_connection = false);
-
- // Stop the debugger agent.
- void StopAgent();
-
- // Blocks until the agent has started listening for connections
- void WaitForAgent();
-
- void CallMessageDispatchHandler();
-
Handle<Context> GetDebugContext();
// Unload the debugger if possible. Only called when no debugger is currently
@@ -882,6 +863,9 @@
Handle<Object> event_data);
void ListenersChanged();
+ // Invoke the message handler function.
+ void InvokeMessageHandler(MessageImpl message);
+
RecursiveMutex debugger_access_; // Mutex guarding debugger variables.
Handle<Object> event_listener_; // Global handle to listener.
Handle<Object> event_listener_data_;
@@ -889,15 +873,9 @@
bool ignore_debugger_; // Are we temporarily ignoring the debugger?
bool live_edit_enabled_; // Enable LiveEdit.
bool never_unload_debugger_; // Can we unload the debugger?
- v8::Debug::MessageHandler2 message_handler_;
+ v8::Debug::MessageHandler message_handler_;
bool debugger_unload_pending_; // Was message handler cleared?
- Mutex dispatch_handler_access_; // Mutex guarding dispatch handler.
- v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
- MessageDispatchHelperThread* message_dispatch_helper_thread_;
-
- DebuggerAgent* agent_;
-
static const int kQueueInitialSize = 4;
LockingCommandMessageQueue command_queue_;
Semaphore command_received_; // Signaled for each command received.
@@ -994,29 +972,6 @@
Debug::AddressId id_;
};
-// The optional thread that Debug Agent may use to temporary call V8 to process
-// pending debug requests if debuggee is not running V8 at the moment.
-// Techincally it does not call V8 itself, rather it asks embedding program
-// to do this via v8::Debug::HostDispatchHandler
-class MessageDispatchHelperThread: public Thread {
- public:
- explicit MessageDispatchHelperThread(Isolate* isolate);
- ~MessageDispatchHelperThread() {}
-
- void Schedule();
-
- private:
- void Run();
-
- Isolate* isolate_;
- Semaphore sem_;
- Mutex mutex_;
- bool already_signalled_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
-};
-
-
} } // namespace v8::internal
#endif // V8_DEBUG_H_
diff --git a/src/execution.cc b/src/execution.cc
index b88cdd5..8f8c153 100644
--- a/src/execution.cc
+++ b/src/execution.cc
@@ -714,6 +714,9 @@
void Execution::ProcessDebugMessages(Isolate* isolate,
bool debug_command_only) {
+ // Assert that we are on the main thread of the isolate.
+ ASSERT(ThreadId::Current().Equals(isolate->thread_id()));
+
isolate->stack_guard()->ClearDebugCommand();
StackLimitCheck check(isolate);
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index 31058ae..1423658 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -660,10 +660,6 @@
DEFINE_bool(dump_counters, false, "Dump counters on exit")
DEFINE_bool(debugger, false, "Enable JavaScript debugger")
-DEFINE_bool(remote_debugger, false, "Connect JavaScript debugger to the "
- "debugger agent in another process")
-DEFINE_bool(debugger_agent, false, "Enable debugger agent")
-DEFINE_int(debugger_port, 5858, "Port to use for remote debugging")
DEFINE_string(map_counters, "", "Map counters to a file")
DEFINE_args(js_arguments,
diff --git a/src/harmony-math.js b/src/harmony-math.js
index 505e9a1..4a8d95b 100644
--- a/src/harmony-math.js
+++ b/src/harmony-math.js
@@ -132,7 +132,7 @@
// ES6 draft 09-27-13, section 20.2.2.16.
-function MathFround(x) {
+function MathFroundJS(x) {
return %MathFround(TO_NUMBER_INLINE(x));
}
@@ -234,7 +234,7 @@
"log10", MathLog10,
"log2", MathLog2,
"hypot", MathHypot,
- "fround", MathFround,
+ "fround", MathFroundJS,
"clz32", MathClz32,
"cbrt", MathCbrt,
"log1p", MathLog1p,
diff --git a/src/heap.cc b/src/heap.cc
index f0c9154..5d338b2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1079,8 +1079,6 @@
MarkCompact(tracer);
sweep_generation_++;
- UpdateSurvivalRateTrend(start_new_space_size);
-
size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSizeOfObjects();
old_generation_allocation_limit_ =
@@ -1091,10 +1089,10 @@
tracer_ = tracer;
Scavenge();
tracer_ = NULL;
-
- UpdateSurvivalRateTrend(start_new_space_size);
}
+ UpdateSurvivalRateTrend(start_new_space_size);
+
if (!new_space_high_promotion_mode_active_ &&
new_space_.Capacity() == new_space_.MaximumCapacity() &&
IsStableOrIncreasingSurvivalTrend() &&
@@ -5460,6 +5458,8 @@
Handle<DependentCode> dep) {
ASSERT(!InNewSpace(*obj));
ASSERT(!InNewSpace(*dep));
+ // This handle scope keeps the table handle local to this function, which
+ // allows us to safely skip write barriers in table update operations.
HandleScope scope(isolate());
Handle<WeakHashTable> table(WeakHashTable::cast(weak_object_to_code_table_),
isolate());
@@ -6179,6 +6179,7 @@
PrintF("nodes_died_in_new=%d ", nodes_died_in_new_space_);
PrintF("nodes_copied_in_new=%d ", nodes_copied_in_new_space_);
PrintF("nodes_promoted=%d ", nodes_promoted_);
+ PrintF("survived=%.1f%% ", heap_->survival_rate_);
if (collector_ == SCAVENGER) {
PrintF("stepscount=%d ", steps_count_since_last_gc_);
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 46f893d..b232a5e 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -11126,7 +11126,7 @@
}
-void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
+void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) {
ASSERT(call->arguments()->length() == 1);
CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
HValue* value = Pop();
diff --git a/src/isolate.h b/src/isolate.h
index 3bed763..9b58321 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -75,7 +75,6 @@
class Debug;
class Debugger;
-class DebuggerAgent;
#if !defined(__arm__) && V8_TARGET_ARCH_ARM || \
!defined(__aarch64__) && V8_TARGET_ARCH_ARM64 || \
@@ -358,7 +357,6 @@
V(bool, fp_stubs_generated, false) \
V(int, max_available_threads, 0) \
V(uint32_t, per_isolate_assert_data, 0xFFFFFFFFu) \
- V(DebuggerAgent*, debugger_agent_instance, NULL) \
V(InterruptCallback, api_interrupt_callback, NULL) \
V(void*, api_interrupt_callback_data, NULL) \
ISOLATE_INIT_SIMULATOR_LIST(V)
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index ff6d2e3..9103910 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -2634,6 +2634,7 @@
ClearDependentCode(DependentCode::cast(value));
table->set(key_index, heap_->the_hole_value());
table->set(value_index, heap_->the_hole_value());
+ table->ElementRemoved();
}
}
}
diff --git a/src/math.js b/src/math.js
index fe10de4..0ad5453 100644
--- a/src/math.js
+++ b/src/math.js
@@ -47,7 +47,7 @@
// ECMA 262 - 15.8.2.5
// The naming of y and x matches the spec, as does the order in which
// ToNumber (valueOf) is called.
-function MathAtan2(y, x) {
+function MathAtan2JS(y, x) {
return %MathAtan2(TO_NUMBER_INLINE(y), TO_NUMBER_INLINE(x));
}
@@ -64,7 +64,7 @@
// ECMA 262 - 15.8.2.8
function MathExp(x) {
- return %MathExp(TO_NUMBER_INLINE(x));
+ return %MathExpRT(TO_NUMBER_INLINE(x));
}
// ECMA 262 - 15.8.2.9
@@ -79,7 +79,7 @@
// has to be -0, which wouldn't be the case with the shift.
return TO_UINT32(x);
} else {
- return %MathFloor(x);
+ return %MathFloorRT(x);
}
}
@@ -173,7 +173,7 @@
// ECMA 262 - 15.8.2.17
function MathSqrt(x) {
- return %_MathSqrt(TO_NUMBER_INLINE(x));
+ return %_MathSqrtRT(TO_NUMBER_INLINE(x));
}
// ECMA 262 - 15.8.2.18
@@ -296,7 +296,7 @@
"sin", MathSin,
"sqrt", MathSqrt,
"tan", MathTan,
- "atan2", MathAtan2,
+ "atan2", MathAtan2JS,
"pow", MathPow,
"max", MathMax,
"min", MathMin,
diff --git a/src/messages.js b/src/messages.js
index 6c50b1b..5f01dc9 100644
--- a/src/messages.js
+++ b/src/messages.js
@@ -957,12 +957,12 @@
var methodName = this.getMethodName();
if (functionName) {
if (typeName &&
- %_CallFunction(functionName, typeName, StringIndexOf) != 0) {
+ %_CallFunction(functionName, typeName, StringIndexOfJS) != 0) {
line += typeName + ".";
}
line += functionName;
if (methodName &&
- (%_CallFunction(functionName, "." + methodName, StringIndexOf) !=
+ (%_CallFunction(functionName, "." + methodName, StringIndexOfJS) !=
functionName.length - methodName.length - 1)) {
line += " [as " + methodName + "]";
}
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index bb0b358..e09feea 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -1298,9 +1298,14 @@
Register scratch = scratch0();
ASSERT(!scratch.is(dividend));
+ // If the divisor is 1, return the dividend.
+ if (divisor == 1) {
+ __ Move(result, dividend);
+ return;
+ }
+
// If the divisor is positive, things are easy: There can be no deopts and we
// can simply do an arithmetic right shift.
- if (divisor == 1) return;
uint16_t shift = WhichPowerOf2Abs(divisor);
if (divisor > 1) {
__ sra(result, dividend, shift);
diff --git a/src/object-observe.js b/src/object-observe.js
index f4b1f53..26a1e18 100644
--- a/src/object-observe.js
+++ b/src/object-observe.js
@@ -35,7 +35,7 @@
var observationState;
-function GetObservationState() {
+function GetObservationStateJS() {
if (IS_UNDEFINED(observationState))
observationState = %GetObservationState();
@@ -76,7 +76,7 @@
function GetContextMaps() {
if (IS_UNDEFINED(contextMaps)) {
var map = GetWeakMapWrapper();
- var observationState = GetObservationState();
+ var observationState = GetObservationStateJS();
contextMaps = {
callbackInfoMap: new map(observationState.callbackInfoMap),
objectInfoMap: new map(observationState.objectInfoMap),
@@ -100,15 +100,15 @@
}
function GetPendingObservers() {
- return GetObservationState().pendingObservers;
+ return GetObservationStateJS().pendingObservers;
}
function SetPendingObservers(pendingObservers) {
- GetObservationState().pendingObservers = pendingObservers;
+ GetObservationStateJS().pendingObservers = pendingObservers;
}
function GetNextCallbackPriority() {
- return GetObservationState().nextCallbackPriority++;
+ return GetObservationStateJS().nextCallbackPriority++;
}
function nullProtoObject() {
@@ -440,7 +440,7 @@
%DefineOrRedefineDataProperty(newRecord, prop, changeRecord[prop],
READ_ONLY + DONT_DELETE);
}
- ObjectFreeze(newRecord);
+ ObjectFreezeJS(newRecord);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, newRecord);
}
@@ -488,8 +488,8 @@
addedCount: addedCount
};
- ObjectFreeze(changeRecord);
- ObjectFreeze(changeRecord.removed);
+ ObjectFreezeJS(changeRecord);
+ ObjectFreezeJS(changeRecord.removed);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
}
@@ -512,7 +512,7 @@
};
}
- ObjectFreeze(changeRecord);
+ ObjectFreezeJS(changeRecord);
ObjectInfoEnqueueInternalChangeRecord(objectInfo, changeRecord);
}
diff --git a/src/objects.cc b/src/objects.cc
index f9a52e5..b7928af 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -16168,7 +16168,10 @@
int entry = table->FindEntry(key);
// Key is already in table, just overwrite value.
if (entry != kNotFound) {
- table->set(EntryToValueIndex(entry), *value);
+ // TODO(ulan): Skipping write barrier is a temporary solution to avoid
+ // memory leaks. Remove this once we have special visitor for weak fixed
+ // arrays.
+ table->set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
return table;
}
@@ -16184,8 +16187,11 @@
Handle<Object> key,
Handle<Object> value) {
DisallowHeapAllocation no_allocation;
- set(EntryToIndex(entry), *key);
- set(EntryToValueIndex(entry), *value);
+ // TODO(ulan): Skipping write barrier is a temporary solution to avoid
+ // memory leaks. Remove this once we have special visitor for weak fixed
+ // arrays.
+ set(EntryToIndex(entry), *key, SKIP_WRITE_BARRIER);
+ set(EntryToValueIndex(entry), *value, SKIP_WRITE_BARRIER);
ElementAdded();
}
diff --git a/src/platform-posix.cc b/src/platform-posix.cc
index 1370ded..642c2e6 100644
--- a/src/platform-posix.cc
+++ b/src/platform-posix.cc
@@ -17,7 +17,6 @@
#include <time.h>
#include <sys/mman.h>
-#include <sys/socket.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
diff --git a/src/platform/socket.cc b/src/platform/socket.cc
deleted file mode 100644
index f4b3387..0000000
--- a/src/platform/socket.cc
+++ /dev/null
@@ -1,201 +0,0 @@
-// Copyright 2013 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.
-
-#include "platform/socket.h"
-
-#if V8_OS_POSIX
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
-#include <netdb.h>
-
-#include <unistd.h>
-#endif
-
-#include <errno.h>
-
-#include "checks.h"
-#include "once.h"
-
-namespace v8 {
-namespace internal {
-
-#if V8_OS_WIN
-
-static V8_DECLARE_ONCE(initialize_winsock) = V8_ONCE_INIT;
-
-
-static void InitializeWinsock() {
- WSADATA wsa_data;
- int result = WSAStartup(MAKEWORD(1, 0), &wsa_data);
- CHECK_EQ(0, result);
-}
-
-#endif // V8_OS_WIN
-
-
-Socket::Socket() {
-#if V8_OS_WIN
- // Be sure to initialize the WinSock DLL first.
- CallOnce(&initialize_winsock, &InitializeWinsock);
-#endif // V8_OS_WIN
-
- // Create the native socket handle.
- native_handle_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-}
-
-
-bool Socket::Bind(int port) {
- ASSERT_GE(port, 0);
- ASSERT_LT(port, 65536);
- if (!IsValid()) return false;
- struct sockaddr_in sin;
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- sin.sin_port = htons(static_cast<uint16_t>(port));
- int result = ::bind(
- native_handle_, reinterpret_cast<struct sockaddr*>(&sin), sizeof(sin));
- return result == 0;
-}
-
-
-bool Socket::Listen(int backlog) {
- if (!IsValid()) return false;
- int result = ::listen(native_handle_, backlog);
- return result == 0;
-}
-
-
-Socket* Socket::Accept() {
- if (!IsValid()) return NULL;
- while (true) {
- NativeHandle native_handle = ::accept(native_handle_, NULL, NULL);
- if (native_handle == kInvalidNativeHandle) {
-#if V8_OS_POSIX
- if (errno == EINTR) continue; // Retry after signal.
-#endif
- return NULL;
- }
- return new Socket(native_handle);
- }
-}
-
-
-bool Socket::Connect(const char* host, const char* port) {
- ASSERT_NE(NULL, host);
- ASSERT_NE(NULL, port);
- if (!IsValid()) return false;
-
- // Lookup host and port.
- struct addrinfo* info = NULL;
- struct addrinfo hint;
- memset(&hint, 0, sizeof(hint));
- hint.ai_family = AF_INET;
- hint.ai_socktype = SOCK_STREAM;
- hint.ai_protocol = IPPROTO_TCP;
- int result = ::getaddrinfo(host, port, &hint, &info);
- if (result != 0) {
- return false;
- }
-
- // Connect to the host on the given port.
- for (struct addrinfo* ai = info; ai != NULL; ai = ai->ai_next) {
- // Try to connect using this addr info.
- while (true) {
- result = ::connect(
- native_handle_, ai->ai_addr, static_cast<int>(ai->ai_addrlen));
- if (result == 0) {
- freeaddrinfo(info);
- return true;
- }
-#if V8_OS_POSIX
- if (errno == EINTR) continue; // Retry after signal.
-#endif
- break;
- }
- }
- freeaddrinfo(info);
- return false;
-}
-
-
-bool Socket::Shutdown() {
- if (!IsValid()) return false;
- // Shutdown socket for both read and write.
-#if V8_OS_POSIX
- int result = ::shutdown(native_handle_, SHUT_RDWR);
- ::close(native_handle_);
-#elif V8_OS_WIN
- int result = ::shutdown(native_handle_, SD_BOTH);
- ::closesocket(native_handle_);
-#endif
- native_handle_ = kInvalidNativeHandle;
- return result == 0;
-}
-
-
-int Socket::Send(const char* buffer, int length) {
- ASSERT(length <= 0 || buffer != NULL);
- if (!IsValid()) return 0;
- int offset = 0;
- while (offset < length) {
- int result = ::send(native_handle_, buffer + offset, length - offset, 0);
- if (result == 0) {
- break;
- } else if (result > 0) {
- ASSERT(result <= length - offset);
- offset += result;
- } else {
-#if V8_OS_POSIX
- if (errno == EINTR) continue; // Retry after signal.
-#endif
- return 0;
- }
- }
- return offset;
-}
-
-
-int Socket::Receive(char* buffer, int length) {
- if (!IsValid()) return 0;
- if (length <= 0) return 0;
- ASSERT_NE(NULL, buffer);
- while (true) {
- int result = ::recv(native_handle_, buffer, length, 0);
- if (result < 0) {
-#if V8_OS_POSIX
- if (errno == EINTR) continue; // Retry after signal.
-#endif
- return 0;
- }
- return result;
- }
-}
-
-
-bool Socket::SetReuseAddress(bool reuse_address) {
- if (!IsValid()) return 0;
- int v = reuse_address ? 1 : 0;
- int result = ::setsockopt(native_handle_, SOL_SOCKET, SO_REUSEADDR,
- reinterpret_cast<char*>(&v), sizeof(v));
- return result == 0;
-}
-
-
-// static
-int Socket::GetLastError() {
-#if V8_OS_POSIX
- return errno;
-#elif V8_OS_WIN
- // Be sure to initialize the WinSock DLL first.
- CallOnce(&initialize_winsock, &InitializeWinsock);
-
- // Now we can safely perform WSA calls.
- return ::WSAGetLastError();
-#endif
-}
-
-} } // namespace v8::internal
diff --git a/src/platform/socket.h b/src/platform/socket.h
deleted file mode 100644
index 8605ae0..0000000
--- a/src/platform/socket.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2013 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.
-
-#ifndef V8_PLATFORM_SOCKET_H_
-#define V8_PLATFORM_SOCKET_H_
-
-#include "globals.h"
-#if V8_OS_WIN
-#include "win32-headers.h"
-#endif
-
-namespace v8 {
-namespace internal {
-
-// ----------------------------------------------------------------------------
-// Socket
-//
-
-class Socket V8_FINAL {
- public:
- Socket();
- ~Socket() { Shutdown(); }
-
- // Server initialization.
- bool Bind(int port) V8_WARN_UNUSED_RESULT;
- bool Listen(int backlog) V8_WARN_UNUSED_RESULT;
- Socket* Accept() V8_WARN_UNUSED_RESULT;
-
- // Client initialization.
- bool Connect(const char* host, const char* port) V8_WARN_UNUSED_RESULT;
-
- // Shutdown socket for both read and write. This causes blocking Send and
- // Receive calls to exit. After |Shutdown()| the Socket object cannot be
- // used for any communication.
- bool Shutdown();
-
- // Data Transimission
- // Return 0 on failure.
- int Send(const char* buffer, int length) V8_WARN_UNUSED_RESULT;
- int Receive(char* buffer, int length) V8_WARN_UNUSED_RESULT;
-
- // Set the value of the SO_REUSEADDR socket option.
- bool SetReuseAddress(bool reuse_address);
-
- V8_INLINE bool IsValid() const {
- return native_handle_ != kInvalidNativeHandle;
- }
-
- static int GetLastError();
-
- // The implementation-defined native handle type.
-#if V8_OS_POSIX
- typedef int NativeHandle;
- static const NativeHandle kInvalidNativeHandle = -1;
-#elif V8_OS_WIN
- typedef SOCKET NativeHandle;
- static const NativeHandle kInvalidNativeHandle = INVALID_SOCKET;
-#endif
-
- NativeHandle& native_handle() {
- return native_handle_;
- }
- const NativeHandle& native_handle() const {
- return native_handle_;
- }
-
- private:
- explicit Socket(NativeHandle native_handle) : native_handle_(native_handle) {}
-
- NativeHandle native_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(Socket);
-};
-
-} } // namespace v8::internal
-
-#endif // V8_PLATFORM_SOCKET_H_
diff --git a/src/promise.js b/src/promise.js
index fa650ea..f4c60d6 100644
--- a/src/promise.js
+++ b/src/promise.js
@@ -204,31 +204,22 @@
);
}
-PromiseCoerce.table = new $WeakMap;
-
function PromiseCoerce(constructor, x) {
if (!IsPromise(x) && IS_SPEC_OBJECT(x)) {
var then;
try {
then = x.then;
} catch(r) {
- var promise = %_CallFunction(constructor, r, PromiseRejected);
- PromiseCoerce.table.set(x, promise);
- return promise;
+ return %_CallFunction(constructor, r, PromiseRejected);
}
- if (typeof then === 'function') {
- if (PromiseCoerce.table.has(x)) {
- return PromiseCoerce.table.get(x);
- } else {
- var deferred = %_CallFunction(constructor, PromiseDeferred);
- PromiseCoerce.table.set(x, deferred.promise);
- try {
- %_CallFunction(x, deferred.resolve, deferred.reject, then);
- } catch(r) {
- deferred.reject(r);
- }
- return deferred.promise;
+ if (IS_SPEC_FUNCTION(then)) {
+ var deferred = %_CallFunction(constructor, PromiseDeferred);
+ try {
+ %_CallFunction(x, deferred.resolve, deferred.reject, then);
+ } catch(r) {
+ deferred.reject(r);
}
+ return deferred.promise;
}
}
return x;
diff --git a/src/regexp.js b/src/regexp.js
index 6a0e2b5..d58ca26 100644
--- a/src/regexp.js
+++ b/src/regexp.js
@@ -80,7 +80,7 @@
// were called again. In SpiderMonkey, this method returns the regexp object.
// In JSC, it returns undefined. For compatibility with JSC, we match their
// behavior.
-function RegExpCompile(pattern, flags) {
+function RegExpCompileJS(pattern, flags) {
// Both JSC and SpiderMonkey treat a missing pattern argument as the
// empty subject string, and an actual undefined value passed as the
// pattern as the string 'undefined'. Note that JSC is inconsistent
@@ -381,7 +381,7 @@
"exec", RegExpExec,
"test", RegExpTest,
"toString", RegExpToString,
- "compile", RegExpCompile
+ "compile", RegExpCompileJS
));
// The length of compile is 1 in SpiderMonkey.
diff --git a/src/runtime.cc b/src/runtime.cc
index a63fd65..f73c5b1 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -7850,7 +7850,7 @@
}
-RUNTIME_FUNCTION(Runtime_MathExp) {
+RUNTIME_FUNCTION(Runtime_MathExpRT) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_exp()->Increment();
@@ -7861,7 +7861,7 @@
}
-RUNTIME_FUNCTION(Runtime_MathFloor) {
+RUNTIME_FUNCTION(Runtime_MathFloorRT) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_floor()->Increment();
@@ -7956,7 +7956,7 @@
}
-RUNTIME_FUNCTION(Runtime_MathSqrt) {
+RUNTIME_FUNCTION(Runtime_MathSqrtRT) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
isolate->counters()->math_sqrt()->Increment();
diff --git a/src/runtime.h b/src/runtime.h
index 6c498de..f0bc718 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -138,9 +138,9 @@
F(MathAcos, 1, 1) \
F(MathAsin, 1, 1) \
F(MathAtan, 1, 1) \
- F(MathFloor, 1, 1) \
+ F(MathFloorRT, 1, 1) \
F(MathAtan2, 2, 1) \
- F(MathExp, 1, 1) \
+ F(MathExpRT, 1, 1) \
F(RoundNumber, 1, 1) \
F(MathFround, 1, 1) \
\
@@ -684,7 +684,7 @@
F(ConstructDouble, 2, 1) \
F(DoubleHi, 1, 1) \
F(DoubleLo, 1, 1) \
- F(MathSqrt, 1, 1) \
+ F(MathSqrtRT, 1, 1) \
F(MathLog, 1, 1) \
/* Debugger */ \
F(DebugCallbackSupportsStepping, 1, 1)
diff --git a/src/store-buffer.cc b/src/store-buffer.cc
index b0f7d2f..547359a 100644
--- a/src/store-buffer.cc
+++ b/src/store-buffer.cc
@@ -332,27 +332,6 @@
#ifdef VERIFY_HEAP
-static void DummyScavengePointer(HeapObject** p, HeapObject* o) {
- // Do nothing.
-}
-
-
-void StoreBuffer::VerifyPointers(PagedSpace* space,
- RegionCallback region_callback) {
- PageIterator it(space);
-
- while (it.has_next()) {
- Page* page = it.next();
- FindPointersToNewSpaceOnPage(
- reinterpret_cast<PagedSpace*>(page->owner()),
- page,
- region_callback,
- &DummyScavengePointer,
- false);
- }
-}
-
-
void StoreBuffer::VerifyPointers(LargeObjectSpace* space) {
LargeObjectIterator it(space);
for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
@@ -378,10 +357,6 @@
void StoreBuffer::Verify() {
#ifdef VERIFY_HEAP
- VerifyPointers(heap_->old_pointer_space(),
- &StoreBuffer::FindPointersToNewSpaceInRegion);
- VerifyPointers(heap_->map_space(),
- &StoreBuffer::FindPointersToNewSpaceInMapsRegion);
VerifyPointers(heap_->lo_space());
#endif
}
@@ -482,94 +457,6 @@
}
-// This function iterates over all the pointers in a paged space in the heap,
-// looking for pointers into new space. Within the pages there may be dead
-// objects that have not been overwritten by free spaces or fillers because of
-// concurrent sweeping. These dead objects may not contain pointers to new
-// space. The garbage areas that have been swept properly (these will normally
-// be the large ones) will be marked with free space and filler map words. In
-// addition any area that has never been used at all for object allocation must
-// be marked with a free space or filler. Because the free space and filler
-// maps do not move we can always recognize these even after a compaction.
-// Normal objects like FixedArrays and JSObjects should not contain references
-// to these maps. Constant pool array objects may contain references to these
-// maps, however, constant pool arrays cannot contain pointers to new space
-// objects, therefore they are skipped. The special garbage section (see
-// comment in spaces.h) is skipped since it can contain absolutely anything.
-// Any objects that are allocated during iteration may or may not be visited by
-// the iteration, but they will not be partially visited.
-void StoreBuffer::FindPointersToNewSpaceOnPage(
- PagedSpace* space,
- Page* page,
- RegionCallback region_callback,
- ObjectSlotCallback slot_callback,
- bool clear_maps) {
- Address visitable_start = page->area_start();
- Address end_of_page = page->area_end();
-
- Address visitable_end = visitable_start;
-
- Object* free_space_map = heap_->free_space_map();
- Object* two_pointer_filler_map = heap_->two_pointer_filler_map();
- Object* constant_pool_array_map = heap_->constant_pool_array_map();
-
- while (visitable_end < end_of_page) {
- // The sweeper thread concurrently may write free space maps and size to
- // this page. We need acquire load here to make sure that we get a
- // consistent view of maps and their sizes.
- Object* o = reinterpret_cast<Object*>(
- Acquire_Load(reinterpret_cast<AtomicWord*>(visitable_end)));
- // Skip fillers or constant pool arrays (which never contain new-space
- // pointers but can contain pointers which can be confused for fillers)
- // but not things that look like fillers in the special garbage section
- // which can contain anything.
- if (o == free_space_map ||
- o == two_pointer_filler_map ||
- o == constant_pool_array_map ||
- (visitable_end == space->top() && visitable_end != space->limit())) {
- if (visitable_start != visitable_end) {
- // After calling this the special garbage section may have moved.
- (this->*region_callback)(visitable_start,
- visitable_end,
- slot_callback,
- clear_maps);
- if (visitable_end >= space->top() && visitable_end < space->limit()) {
- visitable_end = space->limit();
- visitable_start = visitable_end;
- continue;
- }
- }
- if (visitable_end == space->top() && visitable_end != space->limit()) {
- visitable_start = visitable_end = space->limit();
- } else {
- // At this point we are either at the start of a filler, a
- // constant pool array, or we are at the point where the space->top()
- // used to be before the visit_pointer_region call above. Either way we
- // can skip the object at the current spot: We don't promise to visit
- // objects allocated during heap traversal, and if space->top() moved
- // then it must be because an object was allocated at this point.
- visitable_start =
- visitable_end + HeapObject::FromAddress(visitable_end)->Size();
- visitable_end = visitable_start;
- }
- } else {
- ASSERT(o != free_space_map);
- ASSERT(o != two_pointer_filler_map);
- ASSERT(o != constant_pool_array_map);
- ASSERT(visitable_end < space->top() || visitable_end >= space->limit());
- visitable_end += kPointerSize;
- }
- }
- ASSERT(visitable_end == end_of_page);
- if (visitable_start != visitable_end) {
- (this->*region_callback)(visitable_start,
- visitable_end,
- slot_callback,
- clear_maps);
- }
-}
-
-
void StoreBuffer::IteratePointersInStoreBuffer(
ObjectSlotCallback slot_callback,
bool clear_maps) {
@@ -656,14 +543,15 @@
} else {
Page* page = reinterpret_cast<Page*>(chunk);
PagedSpace* owner = reinterpret_cast<PagedSpace*>(page->owner());
- FindPointersToNewSpaceOnPage(
- owner,
- page,
- (owner == heap_->map_space() ?
- &StoreBuffer::FindPointersToNewSpaceInMapsRegion :
- &StoreBuffer::FindPointersToNewSpaceInRegion),
- slot_callback,
- clear_maps);
+ Address start = page->area_start();
+ Address end = page->area_end();
+ if (owner == heap_->map_space()) {
+ FindPointersToNewSpaceInMapsRegion(
+ start, end, slot_callback, clear_maps);
+ } else {
+ FindPointersToNewSpaceInRegion(
+ start, end, slot_callback, clear_maps);
+ }
}
}
}
diff --git a/src/store-buffer.h b/src/store-buffer.h
index bf3a3f7..f775afb 100644
--- a/src/store-buffer.h
+++ b/src/store-buffer.h
@@ -180,18 +180,10 @@
ObjectSlotCallback slot_callback,
bool clear_maps);
- void FindPointersToNewSpaceOnPage(
- PagedSpace* space,
- Page* page,
- RegionCallback region_callback,
- ObjectSlotCallback slot_callback,
- bool clear_maps);
-
void IteratePointersInStoreBuffer(ObjectSlotCallback slot_callback,
bool clear_maps);
#ifdef VERIFY_HEAP
- void VerifyPointers(PagedSpace* space, RegionCallback region_callback);
void VerifyPointers(LargeObjectSpace* space);
#endif
diff --git a/src/string.js b/src/string.js
index 9c90427..1120479 100644
--- a/src/string.js
+++ b/src/string.js
@@ -83,7 +83,7 @@
// ECMA-262 section 15.5.4.7
-function StringIndexOf(pattern /* position */) { // length == 1
+function StringIndexOfJS(pattern /* position */) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "String.prototype.indexOf");
var subject = TO_STRING_INLINE(this);
@@ -100,7 +100,7 @@
// ECMA-262 section 15.5.4.8
-function StringLastIndexOf(pat /* position */) { // length == 1
+function StringLastIndexOfJS(pat /* position */) { // length == 1
CHECK_OBJECT_COERCIBLE(this, "String.prototype.lastIndexOf");
var sub = TO_STRING_INLINE(this);
@@ -131,7 +131,7 @@
//
// This function is implementation specific. For now, we do not
// do anything locale specific.
-function StringLocaleCompare(other) {
+function StringLocaleCompareJS(other) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.localeCompare");
return %StringLocaleCompare(TO_STRING_INLINE(this),
@@ -140,7 +140,7 @@
// ECMA-262 section 15.5.4.10
-function StringMatch(regexp) {
+function StringMatchJS(regexp) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.match");
var subject = TO_STRING_INLINE(this);
@@ -170,7 +170,7 @@
// For now we do nothing, as proper normalization requires big tables.
// If Intl is enabled, then i18n.js will override it and provide the the
// proper functionality.
-function StringNormalize(form) {
+function StringNormalizeJS(form) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.normalize");
var form = form ? TO_STRING_INLINE(form) : 'NFC';
@@ -585,7 +585,7 @@
// ECMA-262 section 15.5.4.14
-function StringSplit(separator, limit) {
+function StringSplitJS(separator, limit) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.split");
var subject = TO_STRING_INLINE(this);
@@ -756,7 +756,7 @@
// ECMA-262, 15.5.4.16
-function StringToLowerCase() {
+function StringToLowerCaseJS() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
return %StringToLowerCase(TO_STRING_INLINE(this));
@@ -772,7 +772,7 @@
// ECMA-262, 15.5.4.18
-function StringToUpperCase() {
+function StringToUpperCaseJS() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.toUpperCase");
return %StringToUpperCase(TO_STRING_INLINE(this));
@@ -787,7 +787,7 @@
}
// ES5, 15.5.4.20
-function StringTrim() {
+function StringTrimJS() {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.trim");
return %StringTrim(TO_STRING_INLINE(this), true, true);
@@ -935,22 +935,22 @@
"charAt", StringCharAt,
"charCodeAt", StringCharCodeAt,
"concat", StringConcat,
- "indexOf", StringIndexOf,
- "lastIndexOf", StringLastIndexOf,
- "localeCompare", StringLocaleCompare,
- "match", StringMatch,
- "normalize", StringNormalize,
+ "indexOf", StringIndexOfJS,
+ "lastIndexOf", StringLastIndexOfJS,
+ "localeCompare", StringLocaleCompareJS,
+ "match", StringMatchJS,
+ "normalize", StringNormalizeJS,
"replace", StringReplace,
"search", StringSearch,
"slice", StringSlice,
- "split", StringSplit,
+ "split", StringSplitJS,
"substring", StringSubstring,
"substr", StringSubstr,
- "toLowerCase", StringToLowerCase,
+ "toLowerCase", StringToLowerCaseJS,
"toLocaleLowerCase", StringToLocaleLowerCase,
- "toUpperCase", StringToUpperCase,
+ "toUpperCase", StringToUpperCaseJS,
"toLocaleUpperCase", StringToLocaleUpperCase,
- "trim", StringTrim,
+ "trim", StringTrimJS,
"trimLeft", StringTrimLeft,
"trimRight", StringTrimRight,
"link", StringLink,
diff --git a/src/uri.js b/src/uri.js
index 123503b..3cc1fe4 100644
--- a/src/uri.js
+++ b/src/uri.js
@@ -403,14 +403,14 @@
// ECMA-262 - B.2.1.
-function URIEscape(str) {
+function URIEscapeJS(str) {
var s = ToString(str);
return %URIEscape(s);
}
// ECMA-262 - B.2.2.
-function URIUnescape(str) {
+function URIUnescapeJS(str) {
var s = ToString(str);
return %URIUnescape(s);
}
@@ -424,8 +424,8 @@
// Set up non-enumerable URI functions on the global object and set
// their names.
InstallFunctions(global, DONT_ENUM, $Array(
- "escape", URIEscape,
- "unescape", URIUnescape,
+ "escape", URIEscapeJS,
+ "unescape", URIUnescapeJS,
"decodeURI", URIDecode,
"decodeURIComponent", URIDecodeComponent,
"encodeURI", URIEncode,
diff --git a/src/v8natives.js b/src/v8natives.js
index cd60cb4..46dfab4 100644
--- a/src/v8natives.js
+++ b/src/v8natives.js
@@ -263,7 +263,7 @@
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
if (IS_SYMBOL(V)) return false;
- var desc = GetOwnProperty(this, P);
+ var desc = GetOwnPropertyJS(this, P);
return IS_UNDEFINED(desc) ? false : desc.isEnumerable();
}
return %IsPropertyEnumerable(ToObject(this), P);
@@ -627,7 +627,7 @@
// ES5 section 8.12.1.
-function GetOwnProperty(obj, v) {
+function GetOwnPropertyJS(obj, v) {
var p = ToName(v);
if (%IsJSProxy(obj)) {
// TODO(rossberg): adjust once there is a story for symbols vs proxies.
@@ -659,7 +659,7 @@
// ES5 section 8.12.7.
function Delete(obj, p, should_throw) {
- var desc = GetOwnProperty(obj, p);
+ var desc = GetOwnPropertyJS(obj, p);
if (IS_UNDEFINED(desc)) return true;
if (desc.isConfigurable()) {
%DeleteProperty(obj, p, 0);
@@ -866,7 +866,7 @@
if (new_length != ToNumber(desc.getValue())) {
throw new $RangeError('defineProperty() array length out of range');
}
- var length_desc = GetOwnProperty(obj, "length");
+ var length_desc = GetOwnPropertyJS(obj, "length");
if (new_length != length && !length_desc.isWritable()) {
if (should_throw) {
throw MakeTypeError("redefine_disallowed", [p]);
@@ -888,7 +888,7 @@
while (new_length < length--) {
var index = ToString(length);
if (emit_splice) {
- var deletedDesc = GetOwnProperty(obj, index);
+ var deletedDesc = GetOwnPropertyJS(obj, index);
if (deletedDesc && deletedDesc.hasValue())
removed[length - new_length] = deletedDesc.getValue();
}
@@ -935,7 +935,7 @@
BeginPerformSplice(obj);
}
- var length_desc = GetOwnProperty(obj, "length");
+ var length_desc = GetOwnPropertyJS(obj, "length");
if ((index >= length && !length_desc.isWritable()) ||
!DefineObjectProperty(obj, p, desc, true)) {
if (emit_splice)
@@ -1007,7 +1007,7 @@
throw MakeTypeError("called_on_non_object",
["Object.getOwnPropertyDescriptor"]);
}
- var desc = GetOwnProperty(obj, p);
+ var desc = GetOwnPropertyJS(obj, p);
return FromPropertyDescriptor(desc);
}
@@ -1157,7 +1157,7 @@
for (var i = 0; i < names.length; i++) {
var N = names[i];
if (!(%HasLocalProperty(standardNames, N))) {
- var attr = GetOwnProperty(attributes, N);
+ var attr = GetOwnPropertyJS(attributes, N);
DefineOwnProperty(descObj, N, attr, true);
}
}
@@ -1242,7 +1242,7 @@
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
- var desc = GetOwnProperty(obj, name);
+ var desc = GetOwnPropertyJS(obj, name);
if (desc.isConfigurable()) {
desc.setConfigurable(false);
DefineOwnProperty(obj, name, desc, true);
@@ -1254,7 +1254,7 @@
// ES5 section 15.2.3.9.
-function ObjectFreeze(obj) {
+function ObjectFreezeJS(obj) {
if (!IS_SPEC_OBJECT(obj)) {
throw MakeTypeError("called_on_non_object", ["Object.freeze"]);
}
@@ -1266,7 +1266,7 @@
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
- var desc = GetOwnProperty(obj, name);
+ var desc = GetOwnPropertyJS(obj, name);
if (desc.isWritable() || desc.isConfigurable()) {
if (IsDataDescriptor(desc)) desc.setWritable(false);
desc.setConfigurable(false);
@@ -1310,7 +1310,7 @@
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
- var desc = GetOwnProperty(obj, name);
+ var desc = GetOwnPropertyJS(obj, name);
if (desc.isConfigurable()) return false;
}
return true;
@@ -1331,7 +1331,7 @@
var names = ObjectGetOwnPropertyNames(obj);
for (var i = 0; i < names.length; i++) {
var name = names[i];
- var desc = GetOwnProperty(obj, name);
+ var desc = GetOwnPropertyJS(obj, name);
if (IsDataDescriptor(desc) && desc.isWritable()) return false;
if (desc.isConfigurable()) return false;
}
@@ -1422,7 +1422,7 @@
"create", ObjectCreate,
"defineProperty", ObjectDefineProperty,
"defineProperties", ObjectDefineProperties,
- "freeze", ObjectFreeze,
+ "freeze", ObjectFreezeJS,
"getPrototypeOf", ObjectGetPrototypeOf,
"setPrototypeOf", ObjectSetPrototypeOf,
"getOwnPropertyDescriptor", ObjectGetOwnPropertyDescriptor,
@@ -1554,7 +1554,7 @@
// ECMA-262 section 15.7.4.5
-function NumberToFixed(fractionDigits) {
+function NumberToFixedJS(fractionDigits) {
var x = this;
if (!IS_NUMBER(this)) {
if (!IS_NUMBER_WRAPPER(this)) {
@@ -1579,7 +1579,7 @@
// ECMA-262 section 15.7.4.6
-function NumberToExponential(fractionDigits) {
+function NumberToExponentialJS(fractionDigits) {
var x = this;
if (!IS_NUMBER(this)) {
if (!IS_NUMBER_WRAPPER(this)) {
@@ -1605,7 +1605,7 @@
// ECMA-262 section 15.7.4.7
-function NumberToPrecision(precision) {
+function NumberToPrecisionJS(precision) {
var x = this;
if (!IS_NUMBER(this)) {
if (!IS_NUMBER_WRAPPER(this)) {
@@ -1694,9 +1694,9 @@
"toString", NumberToString,
"toLocaleString", NumberToLocaleString,
"valueOf", NumberValueOf,
- "toFixed", NumberToFixed,
- "toExponential", NumberToExponential,
- "toPrecision", NumberToPrecision
+ "toFixed", NumberToFixedJS,
+ "toExponential", NumberToExponentialJS,
+ "toPrecision", NumberToPrecisionJS
));
// Harmony Number constructor additions
@@ -1823,7 +1823,7 @@
// If the formal parameters string include ) - an illegal
// character - it may make the combined function expression
// compile. We avoid this problem by checking for this early on.
- if (%_CallFunction(p, ')', StringIndexOf) != -1) {
+ if (%_CallFunction(p, ')', StringIndexOfJS) != -1) {
throw MakeSyntaxError('paren_in_arg_string', []);
}
// If the formal parameters include an unbalanced block comment, the
@@ -1870,7 +1870,7 @@
// Eventually, we should move to a real event queue that allows to maintain
// relative ordering of different kinds of tasks.
-function RunMicrotasks() {
+function RunMicrotasksJS() {
while (%SetMicrotaskPending(false)) {
var microtaskState = %GetMicrotaskState();
if (IS_UNDEFINED(microtaskState.queue))
diff --git a/src/version.cc b/src/version.cc
index e2885c1..7ac27b1 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// system so their names cannot be changed without changing the scripts.
#define MAJOR_VERSION 3
#define MINOR_VERSION 27
-#define BUILD_NUMBER 3
+#define BUILD_NUMBER 4
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)
diff --git a/test/cctest/cctest.gyp b/test/cctest/cctest.gyp
index 745b4c5..1292628 100644
--- a/test/cctest/cctest.gyp
+++ b/test/cctest/cctest.gyp
@@ -105,7 +105,6 @@
'test-representation.cc',
'test-semaphore.cc',
'test-serialize.cc',
- 'test-socket.cc',
'test-spaces.cc',
'test-strings.cc',
'test-symbols.cc',
diff --git a/test/cctest/cctest.h b/test/cctest/cctest.h
index 36e1b96..01d765e 100644
--- a/test/cctest/cctest.h
+++ b/test/cctest/cctest.h
@@ -403,13 +403,6 @@
}
-// Pick a slightly different port to allow tests to be run in parallel.
-static inline int FlagDependentPortOffset() {
- return ::v8::internal::FLAG_crankshaft == false ? 100 :
- ::v8::internal::FLAG_always_opt ? 200 : 0;
-}
-
-
// Helper function that simulates a full new-space in the heap.
static inline void SimulateFullSpace(v8::internal::NewSpace* space) {
int new_linear_size = static_cast<int>(
diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status
index 80a91a0..087b833 100644
--- a/test/cctest/cctest.status
+++ b/test/cctest/cctest.status
@@ -156,6 +156,10 @@
# BUG(3215). Crashes on windows.
'test-lockers/MultithreadedParallelIsolates': [SKIP],
+
+ # BUG(3331). Fails on windows.
+ 'test-heap/NoWeakHashTableLeakWithIncrementalMarking': [SKIP],
+
}], # 'system == windows'
##############################################################################
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index a9ee931..2a2ca3e 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -37,7 +37,6 @@
#include "frames.h"
#include "platform.h"
#include "platform/condition-variable.h"
-#include "platform/socket.h"
#include "stub-cache.h"
#include "utils.h"
@@ -1094,7 +1093,7 @@
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
"function foo(){bar=0;}"))->Run();
v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
@@ -1116,7 +1115,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1126,7 +1125,7 @@
break_point_hit_count = 0;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), "bar=1"))
->Run();
v8::Script::Compile(
@@ -1151,7 +1150,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1161,7 +1160,7 @@
break_point_hit_count = 0;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){}"))->Run();
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
@@ -1185,7 +1184,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1195,7 +1194,7 @@
break_point_hit_count = 0;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){return 1;}"))
->Run();
@@ -1221,7 +1220,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1231,7 +1230,7 @@
break_point_hit_count = 0;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
"function bar(){ this.x = 1;}"))
->Run();
@@ -1257,7 +1256,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1278,7 +1277,7 @@
"frame_source_column");
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){}"))->Run();
v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
@@ -1304,7 +1303,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1327,7 +1326,7 @@
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointCollectGarbage);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointCollectGarbage);
v8::Local<v8::Function> foo;
// Test IC store break point with garbage collection.
@@ -1355,7 +1354,7 @@
SetBreakPoint(foo, 0);
CallWithBreakPoints(env->Global(), foo, 1, 25);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1390,7 +1389,7 @@
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::Function> foo;
// Test IC store break point with garbage collection.
@@ -1436,7 +1435,7 @@
CallAndGC(env->Global(), foo);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1448,7 +1447,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){}"))->Run();
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(),
@@ -1490,7 +1489,7 @@
foo->Run();
CHECK_EQ(8, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Make sure that the break point numbers are consecutive.
@@ -1507,7 +1506,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> script = v8::String::NewFromUtf8(
env->GetIsolate(),
@@ -1592,7 +1591,7 @@
g->Call(env->Global(), 0, NULL);
CHECK_EQ(0, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Make sure that the break point numbers are consecutive.
@@ -1611,7 +1610,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> source = v8::String::NewFromUtf8(
env->GetIsolate(),
@@ -1700,7 +1699,7 @@
g->Call(env->Global(), 0, NULL);
CHECK_EQ(0, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Make sure that the break point numbers are consecutive.
@@ -1720,7 +1719,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> script = v8::String::NewFromUtf8(
env->GetIsolate(),
@@ -1766,7 +1765,7 @@
f->Call(env->Global(), 0, NULL);
CHECK_EQ(3, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1778,7 +1777,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> script = v8::String::NewFromUtf8(
env->GetIsolate(),
@@ -1829,7 +1828,7 @@
}
CHECK_EQ(5, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1841,7 +1840,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> script = v8::String::NewFromUtf8(
env->GetIsolate(),
@@ -1885,7 +1884,7 @@
}
CHECK_EQ(5, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1897,7 +1896,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::Function> f;
v8::Local<v8::String> script = v8::String::NewFromUtf8(
@@ -1949,7 +1948,7 @@
f->Call(env->Global(), 0, NULL);
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -1961,7 +1960,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::Function> f;
v8::Local<v8::String> script_f =
@@ -2018,7 +2017,7 @@
g->Call(env->Global(), 0, NULL);
CHECK_EQ(2, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2030,7 +2029,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::Function> f;
v8::Local<v8::String> script = v8::String::NewFromUtf8(
@@ -2078,7 +2077,7 @@
f->Call(env->Global(), 0, NULL);
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2094,7 +2093,7 @@
frame_function_name_source,
"frame_function_name");
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::Function> f;
v8::Local<v8::Function> g;
@@ -2194,7 +2193,7 @@
v8::Script::Compile(script, &origin)->Run();
CHECK_EQ(0, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2205,7 +2204,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> script =
v8::String::NewFromUtf8(env->GetIsolate(),
@@ -2241,7 +2240,7 @@
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
CHECK_EQ(0, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2253,7 +2252,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Local<v8::String> script_source =
v8::String::NewFromUtf8(env->GetIsolate(),
@@ -2276,7 +2275,7 @@
ClearBreakPointFromJS(env->GetIsolate(), sbp1);
ClearBreakPointFromJS(env->GetIsolate(), sbp2);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2292,7 +2291,7 @@
debug_event_remove_break_point = SetBreakPoint(foo, 0);
// Register the debug event listener pasing the function
- v8::Debug::SetDebugEventListener2(DebugEventRemoveBreakPoint, foo);
+ v8::Debug::SetDebugEventListener(DebugEventRemoveBreakPoint, foo);
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
@@ -2302,7 +2301,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(0, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2312,7 +2311,7 @@
break_point_hit_count = 0;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "function bar(){debugger}"))
->Run();
@@ -2332,7 +2331,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(3, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2342,7 +2341,7 @@
break_point_hit_count = 0;
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "function foo(){debugger;}"))
->Run();
@@ -2360,7 +2359,7 @@
CHECK_EQ(2, break_point_hit_count);
ClearBreakPoint(bp);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2378,7 +2377,7 @@
evaluate_check_source,
"evaluate_check");
// Register the debug event listener
- v8::Debug::SetDebugEventListener2(DebugEventEvaluate);
+ v8::Debug::SetDebugEventListener(DebugEventEvaluate);
// Different expected vaules of x and a when in a break point (u = undefined,
// d = Hello, world!).
@@ -2479,7 +2478,7 @@
};
bar->Call(env->Global(), 2, argv_bar_3);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2497,7 +2496,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(CheckDebugEvent);
+ v8::Debug::SetDebugEventListener(CheckDebugEvent);
v8::Local<v8::Function> foo = CompileFunction(&env,
"function foo(x) {\n"
@@ -2514,7 +2513,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(1, debugEventCount);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2544,7 +2543,7 @@
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(CheckDebugEval);
+ v8::Debug::SetDebugEventListener(CheckDebugEval);
v8::Local<v8::Function> foo = CompileFunction(&env,
"var global = 'Global';\n"
@@ -2572,7 +2571,7 @@
checkGlobalEvalFunction.Clear();
checkFrameEvalFunction.Clear();
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2677,7 +2676,7 @@
// Test that the evaluation of expressions works even from ProcessDebugMessages
// i.e. with empty stack.
TEST(DebugEvaluateWithoutStack) {
- v8::Debug::SetMessageHandler2(DebugProcessDebugMessagesHandler);
+ v8::Debug::SetMessageHandler(DebugProcessDebugMessagesHandler);
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
@@ -2733,8 +2732,8 @@
0);
CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0);
- v8::Debug::SetMessageHandler2(NULL);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2755,7 +2754,7 @@
SetBreakPoint(foo, 3);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
step_action = StepIn;
break_point_hit_count = 0;
@@ -2764,11 +2763,11 @@
// With stepping all break locations are hit.
CHECK_EQ(4, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
SetBreakPoint(foo, 3);
break_point_hit_count = 0;
@@ -2777,7 +2776,7 @@
// Without stepping only active break points are hit.
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2788,7 +2787,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping of keyed load. The statement 'y=1'
// is there to have more than one breakable statement in the loop, TODO(315).
@@ -2826,7 +2825,7 @@
// With stepping all break locations are hit.
CHECK_EQ(35, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2837,7 +2836,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping of keyed store. The statement 'y=1'
// is there to have more than one breakable statement in the loop, TODO(315).
@@ -2874,7 +2873,7 @@
// With stepping all break locations are hit.
CHECK_EQ(34, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2885,7 +2884,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping of named load.
v8::Local<v8::Function> foo = CompileFunction(
@@ -2918,7 +2917,7 @@
// With stepping all break locations are hit.
CHECK_EQ(55, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2928,7 +2927,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping of named store.
v8::Local<v8::Function> foo = CompileFunction(
@@ -2953,7 +2952,7 @@
// With stepping all expected break locations are hit.
CHECK_EQ(expected, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -2970,7 +2969,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping.
v8::Local<v8::Function> foo = CompileFunction(&env,
@@ -2993,11 +2992,11 @@
// With stepping all break locations are hit.
CHECK_EQ(11, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
SetBreakPoint(foo, 0);
break_point_hit_count = 0;
@@ -3006,7 +3005,7 @@
// Without stepping only active break points are hit.
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3016,7 +3015,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3039,7 +3038,7 @@
CHECK_EQ(6, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3049,7 +3048,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3072,7 +3071,7 @@
CHECK_EQ(6, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3083,7 +3082,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3116,7 +3115,7 @@
CHECK_EQ(5, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3127,7 +3126,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3173,7 +3172,7 @@
CHECK_EQ(7, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3184,7 +3183,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3214,7 +3213,7 @@
CHECK_EQ(202, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3225,7 +3224,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3255,7 +3254,7 @@
CHECK_EQ(202, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3266,7 +3265,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3297,7 +3296,7 @@
CHECK_EQ(203, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3308,7 +3307,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3349,7 +3348,7 @@
CHECK_EQ(457, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3360,7 +3359,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3402,7 +3401,7 @@
CHECK_EQ(505, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3412,7 +3411,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3450,7 +3449,7 @@
CHECK_EQ(8, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3460,7 +3459,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3482,7 +3481,7 @@
CHECK_EQ(4, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3493,7 +3492,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3519,7 +3518,7 @@
CHECK_EQ(5, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3534,7 +3533,7 @@
"frame_function_name");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
+ v8::Debug::SetDebugEventListener(DebugEventStepSequence);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3570,7 +3569,7 @@
break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3585,7 +3584,7 @@
"frame_function_name");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
+ v8::Debug::SetDebugEventListener(DebugEventStepSequence);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3622,7 +3621,7 @@
break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded(true);
}
@@ -3637,7 +3636,7 @@
"frame_function_name");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
+ v8::Debug::SetDebugEventListener(DebugEventStepSequence);
// Create a function for testing stepping. Run it to allow it to get
// optimized.
@@ -3657,7 +3656,7 @@
break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3674,7 +3673,7 @@
"foo");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
step_action = StepIn;
break_point_hit_count = 0;
@@ -3683,11 +3682,11 @@
// With stepping all break locations are hit.
CHECK_EQ(3, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
@@ -3695,7 +3694,7 @@
// Without stepping only active break points are hit.
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3713,7 +3712,7 @@
"foo");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
step_action = StepIn;
break_point_hit_count = 0;
@@ -3722,11 +3721,11 @@
// With stepping all break locations are hit.
CHECK_EQ(7, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
@@ -3734,7 +3733,7 @@
// Without stepping only the debugger statement is hit.
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3759,7 +3758,7 @@
"foo");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStep);
+ v8::Debug::SetDebugEventListener(DebugEventStep);
step_action = StepIn;
// Check stepping where the if condition in bar is false.
@@ -3774,11 +3773,11 @@
foo->Call(env->Global(), argc, argv);
CHECK_EQ(8, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
// Register a debug event listener which just counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
break_point_hit_count = 0;
foo->Call(env->Global(), 0, NULL);
@@ -3786,7 +3785,7 @@
// Without stepping only the debugger statement is hit.
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3798,7 +3797,7 @@
env.ExposeDebug();
// Register a debug event listener which counts.
- v8::Debug::SetDebugEventListener2(DebugEventCounter);
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
// Create a script that returns a function.
const char* src = "(function (evt) {})";
@@ -3819,7 +3818,7 @@
CHECK_EQ(1, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -3845,7 +3844,7 @@
CompileFunction(&env, "function notCaught(){throws();}", "notCaught");
v8::V8::AddMessageListener(MessageCallbackCount);
- v8::Debug::SetDebugEventListener2(DebugEventCounter);
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
// Initial state should be no break on exceptions.
DebugEventCounterClear();
@@ -3963,7 +3962,7 @@
CHECK_EQ(1, uncaught_exception_hit_count);
CHECK_EQ(1, message_callback_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
v8::V8::RemoveMessageListeners(MessageCallbackCount);
}
@@ -3983,7 +3982,7 @@
frame_count = CompileFunction(&env, frame_count_source, "frame_count");
v8::V8::AddMessageListener(MessageCallbackCount);
- v8::Debug::SetDebugEventListener2(DebugEventCounter);
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
DebugEventCounterClear();
MessageCallbackCountClear();
@@ -4039,7 +4038,7 @@
"frame_function_name");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventStepSequence);
+ v8::Debug::SetDebugEventListener(DebugEventStepSequence);
// Create functions for testing stepping.
const char* src = "function a() { n(); }; "
@@ -4111,7 +4110,7 @@
break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -4126,7 +4125,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which sets the break flag and counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreak);
+ v8::Debug::SetDebugEventListener(DebugEventBreak);
// Create a function for testing stepping.
const char* src = "function f0() {}"
@@ -4166,7 +4165,7 @@
CHECK_EQ(4 * ARRAY_SIZE(argv), break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -4178,7 +4177,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which sets the break flag and counts.
- v8::Debug::SetDebugEventListener2(DebugEventCounter);
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
// Create a function for testing stepping.
const char* src = "function f() {g()};function g(){i=0; while(i<10){i++}}";
@@ -4204,7 +4203,7 @@
CHECK_EQ(2, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -4220,7 +4219,7 @@
v8::HandleScope scope(isolate);
// Register a debug event listener which sets the break flag and counts.
- v8::Debug::SetDebugEventListener2(DebugEventCounter);
+ v8::Debug::SetDebugEventListener(DebugEventCounter);
// Set the debug break flag.
v8::Debug::DebugBreak(isolate);
@@ -4239,7 +4238,7 @@
CHECK_EQ(0, break_point_hit_count);
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -4961,7 +4960,7 @@
// Create a V8 environment
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetMessageHandler2(MessageHandler);
+ v8::Debug::SetMessageHandler(MessageHandler);
message_queue_debugger_thread.Start();
const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
@@ -5055,7 +5054,7 @@
v8::HandleScope scope(isolate);
TestClientData::ResetCounters();
handled_client_data_instances_count = 0;
- v8::Debug::SetMessageHandler2(MessageHandlerCountingClientData);
+ v8::Debug::SetMessageHandler(MessageHandlerCountingClientData);
const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;";
const int kBufferSize = 1000;
uint16_t buffer[kBufferSize];
@@ -5162,7 +5161,7 @@
v8::Isolate::Scope isolate_scope(isolate);
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetMessageHandler2(&ThreadedMessageHandler);
+ v8::Debug::SetMessageHandler(&ThreadedMessageHandler);
v8::Handle<v8::ObjectTemplate> global_template =
v8::ObjectTemplate::New(env->GetIsolate());
global_template->Set(
@@ -5281,7 +5280,7 @@
v8::Isolate::Scope isolate_scope(isolate);
DebugLocalContext env;
v8::HandleScope scope(isolate);
- v8::Debug::SetMessageHandler2(&BreakpointsMessageHandler);
+ v8::Debug::SetMessageHandler(&BreakpointsMessageHandler);
CompileRun(source_1);
breakpoints_barriers->barrier_1.Wait();
@@ -5438,7 +5437,7 @@
TEST(SetDebugEventListenerOnUninitializedVM) {
- v8::Debug::SetDebugEventListener2(DummyDebugEventListener);
+ v8::Debug::SetDebugEventListener(DummyDebugEventListener);
}
@@ -5447,7 +5446,7 @@
TEST(SetMessageHandlerOnUninitializedVM) {
- v8::Debug::SetMessageHandler2(DummyMessageHandler);
+ v8::Debug::SetMessageHandler(DummyMessageHandler);
}
@@ -5639,7 +5638,7 @@
// Set a debug event listener.
break_point_hit_count = 0;
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
{
v8::HandleScope scope(env->GetIsolate());
// Create a couple of functions for the test.
@@ -5664,12 +5663,12 @@
// Remove the debug event listener without clearing breakpoints. Do this
// outside a handle scope.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded(true);
// Now set a debug message handler.
break_point_hit_count = 0;
- v8::Debug::SetMessageHandler2(MessageHandlerBreakPointHitCount);
+ v8::Debug::SetMessageHandler(MessageHandlerBreakPointHitCount);
{
v8::HandleScope scope(env->GetIsolate());
@@ -5689,7 +5688,7 @@
// Remove the debug message handler without clearing breakpoints. Do this
// outside a handle scope.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded(true);
}
@@ -5732,7 +5731,7 @@
CheckDebuggerUnloaded();
// Set a debug message handler.
- v8::Debug::SetMessageHandler2(MessageHandlerHitCount);
+ v8::Debug::SetMessageHandler(MessageHandlerHitCount);
// Run code to throw a unhandled exception. This should end up in the message
// handler.
@@ -5743,7 +5742,7 @@
// Clear debug message handler.
message_handler_hit_count = 0;
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
// Run code to throw a unhandled exception. This should end up in the message
// handler.
@@ -5762,7 +5761,7 @@
message_handler_hit_count++;
// Clear debug message handler.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
}
@@ -5775,7 +5774,7 @@
CheckDebuggerUnloaded();
// Set a debug message handler.
- v8::Debug::SetMessageHandler2(MessageHandlerClearingMessageHandler);
+ v8::Debug::SetMessageHandler(MessageHandlerClearingMessageHandler);
// Run code to throw a unhandled exception. This should end up in the message
// handler.
@@ -5788,242 +5787,6 @@
}
-/* Test DebugMessageDispatch */
-/* In this test, the V8 thread waits for a message from the debug thread.
- * The DebugMessageDispatchHandler is executed from the debugger thread
- * which signals the V8 thread to wake up.
- */
-
-class DebugMessageDispatchV8Thread : public v8::internal::Thread {
- public:
- DebugMessageDispatchV8Thread() : Thread("DebugMessageDispatchV8Thread") { }
- void Run();
-};
-
-class DebugMessageDispatchDebuggerThread : public v8::internal::Thread {
- public:
- DebugMessageDispatchDebuggerThread()
- : Thread("DebugMessageDispatchDebuggerThread") { }
- void Run();
-};
-
-Barriers* debug_message_dispatch_barriers;
-
-
-static void DebugMessageHandler() {
- debug_message_dispatch_barriers->semaphore_1.Signal();
-}
-
-
-void DebugMessageDispatchV8Thread::Run() {
- v8::Isolate::Scope isolate_scope(CcTest::isolate());
- DebugLocalContext env;
- v8::HandleScope scope(env->GetIsolate());
-
- // Set up debug message dispatch handler.
- v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler);
-
- CompileRun("var y = 1 + 2;\n");
- debug_message_dispatch_barriers->barrier_1.Wait();
- debug_message_dispatch_barriers->semaphore_1.Wait();
- debug_message_dispatch_barriers->barrier_2.Wait();
-}
-
-
-void DebugMessageDispatchDebuggerThread::Run() {
- debug_message_dispatch_barriers->barrier_1.Wait();
- SendContinueCommand();
- debug_message_dispatch_barriers->barrier_2.Wait();
-}
-
-
-TEST(DebuggerDebugMessageDispatch) {
- DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread;
- DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread;
-
- // Create a V8 environment
- Barriers stack_allocated_debug_message_dispatch_barriers;
- debug_message_dispatch_barriers =
- &stack_allocated_debug_message_dispatch_barriers;
-
- debug_message_dispatch_v8_thread.Start();
- debug_message_dispatch_debugger_thread.Start();
-
- debug_message_dispatch_v8_thread.Join();
- debug_message_dispatch_debugger_thread.Join();
-}
-
-
-TEST(DebuggerAgent) {
- v8::V8::Initialize();
- i::Debugger* debugger = CcTest::i_isolate()->debugger();
- // Make sure these ports is not used by other tests to allow tests to run in
- // parallel.
- const int kPort1 = 5858 + FlagDependentPortOffset();
- const int kPort2 = 5857 + FlagDependentPortOffset();
- const int kPort3 = 5856 + FlagDependentPortOffset();
-
- // Make a string with the port2 number.
- const int kPortBufferLen = 6;
- char port2_str[kPortBufferLen];
- OS::SNPrintF(i::Vector<char>(port2_str, kPortBufferLen), "%d", kPort2);
-
- bool ok;
-
- // Test starting and stopping the agent without any client connection.
- debugger->StartAgent("test", kPort1);
- debugger->StopAgent();
- // Test starting the agent, connecting a client and shutting down the agent
- // with the client connected.
- ok = debugger->StartAgent("test", kPort2);
- CHECK(ok);
- debugger->WaitForAgent();
- i::Socket* client = new i::Socket;
- ok = client->Connect("localhost", port2_str);
- CHECK(ok);
- // It is important to wait for a message from the agent. Otherwise,
- // we can close the server socket during "accept" syscall, making it failing
- // (at least on Linux), and the test will work incorrectly.
- char buf;
- ok = client->Receive(&buf, 1) == 1;
- CHECK(ok);
- debugger->StopAgent();
- delete client;
-
- // Test starting and stopping the agent with the required port already
- // occoupied.
- i::Socket* server = new i::Socket;
- ok = server->Bind(kPort3);
- CHECK(ok);
-
- debugger->StartAgent("test", kPort3);
- debugger->StopAgent();
-
- delete server;
-}
-
-
-class DebuggerAgentProtocolServerThread : public i::Thread {
- public:
- explicit DebuggerAgentProtocolServerThread(int port)
- : Thread("DebuggerAgentProtocolServerThread"),
- port_(port),
- server_(NULL),
- client_(NULL),
- listening_(0) {
- }
- ~DebuggerAgentProtocolServerThread() {
- // Close both sockets.
- delete client_;
- delete server_;
- }
-
- void Run();
- void WaitForListening() { listening_.Wait(); }
- char* body() { return body_.get(); }
-
- private:
- int port_;
- i::SmartArrayPointer<char> body_;
- i::Socket* server_; // Server socket used for bind/accept.
- i::Socket* client_; // Single client connection used by the test.
- i::Semaphore listening_; // Signalled when the server is in listen mode.
-};
-
-
-void DebuggerAgentProtocolServerThread::Run() {
- bool ok;
-
- // Create the server socket and bind it to the requested port.
- server_ = new i::Socket;
- CHECK(server_ != NULL);
- ok = server_->Bind(port_);
- CHECK(ok);
-
- // Listen for new connections.
- ok = server_->Listen(1);
- CHECK(ok);
- listening_.Signal();
-
- // Accept a connection.
- client_ = server_->Accept();
- CHECK(client_ != NULL);
-
- // Receive a debugger agent protocol message.
- i::DebuggerAgentUtil::ReceiveMessage(client_);
-}
-
-
-TEST(DebuggerAgentProtocolOverflowHeader) {
- // Make sure this port is not used by other tests to allow tests to run in
- // parallel.
- const int kPort = 5860 + FlagDependentPortOffset();
- static const char* kLocalhost = "localhost";
-
- // Make a string with the port number.
- const int kPortBufferLen = 6;
- char port_str[kPortBufferLen];
- OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort);
-
- // Create a socket server to receive a debugger agent message.
- DebuggerAgentProtocolServerThread* server =
- new DebuggerAgentProtocolServerThread(kPort);
- server->Start();
- server->WaitForListening();
-
- // Connect.
- i::Socket* client = new i::Socket;
- CHECK(client != NULL);
- bool ok = client->Connect(kLocalhost, port_str);
- CHECK(ok);
-
- // Send headers which overflow the receive buffer.
- static const int kBufferSize = 1000;
- char buffer[kBufferSize];
-
- // Long key and short value: XXXX....XXXX:0\r\n.
- for (int i = 0; i < kBufferSize - 4; i++) {
- buffer[i] = 'X';
- }
- buffer[kBufferSize - 4] = ':';
- buffer[kBufferSize - 3] = '0';
- buffer[kBufferSize - 2] = '\r';
- buffer[kBufferSize - 1] = '\n';
- int result = client->Send(buffer, kBufferSize);
- CHECK_EQ(kBufferSize, result);
-
- // Short key and long value: X:XXXX....XXXX\r\n.
- buffer[0] = 'X';
- buffer[1] = ':';
- for (int i = 2; i < kBufferSize - 2; i++) {
- buffer[i] = 'X';
- }
- buffer[kBufferSize - 2] = '\r';
- buffer[kBufferSize - 1] = '\n';
- result = client->Send(buffer, kBufferSize);
- CHECK_EQ(kBufferSize, result);
-
- // Add empty body to request.
- const char* content_length_zero_header = "Content-Length:0\r\n";
- int length = StrLength(content_length_zero_header);
- result = client->Send(content_length_zero_header, length);
- CHECK_EQ(length, result);
- result = client->Send("\r\n", 2);
- CHECK_EQ(2, result);
-
- // Wait until data is received.
- server->Join();
-
- // Check for empty body.
- CHECK(server->body() == NULL);
-
- // Close the client before the server to avoid TIME_WAIT issues.
- client->Shutdown();
- delete client;
- delete server;
-}
-
-
// Test for issue http://code.google.com/p/v8/issues/detail?id=289.
// Make sure that DebugGetLoadedScripts doesn't return scripts
// with disposed external source.
@@ -6087,7 +5850,7 @@
frame_script_name_source,
"frame_script_name");
- v8::Debug::SetDebugEventListener2(DebugEventBreakPointHitCount);
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount);
// Test function source.
v8::Local<v8::String> script = v8::String::NewFromUtf8(env->GetIsolate(),
@@ -6180,7 +5943,7 @@
context_1 = v8::Context::New(isolate, NULL, global_template, global_object);
context_2 = v8::Context::New(isolate, NULL, global_template, global_object);
- v8::Debug::SetMessageHandler2(ContextCheckMessageHandler);
+ v8::Debug::SetMessageHandler(ContextCheckMessageHandler);
// Default data value is undefined.
CHECK(context_1->GetEmbedderData(0)->IsUndefined());
@@ -6219,7 +5982,7 @@
// Two times compile event and two times break event.
CHECK_GT(message_handler_hit_count, 4);
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded();
}
@@ -6248,7 +6011,7 @@
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetMessageHandler2(DebugBreakMessageHandler);
+ v8::Debug::SetMessageHandler(DebugBreakMessageHandler);
// Test functions.
const char* script = "function f() { debugger; g(); } function g() { }";
@@ -6328,7 +6091,7 @@
v8::Local<v8::Value> result = f->Call(env->Global(), argc, argv);
CHECK_EQ(12, result->Int32Value());
- v8::Debug::SetDebugEventListener2(DebugEventDebugBreak);
+ v8::Debug::SetDebugEventListener(DebugEventDebugBreak);
v8::Debug::DebugBreak(env->GetIsolate());
result = f->Call(env->Global(), argc, argv);
@@ -6342,7 +6105,7 @@
// Common part of EvalContextData and NestedBreakEventContextData tests.
static void ExecuteScriptForContextCheck(
- v8::Debug::MessageHandler2 message_handler) {
+ v8::Debug::MessageHandler message_handler) {
// Create a context.
v8::Handle<v8::Context> context_1;
v8::Handle<v8::ObjectTemplate> global_template =
@@ -6350,7 +6113,7 @@
context_1 =
v8::Context::New(CcTest::isolate(), NULL, global_template);
- v8::Debug::SetMessageHandler2(message_handler);
+ v8::Debug::SetMessageHandler(message_handler);
// Default data value is undefined.
CHECK(context_1->GetEmbedderData(0)->IsUndefined());
@@ -6373,7 +6136,7 @@
f->Call(context_1->Global(), 0, NULL);
}
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
}
@@ -6488,7 +6251,7 @@
CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
script_collected_count = 0;
- v8::Debug::SetDebugEventListener2(DebugEventScriptCollectedEvent);
+ v8::Debug::SetDebugEventListener(DebugEventScriptCollectedEvent);
{
v8::Script::Compile(
v8::String::NewFromUtf8(env->GetIsolate(), "eval('a=1')"))->Run();
@@ -6502,7 +6265,7 @@
CHECK_EQ(2, script_collected_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -6551,7 +6314,7 @@
// collected afterwards.
CcTest::heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
- v8::Debug::SetMessageHandler2(ScriptCollectedMessageHandler);
+ v8::Debug::SetMessageHandler(ScriptCollectedMessageHandler);
v8::Script::Compile(v8::String::NewFromUtf8(isolate, "eval('a=1')"))->Run();
v8::Script::Compile(v8::String::NewFromUtf8(isolate, "eval('a=2')"))->Run();
@@ -6570,7 +6333,7 @@
CHECK_EQ(2, script_collected_message_count);
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
}
@@ -6596,18 +6359,18 @@
after_compile_message_count = 0;
const char* script = "var a=1";
- v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
+ v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
->Run();
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
- v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
+ v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
v8::Debug::DebugBreak(env->GetIsolate());
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
->Run();
// Setting listener to NULL should cause debugger unload.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded();
// Compilation cache should be disabled when debugger is active.
@@ -6622,19 +6385,19 @@
after_compile_message_count = 0;
const char* script = "function f() {};";
- v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
+ v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
->Run();
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
- v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
+ v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
v8::Debug::DebugBreak(env->GetIsolate());
v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
f->Call(env->Global(), 0, NULL);
// Setting message handler to NULL should cause debugger unload.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded();
// Compilation cache should be disabled when debugger is active.
@@ -6662,18 +6425,18 @@
exception_event_count = 0;
const char* script = "function f() {throw new Error()};";
- v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
+ v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), script))
->Run();
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
- v8::Debug::SetMessageHandler2(ExceptionMessageHandler);
+ v8::Debug::SetMessageHandler(ExceptionMessageHandler);
v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(
env->Global()->Get(v8::String::NewFromUtf8(env->GetIsolate(), "f")));
f->Call(env->Global(), 0, NULL);
// Setting message handler to NULL should cause debugger unload.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded();
CHECK_EQ(1, exception_event_count);
@@ -6697,7 +6460,7 @@
SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5);
after_compile_message_count = 0;
- v8::Debug::SetMessageHandler2(AfterCompileMessageHandler);
+ v8::Debug::SetMessageHandler(AfterCompileMessageHandler);
v8::ScriptOrigin origin(
v8::String::NewFromUtf8(env->GetIsolate(), resource_name),
@@ -6715,7 +6478,7 @@
ClearBreakPointFromJS(env->GetIsolate(), sbp1);
ClearBreakPointFromJS(env->GetIsolate(), sbp2);
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
}
@@ -6756,7 +6519,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which sets the break flag and counts.
- v8::Debug::SetMessageHandler2(BreakMessageHandler);
+ v8::Debug::SetMessageHandler(BreakMessageHandler);
// Set the debug break flag.
v8::Debug::DebugBreak(env->GetIsolate());
@@ -6775,7 +6538,7 @@
CHECK_EQ(2, break_point_hit_count);
// Get rid of the debug message handler.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded();
}
@@ -6783,7 +6546,7 @@
static int counting_message_handler_counter;
static void CountingMessageHandler(const v8::Debug::Message& message) {
- counting_message_handler_counter++;
+ if (message.IsResponse()) counting_message_handler_counter++;
}
@@ -6795,7 +6558,7 @@
counting_message_handler_counter = 0;
- v8::Debug::SetMessageHandler2(CountingMessageHandler);
+ v8::Debug::SetMessageHandler(CountingMessageHandler);
const int kBufferSize = 1000;
uint16_t buffer[kBufferSize];
@@ -6825,6 +6588,83 @@
CHECK_GE(counting_message_handler_counter, 2);
// Get rid of the debug message handler.
+ v8::Debug::SetMessageHandler(NULL);
+ CheckDebuggerUnloaded();
+}
+
+
+class SendCommandThread : public v8::internal::Thread {
+ public:
+ explicit SendCommandThread(v8::Isolate* isolate)
+ : Thread("SendCommandThread"),
+ semaphore_(0),
+ isolate_(isolate) { }
+
+ static void ProcessDebugMessages(v8::Isolate* isolate, void* data) {
+ v8::Debug::ProcessDebugMessages();
+ reinterpret_cast<v8::internal::Semaphore*>(data)->Signal();
+ }
+
+ virtual void Run() {
+ semaphore_.Wait();
+ const int kBufferSize = 1000;
+ uint16_t buffer[kBufferSize];
+ const char* scripts_command =
+ "{\"seq\":0,"
+ "\"type\":\"request\","
+ "\"command\":\"scripts\"}";
+ int length = AsciiToUtf16(scripts_command, buffer);
+ // Send scripts command.
+
+ for (int i = 0; i < 100; i++) {
+ CHECK_EQ(i, counting_message_handler_counter);
+ // Queue debug message.
+ v8::Debug::SendCommand(isolate_, buffer, length);
+ // Synchronize with the main thread to force message processing.
+ isolate_->RequestInterrupt(ProcessDebugMessages, &semaphore_);
+ semaphore_.Wait();
+ }
+
+ v8::V8::TerminateExecution(isolate_);
+ }
+
+ void StartSending() {
+ semaphore_.Signal();
+ }
+
+ private:
+ v8::internal::Semaphore semaphore_;
+ v8::Isolate* isolate_;
+};
+
+
+static SendCommandThread* send_command_thread_ = NULL;
+
+static void StartSendingCommands(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ send_command_thread_->StartSending();
+}
+
+
+TEST(ProcessDebugMessagesThreaded) {
+ DebugLocalContext env;
+ v8::Isolate* isolate = env->GetIsolate();
+ v8::HandleScope scope(isolate);
+
+ counting_message_handler_counter = 0;
+
+ v8::Debug::SetMessageHandler2(CountingMessageHandler);
+ send_command_thread_ = new SendCommandThread(isolate);
+ send_command_thread_->Start();
+
+ v8::Handle<v8::FunctionTemplate> start =
+ v8::FunctionTemplate::New(isolate, StartSendingCommands);
+ env->Global()->Set(v8_str("start"), start->GetFunction());
+
+ CompileRun("start(); while (true) { }");
+
+ CHECK_EQ(100, counting_message_handler_counter);
+
v8::Debug::SetMessageHandler2(NULL);
CheckDebuggerUnloaded();
}
@@ -6853,7 +6693,7 @@
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
- v8::Debug::SetMessageHandler2(BacktraceData::MessageHandler);
+ v8::Debug::SetMessageHandler(BacktraceData::MessageHandler);
const int kBufferSize = 1000;
uint16_t buffer[kBufferSize];
@@ -6887,7 +6727,7 @@
CHECK_EQ(BacktraceData::frame_counter, 1);
// Get rid of the debug message handler.
- v8::Debug::SetMessageHandler2(NULL);
+ v8::Debug::SetMessageHandler(NULL);
CheckDebuggerUnloaded();
}
@@ -6927,7 +6767,7 @@
"foo");
// Register a debug event listener which steps and counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakMax);
+ v8::Debug::SetDebugEventListener(DebugEventBreakMax);
// Set the debug break flag before calling the code using function.apply.
v8::Debug::DebugBreak(env->GetIsolate());
@@ -6941,7 +6781,7 @@
// When keeping the debug break several break will happen.
CHECK_GT(break_point_hit_count, 1);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -7010,7 +6850,7 @@
named->NewInstance());
// Register the debug event listener
- v8::Debug::SetDebugEventListener2(DebugEventGetAtgumentPropertyValue);
+ v8::Debug::SetDebugEventListener(DebugEventGetAtgumentPropertyValue);
// Create a function that invokes debugger.
v8::Local<v8::Function> foo = CompileFunction(
@@ -7023,7 +6863,7 @@
foo->Call(env->Global(), 0, NULL);
CHECK_EQ(1, break_point_hit_count);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
debugee_context = v8::Handle<v8::Context>();
debugger_context = v8::Handle<v8::Context>();
CheckDebuggerUnloaded();
@@ -7051,13 +6891,13 @@
v8::HandleScope scope(isolate);
expected_context = v8::Context::New(isolate);
expected_callback_data = v8::Int32::New(isolate, 2010);
- v8::Debug::SetDebugEventListener2(DebugEventContextChecker,
+ v8::Debug::SetDebugEventListener(DebugEventContextChecker,
expected_callback_data);
v8::Context::Scope context_scope(expected_context);
v8::Script::Compile(
v8::String::NewFromUtf8(isolate, "(function(){debugger;})();"))->Run();
expected_context.Clear();
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
expected_context_data = v8::Handle<v8::Value>();
CheckDebuggerUnloaded();
}
@@ -7081,7 +6921,7 @@
DebugLocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::HandleScope scope(isolate);
- v8::Debug::SetDebugEventListener2(DebugEventBreakDataChecker);
+ v8::Debug::SetDebugEventListener(DebugEventBreakDataChecker);
TestClientData::constructor_call_counter = 0;
TestClientData::destructor_call_counter = 0;
@@ -7133,7 +6973,7 @@
CHECK_EQ(TestClientData::constructor_call_counter,
TestClientData::destructor_call_counter);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -7187,7 +7027,7 @@
// This tests lazy deoptimization bailout for the stack check, as the first
// time in function bar when using debug break and no break points will be at
// the initial stack check.
- v8::Debug::SetDebugEventListener2(DebugEventBreakDeoptimize);
+ v8::Debug::SetDebugEventListener(DebugEventBreakDeoptimize);
// Compile and run function bar which will optimize it for some flag settings.
v8::Script::Compile(v8::String::NewFromUtf8(
@@ -7200,7 +7040,7 @@
CHECK(debug_event_break_deoptimize_done);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
}
@@ -7255,7 +7095,7 @@
static void ScheduleBreak(const v8::FunctionCallbackInfo<v8::Value>& args) {
- v8::Debug::SetDebugEventListener2(DebugEventBreakWithOptimizedStack);
+ v8::Debug::SetDebugEventListener(DebugEventBreakWithOptimizedStack);
v8::Debug::DebugBreak(args.GetIsolate());
}
@@ -7338,7 +7178,7 @@
v8::HandleScope scope(env->GetIsolate());
// Register a debug event listener which sets the break flag and counts.
- v8::Debug::SetDebugEventListener2(DebugEventBreakMax);
+ v8::Debug::SetDebugEventListener(DebugEventBreakMax);
// Create a function for getting the frame count when hitting the break.
frame_count = CompileFunction(&env, frame_count_source, "frame_count");
@@ -7372,7 +7212,7 @@
TestDebugBreakInLoop("for (;a == 1;) {", loop_bodies, "}");
// Get rid of the debug event listener.
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -7408,7 +7248,7 @@
CHECK_EQ(expected_line_number[i],
i::Script::GetLineNumber(source_script, result->Int32Value()));
}
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
v8::V8::TerminateExecution(CcTest::isolate());
}
@@ -7431,7 +7271,7 @@
"g(false); \n"
"%OptimizeFunctionOnNextCall(g); \n"
"g(true);";
- v8::Debug::SetDebugEventListener2(DebugBreakInlineListener);
+ v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
inline_script =
v8::Script::Compile(v8::String::NewFromUtf8(env->GetIsolate(), source));
inline_script->Run();
@@ -7465,7 +7305,7 @@
// on the stack.
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugEventStepNext);
+ v8::Debug::SetDebugEventListener(DebugEventStepNext);
// We step through the first script. It exits through an exception. We run
// this inside a new frame to record a different FP than the second script
@@ -7477,7 +7317,7 @@
const char* script_2 = "[0].forEach(function() { });";
CompileRun(script_2);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
}
@@ -7494,15 +7334,15 @@
v8::HandleScope scope(env->GetIsolate());
CHECK_EQ(1, CountNativeContexts());
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CompileRun("debugger;");
CHECK_EQ(1, CountNativeContexts());
- v8::Debug::SetDebugEventListener2(NopListener);
+ v8::Debug::SetDebugEventListener(NopListener);
CompileRun("debugger;");
CHECK_EQ(2, CountNativeContexts());
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
}
@@ -7532,7 +7372,7 @@
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
env.ExposeDebug();
- v8::Debug::SetDebugEventListener2(DebugBreakInlineListener);
+ v8::Debug::SetDebugEventListener(DebugBreakInlineListener);
v8::Local<v8::Function> break_here =
CompileFunction(&env, "function break_here(){}", "break_here");
@@ -7554,7 +7394,7 @@
v8::String::Utf8Value utf8(result);
CHECK_EQ("bar", *utf8);
- v8::Debug::SetDebugEventListener2(NULL);
+ v8::Debug::SetDebugEventListener(NULL);
CheckDebuggerUnloaded();
}
@@ -7573,7 +7413,7 @@
TEST(DebugBreakStackTrace) {
DebugLocalContext env;
v8::HandleScope scope(env->GetIsolate());
- v8::Debug::SetDebugEventListener2(DebugBreakStackTraceListener);
+ v8::Debug::SetDebugEventListener(DebugBreakStackTraceListener);
v8::Handle<v8::FunctionTemplate> add_debug_break_template =
v8::FunctionTemplate::New(env->GetIsolate(), AddDebugBreak);
v8::Handle<v8::Function> add_debug_break =
diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc
index 22d2458..45ec1fc 100644
--- a/test/cctest/test-heap.cc
+++ b/test/cctest/test-heap.cc
@@ -40,7 +40,6 @@
using namespace v8::internal;
-
// Go through all incremental marking steps in one swoop.
static void SimulateIncrementalMarking() {
MarkCompactCollector* collector = CcTest::heap()->mark_compact_collector();
@@ -3888,6 +3887,46 @@
}
+TEST(NoWeakHashTableLeakWithIncrementalMarking) {
+ if (i::FLAG_always_opt || !i::FLAG_crankshaft) return;
+ if (!i::FLAG_incremental_marking) return;
+ i::FLAG_weak_embedded_objects_in_optimized_code = true;
+ i::FLAG_allow_natives_syntax = true;
+ i::FLAG_compilation_cache = false;
+ CcTest::InitializeVM();
+ Isolate* isolate = CcTest::i_isolate();
+ v8::internal::Heap* heap = CcTest::heap();
+
+ if (!isolate->use_crankshaft()) return;
+ HandleScope outer_scope(heap->isolate());
+ for (int i = 0; i < 3; i++) {
+ SimulateIncrementalMarking();
+ {
+ LocalContext context;
+ HandleScope scope(heap->isolate());
+ EmbeddedVector<char, 256> source;
+ OS::SNPrintF(source,
+ "function bar%d() {"
+ " return foo%d(1);"
+ "};"
+ "function foo%d(x) { with (x) { return 1 + x; } };"
+ "bar%d();"
+ "bar%d();"
+ "bar%d();"
+ "%OptimizeFunctionOnNextCall(bar%d);"
+ "bar%d();", i, i, i, i, i, i, i, i);
+ CompileRun(source.start());
+ }
+ heap->CollectAllGarbage(i::Heap::kNoGCFlags);
+ }
+ int elements = 0;
+ if (heap->weak_object_to_code_table()->IsHashTable()) {
+ WeakHashTable* t = WeakHashTable::cast(heap->weak_object_to_code_table());
+ elements = t->NumberOfElements();
+ }
+ CHECK_EQ(0, elements);
+}
+
static Handle<JSFunction> OptimizeDummyFunction(const char* name) {
EmbeddedVector<char, 256> source;
diff --git a/test/cctest/test-socket.cc b/test/cctest/test-socket.cc
deleted file mode 100644
index 47d8b17..0000000
--- a/test/cctest/test-socket.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2009 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 "v8.h"
-#include "platform.h"
-#include "platform/socket.h"
-#include "cctest.h"
-
-
-using namespace ::v8::internal;
-
-
-class SocketListenerThread : public Thread {
- public:
- SocketListenerThread(int port, int data_size)
- : Thread("SocketListenerThread"),
- port_(port),
- data_size_(data_size),
- server_(NULL),
- client_(NULL),
- listening_(0) {
- data_ = new char[data_size_];
- }
- ~SocketListenerThread() {
- // Close both sockets.
- delete client_;
- delete server_;
- delete[] data_;
- }
-
- void Run();
- void WaitForListening() { listening_.Wait(); }
- char* data() { return data_; }
-
- private:
- int port_;
- char* data_;
- int data_size_;
- Socket* server_; // Server socket used for bind/accept.
- Socket* client_; // Single client connection used by the test.
- Semaphore listening_; // Signalled when the server socket is in listen mode.
-};
-
-
-void SocketListenerThread::Run() {
- bool ok;
-
- // Create the server socket and bind it to the requested port.
- server_ = new Socket;
- server_->SetReuseAddress(true);
- CHECK(server_ != NULL);
- ok = server_->Bind(port_);
- CHECK(ok);
-
- // Listen for new connections.
- ok = server_->Listen(1);
- CHECK(ok);
- listening_.Signal();
-
- // Accept a connection.
- client_ = server_->Accept();
- CHECK(client_ != NULL);
-
- // Read the expected niumber of bytes of data.
- int bytes_read = 0;
- while (bytes_read < data_size_) {
- bytes_read += client_->Receive(data_ + bytes_read, data_size_ - bytes_read);
- }
-}
-
-
-static bool SendAll(Socket* socket, const char* data, int len) {
- int sent_len = 0;
- while (sent_len < len) {
- int status = socket->Send(data, len);
- if (status <= 0) {
- return false;
- }
- sent_len += status;
- }
- return true;
-}
-
-
-static void SendAndReceive(int port, char *data, int len) {
- static const char* kLocalhost = "localhost";
-
- bool ok;
-
- // Make a string with the port number.
- const int kPortBuferLen = 6;
- char port_str[kPortBuferLen];
- OS::SNPrintF(Vector<char>(port_str, kPortBuferLen), "%d", port);
-
- // Create a socket listener.
- SocketListenerThread* listener = new SocketListenerThread(port, len);
- listener->Start();
- listener->WaitForListening();
-
- // Connect and write some data.
- Socket* client = new Socket;
- CHECK(client != NULL);
- ok = client->Connect(kLocalhost, port_str);
- CHECK(ok);
-
- // Send all the data.
- ok = SendAll(client, data, len);
- CHECK(ok);
-
- // Wait until data is received.
- listener->Join();
-
- // Check that data received is the same as data send.
- for (int i = 0; i < len; i++) {
- CHECK(data[i] == listener->data()[i]);
- }
-
- // Close the client before the listener to avoid TIME_WAIT issues.
- client->Shutdown();
- delete client;
- delete listener;
-}
-
-
-TEST(Socket) {
- // Make sure this port is not used by other tests to allow tests to run in
- // parallel.
- static const int kPort = 5859 + FlagDependentPortOffset();
-
- // Send and receive some data.
- static const int kBufferSizeSmall = 20;
- char small_data[kBufferSizeSmall + 1] = "1234567890abcdefghij";
- SendAndReceive(kPort, small_data, kBufferSizeSmall);
-
- // Send and receive some more data.
- static const int kBufferSizeMedium = 10000;
- char* medium_data = new char[kBufferSizeMedium];
- for (int i = 0; i < kBufferSizeMedium; i++) {
- medium_data[i] = i % 256;
- }
- SendAndReceive(kPort, medium_data, kBufferSizeMedium);
- delete[] medium_data;
-
- // Send and receive even more data.
- static const int kBufferSizeLarge = 1000000;
- char* large_data = new char[kBufferSizeLarge];
- for (int i = 0; i < kBufferSizeLarge; i++) {
- large_data[i] = i % 256;
- }
- SendAndReceive(kPort, large_data, kBufferSizeLarge);
- delete[] large_data;
-}
diff --git a/test/mjsunit/es6/regress/regress-cr372788.js b/test/mjsunit/es6/regress/regress-cr372788.js
new file mode 100644
index 0000000..9b66a7e
--- /dev/null
+++ b/test/mjsunit/es6/regress/regress-cr372788.js
@@ -0,0 +1,45 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+var x = 0;
+var y = 0;
+
+var thenable = { then: function(f) { x++; f(); } };
+
+for (var i = 0; i < 3; ++i) {
+ Promise.resolve(thenable).then(function() { x++; y++; });
+}
+assertEquals(0, x);
+
+(function check() {
+ Promise.resolve().chain(function() {
+ // Delay check until all handlers have run.
+ if (y < 3) check(); else assertEquals(6, x);
+ }).catch(function(e) { %AbortJS("FAILURE: " + e) });
+})();
diff --git a/test/mjsunit/runtime-gen/mathexp.js b/test/mjsunit/runtime-gen/mathexp.js
deleted file mode 100644
index 828f624..0000000
--- a/test/mjsunit/runtime-gen/mathexp.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright 2014 the V8 project authors. All rights reserved.
-// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
-// Flags: --allow-natives-syntax --harmony
-var _x = 1.5;
-%MathExp(_x);
diff --git a/test/mjsunit/runtime-gen/mathfloor.js b/test/mjsunit/runtime-gen/mathexprt.js
similarity index 91%
rename from test/mjsunit/runtime-gen/mathfloor.js
rename to test/mjsunit/runtime-gen/mathexprt.js
index 705c497..4aaacd0 100644
--- a/test/mjsunit/runtime-gen/mathfloor.js
+++ b/test/mjsunit/runtime-gen/mathexprt.js
@@ -2,4 +2,4 @@
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony
var _x = 1.5;
-%MathFloor(_x);
+%MathExpRT(_x);
diff --git a/test/mjsunit/runtime-gen/mathsqrt.js b/test/mjsunit/runtime-gen/mathfloorrt.js
similarity index 91%
copy from test/mjsunit/runtime-gen/mathsqrt.js
copy to test/mjsunit/runtime-gen/mathfloorrt.js
index 9da0cae..0918474 100644
--- a/test/mjsunit/runtime-gen/mathsqrt.js
+++ b/test/mjsunit/runtime-gen/mathfloorrt.js
@@ -2,4 +2,4 @@
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony
var _x = 1.5;
-%_MathSqrt(_x);
+%MathFloorRT(_x);
diff --git a/test/mjsunit/runtime-gen/mathsqrt.js b/test/mjsunit/runtime-gen/mathsqrtrt.js
similarity index 91%
rename from test/mjsunit/runtime-gen/mathsqrt.js
rename to test/mjsunit/runtime-gen/mathsqrtrt.js
index 9da0cae..35a155a 100644
--- a/test/mjsunit/runtime-gen/mathsqrt.js
+++ b/test/mjsunit/runtime-gen/mathsqrtrt.js
@@ -2,4 +2,4 @@
// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY
// Flags: --allow-natives-syntax --harmony
var _x = 1.5;
-%_MathSqrt(_x);
+%_MathSqrtRT(_x);
diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status
index c04412a..0ea08b6 100644
--- a/test/mozilla/mozilla.status
+++ b/test/mozilla/mozilla.status
@@ -113,7 +113,7 @@
'js1_5/Regress/regress-360969-04': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-360969-05': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-360969-06': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
- 'js1_5/extensions/regress-365527': [PASS, ['mode == debug', TIMEOUT, NO_VARIANTS]],
+ 'js1_5/extensions/regress-365527': [PASS, SLOW, ['mode == debug', TIMEOUT, NO_VARIANTS]],
'js1_5/Regress/regress-280769-3': [PASS, ['mode == debug', FAIL]],
'js1_5/Regress/regress-203278-1': [PASS, ['mode == debug', FAIL]],
diff --git a/tools/generate-runtime-tests.py b/tools/generate-runtime-tests.py
index 63f417e..5ce4c9e 100755
--- a/tools/generate-runtime-tests.py
+++ b/tools/generate-runtime-tests.py
@@ -3,10 +3,18 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import itertools
+import multiprocessing
+import optparse
import os
+import random
import re
import shutil
+import signal
+import string
+import subprocess
import sys
+import time
# TODO(jkummerow): Support DATA_VIEW_{G,S}ETTER in runtime.cc
@@ -156,40 +164,504 @@
"SharedFunctionInfo"]
-# Maps argument types to concrete example inputs of that type.
-JS_TYPE_GENERATORS = {
- "Boolean": "true",
- "HeapObject": "new Object()",
- "Int32": "32",
- "JSArray": "new Array()",
- "JSArrayBuffer": "new ArrayBuffer(8)",
- "JSDataView": "new DataView(new ArrayBuffer(8))",
- "JSDate": "new Date()",
- "JSFunction": "function() {}",
- "JSFunctionProxy": "Proxy.createFunction({}, function() {})",
- "JSGeneratorObject": "(function*(){ yield 1; })()",
- "JSMap": "new Map()",
- "JSMapIterator": "%MapCreateIterator(new Map(), 3)",
- "JSObject": "new Object()",
- "JSProxy": "Proxy.create({})",
- "JSReceiver": "new Object()",
- "JSRegExp": "/ab/g",
- "JSSet": "new Set()",
- "JSSetIterator": "%SetCreateIterator(new Set(), 2)",
- "JSTypedArray": "new Int32Array(2)",
- "JSValue": "new String('foo')",
- "JSWeakCollection": "new WeakMap()",
- "Name": "\"name\"",
- "Number": "1.5",
- "Object": "new Object()",
- "PropertyDetails": "513",
- "SeqString": "\"seqstring\"",
- "Smi": 1,
- "StrictMode": "1",
- "String": "\"foo\"",
- "Symbol": "Symbol(\"symbol\")",
- "Uint32": "32",
-}
+class Generator(object):
+
+ def RandomVariable(self, varname, vartype, simple):
+ if simple:
+ return self._Variable(varname, self.GENERATORS[vartype][0])
+ return self.GENERATORS[vartype][1](self, varname,
+ self.DEFAULT_RECURSION_BUDGET)
+
+ @staticmethod
+ def IsTypeSupported(typename):
+ return typename in Generator.GENERATORS
+
+ USUAL_SUSPECT_PROPERTIES = ["size", "length", "byteLength", "__proto__",
+ "prototype", "0", "1", "-1"]
+ DEFAULT_RECURSION_BUDGET = 2
+ PROXY_TRAPS = """{
+ getOwnPropertyDescriptor: function(name) {
+ return {value: function() {}, configurable: true, writable: true,
+ enumerable: true};
+ },
+ getPropertyDescriptor: function(name) {
+ return {value: function() {}, configurable: true, writable: true,
+ enumerable: true};
+ },
+ getOwnPropertyNames: function() { return []; },
+ getPropertyNames: function() { return []; },
+ defineProperty: function(name, descriptor) {},
+ delete: function(name) { return true; },
+ fix: function() {}
+ }"""
+
+ def _Variable(self, name, value, fallback=None):
+ args = { "name": name, "value": value, "fallback": fallback }
+ if fallback:
+ wrapper = "try { %%s } catch(e) { var %(name)s = %(fallback)s; }" % args
+ else:
+ wrapper = "%s"
+ return [wrapper % ("var %(name)s = %(value)s;" % args)]
+
+ def _Boolean(self, name, recursion_budget):
+ return self._Variable(name, random.choice(["true", "false"]))
+
+ def _Oddball(self, name, recursion_budget):
+ return self._Variable(name,
+ random.choice(["true", "false", "undefined", "null"]))
+
+ def _StrictMode(self, name, recursion_budget):
+ return self._Variable(name, random.choice([0, 1]))
+
+ def _Int32(self, name, recursion_budget=0):
+ die = random.random()
+ if die < 0.5:
+ value = random.choice([-3, -1, 0, 1, 2, 10, 515, 0x3fffffff, 0x7fffffff,
+ 0x40000000, -0x40000000, -0x80000000])
+ elif die < 0.75:
+ value = random.randint(-1000, 1000)
+ else:
+ value = random.randint(-0x80000000, 0x7fffffff)
+ return self._Variable(name, value)
+
+ def _Uint32(self, name, recursion_budget=0):
+ die = random.random()
+ if die < 0.5:
+ value = random.choice([0, 1, 2, 3, 4, 8, 0x3fffffff, 0x40000000,
+ 0x7fffffff, 0xffffffff])
+ elif die < 0.75:
+ value = random.randint(0, 1000)
+ else:
+ value = random.randint(0, 0xffffffff)
+ return self._Variable(name, value)
+
+ def _Smi(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.5:
+ value = random.choice([-5, -1, 0, 1, 2, 3, 0x3fffffff, -0x40000000])
+ elif die < 0.75:
+ value = random.randint(-1000, 1000)
+ else:
+ value = random.randint(-0x40000000, 0x3fffffff)
+ return self._Variable(name, value)
+
+ def _Number(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.5:
+ return self._Smi(name, recursion_budget)
+ elif die < 0.6:
+ value = random.choice(["Infinity", "-Infinity", "NaN", "-0",
+ "1.7976931348623157e+308", # Max value.
+ "2.2250738585072014e-308", # Min value.
+ "4.9406564584124654e-324"]) # Min subnormal.
+ else:
+ value = random.lognormvariate(0, 15)
+ return self._Variable(name, value)
+
+ def _RawRandomString(self, minlength=0, maxlength=100,
+ alphabet=string.ascii_letters):
+ length = random.randint(minlength, maxlength)
+ result = ""
+ for i in xrange(length):
+ result += random.choice(alphabet)
+ return result
+
+ def _SeqString(self, name, recursion_budget):
+ s1 = self._RawRandomString(1, 5)
+ s2 = self._RawRandomString(1, 5)
+ # 'foo' + 'bar'
+ return self._Variable(name, "\"%s\" + \"%s\"" % (s1, s2))
+
+ def _SlicedString(self, name):
+ s = self._RawRandomString(20, 30)
+ # 'ffoo12345678901234567890'.substr(1)
+ return self._Variable(name, "\"%s\".substr(1)" % s)
+
+ def _ConsString(self, name):
+ s1 = self._RawRandomString(8, 15)
+ s2 = self._RawRandomString(8, 15)
+ # 'foo12345' + (function() { return 'bar12345';})()
+ return self._Variable(name,
+ "\"%s\" + (function() { return \"%s\";})()" % (s1, s2))
+
+ def _ExternalString(self, name):
+ # Needs --expose-externalize-string.
+ return None
+
+ def _InternalizedString(self, name):
+ return self._Variable(name, "\"%s\"" % self._RawRandomString(0, 20))
+
+ def _String(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.5:
+ string = random.choice(self.USUAL_SUSPECT_PROPERTIES)
+ return self._Variable(name, "\"%s\"" % string)
+ elif die < 0.6:
+ number_name = name + "_number"
+ result = self._Number(number_name, recursion_budget)
+ return result + self._Variable(name, "\"\" + %s" % number_name)
+ elif die < 0.7:
+ return self._SeqString(name, recursion_budget)
+ elif die < 0.8:
+ return self._ConsString(name)
+ elif die < 0.9:
+ return self._InternalizedString(name)
+ else:
+ return self._SlicedString(name)
+
+ def _Symbol(self, name, recursion_budget):
+ raw_string_name = name + "_1"
+ result = self._String(raw_string_name, recursion_budget)
+ return result + self._Variable(name, "Symbol(%s)" % raw_string_name)
+
+ def _Name(self, name, recursion_budget):
+ if random.random() < 0.2:
+ return self._Symbol(name, recursion_budget)
+ return self._String(name, recursion_budget)
+
+ def _JSValue(self, name, recursion_budget):
+ die = random.random()
+ raw_name = name + "_1"
+ if die < 0.33:
+ result = self._String(raw_name, recursion_budget)
+ return result + self._Variable(name, "new String(%s)" % raw_name)
+ elif die < 0.66:
+ result = self._Boolean(raw_name, recursion_budget)
+ return result + self._Variable(name, "new Boolean(%s)" % raw_name)
+ else:
+ result = self._Number(raw_name, recursion_budget)
+ return result + self._Variable(name, "new Number(%s)" % raw_name)
+
+ def _RawRandomPropertyName(self):
+ if random.random() < 0.5:
+ return random.choice(self.USUAL_SUSPECT_PROPERTIES)
+ return self._RawRandomString(0, 10)
+
+ def _AddProperties(self, name, result, recursion_budget):
+ propcount = random.randint(0, 3)
+ propname = None
+ for i in range(propcount):
+ die = random.random()
+ if die < 0.5:
+ propname = "%s_prop%d" % (name, i)
+ result += self._Name(propname, recursion_budget - 1)
+ else:
+ propname = "\"%s\"" % self._RawRandomPropertyName()
+ propvalue_name = "%s_val%d" % (name, i)
+ result += self._Object(propvalue_name, recursion_budget - 1)
+ result.append("try { %s[%s] = %s; } catch (e) {}" %
+ (name, propname, propvalue_name))
+ if random.random() < 0.2 and propname:
+ # Force the object to slow mode.
+ result.append("delete %s[%s];" % (name, propname))
+
+ def _RandomElementIndex(self, element_name, result):
+ if random.random() < 0.5:
+ return random.randint(-1000, 1000)
+ result += self._Smi(element_name, 0)
+ return element_name
+
+ def _AddElements(self, name, result, recursion_budget):
+ elementcount = random.randint(0, 3)
+ for i in range(elementcount):
+ element_name = "%s_idx%d" % (name, i)
+ index = self._RandomElementIndex(element_name, result)
+ value_name = "%s_elt%d" % (name, i)
+ result += self._Object(value_name, recursion_budget - 1)
+ result.append("try { %s[%s] = %s; } catch(e) {}" %
+ (name, index, value_name))
+
+ def _AddAccessors(self, name, result, recursion_budget):
+ accessorcount = random.randint(0, 3)
+ for i in range(accessorcount):
+ propname = self._RawRandomPropertyName()
+ what = random.choice(["get", "set"])
+ function_name = "%s_access%d" % (name, i)
+ result += self._PlainFunction(function_name, recursion_budget - 1)
+ result.append("try { Object.defineProperty(%s, \"%s\", {%s: %s}); } "
+ "catch (e) {}" % (name, propname, what, function_name))
+
+ def _PlainArray(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.5:
+ literal = random.choice(["[]", "[1, 2]", "[1.5, 2.5]",
+ "['a', 'b', 1, true]"])
+ return self._Variable(name, literal)
+ else:
+ new = random.choice(["", "new "])
+ length = random.randint(0, 101000)
+ return self._Variable(name, "%sArray(%d)" % (new, length))
+
+ def _PlainObject(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.67:
+ literal_propcount = random.randint(0, 3)
+ properties = []
+ result = []
+ for i in range(literal_propcount):
+ propname = self._RawRandomPropertyName()
+ propvalue_name = "%s_lit%d" % (name, i)
+ result += self._Object(propvalue_name, recursion_budget - 1)
+ properties.append("\"%s\": %s" % (propname, propvalue_name))
+ return result + self._Variable(name, "{%s}" % ", ".join(properties))
+ else:
+ return self._Variable(name, "new Object()")
+
+ def _JSArray(self, name, recursion_budget):
+ result = self._PlainArray(name, recursion_budget)
+ self._AddAccessors(name, result, recursion_budget)
+ self._AddProperties(name, result, recursion_budget)
+ self._AddElements(name, result, recursion_budget)
+ return result
+
+ def _RawRandomBufferLength(self):
+ if random.random() < 0.2:
+ return random.choice([0, 1, 8, 0x40000000, 0x80000000])
+ return random.randint(0, 1000)
+
+ def _JSArrayBuffer(self, name, recursion_budget):
+ length = self._RawRandomBufferLength()
+ return self._Variable(name, "new ArrayBuffer(%d)" % length)
+
+ def _JSDataView(self, name, recursion_budget):
+ buffer_name = name + "_buffer"
+ result = self._JSArrayBuffer(buffer_name, recursion_budget)
+ args = [buffer_name]
+ die = random.random()
+ if die < 0.67:
+ offset = self._RawRandomBufferLength()
+ args.append("%d" % offset)
+ if die < 0.33:
+ length = self._RawRandomBufferLength()
+ args.append("%d" % length)
+ result += self._Variable(name, "new DataView(%s)" % ", ".join(args),
+ fallback="new DataView(new ArrayBuffer(8))")
+ return result
+
+ def _JSDate(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.25:
+ return self._Variable(name, "new Date()")
+ elif die < 0.5:
+ ms_name = name + "_ms"
+ result = self._Number(ms_name, recursion_budget)
+ return result + self._Variable(name, "new Date(%s)" % ms_name)
+ elif die < 0.75:
+ str_name = name + "_str"
+ month = random.choice(["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
+ "Aug", "Sep", "Oct", "Nov", "Dec"])
+ day = random.randint(1, 28)
+ year = random.randint(1900, 2100)
+ hour = random.randint(0, 23)
+ minute = random.randint(0, 59)
+ second = random.randint(0, 59)
+ str_value = ("\"%s %s, %s %s:%s:%s\"" %
+ (month, day, year, hour, minute, second))
+ result = self._Variable(str_name, str_value)
+ return result + self._Variable(name, "new Date(%s)" % str_name)
+ else:
+ components = tuple(map(lambda x: "%s_%s" % (name, x),
+ ["y", "m", "d", "h", "min", "s", "ms"]))
+ return ([j for i in map(self._Int32, components) for j in i] +
+ self._Variable(name, "new Date(%s)" % ", ".join(components)))
+
+ def _PlainFunction(self, name, recursion_budget):
+ result_name = "result"
+ body = ["function() {"]
+ body += self._Object(result_name, recursion_budget - 1)
+ body.append("return result;\n}")
+ return self._Variable(name, "%s" % "\n".join(body))
+
+ def _JSFunction(self, name, recursion_budget):
+ result = self._PlainFunction(name, recursion_budget)
+ self._AddAccessors(name, result, recursion_budget)
+ self._AddProperties(name, result, recursion_budget)
+ self._AddElements(name, result, recursion_budget)
+ return result
+
+ def _JSFunctionProxy(self, name, recursion_budget):
+ # TODO(jkummerow): Revisit this as the Proxy implementation evolves.
+ return self._Variable(name, "Proxy.createFunction(%s, function() {})" %
+ self.PROXY_TRAPS)
+
+ def _JSGeneratorObject(self, name, recursion_budget):
+ # TODO(jkummerow): Be more creative here?
+ return self._Variable(name, "(function*() { yield 1; })()")
+
+ def _JSMap(self, name, recursion_budget, weak=""):
+ result = self._Variable(name, "new %sMap()" % weak)
+ num_entries = random.randint(0, 3)
+ for i in range(num_entries):
+ key_name = "%s_k%d" % (name, i)
+ value_name = "%s_v%d" % (name, i)
+ if weak:
+ result += self._JSObject(key_name, recursion_budget - 1)
+ else:
+ result += self._Object(key_name, recursion_budget - 1)
+ result += self._Object(value_name, recursion_budget - 1)
+ result.append("%s.set(%s, %s)" % (name, key_name, value_name))
+ return result
+
+ def _JSMapIterator(self, name, recursion_budget):
+ map_name = name + "_map"
+ result = self._JSMap(map_name, recursion_budget)
+ iterator_type = random.randint(1, 3)
+ return (result + self._Variable(name, "%%MapCreateIterator(%s, %d)" %
+ (map_name, iterator_type)))
+
+ def _JSProxy(self, name, recursion_budget):
+ # TODO(jkummerow): Revisit this as the Proxy implementation evolves.
+ return self._Variable(name, "Proxy.create(%s)" % self.PROXY_TRAPS)
+
+ def _JSRegExp(self, name, recursion_budget):
+ flags = random.choice(["", "g", "i", "m", "gi"])
+ string = "a(b|c)*a" # TODO(jkummerow): Be more creative here?
+ ctor = random.choice(["/%s/%s", "new RegExp(\"%s\", \"%s\")"])
+ return self._Variable(name, ctor % (string, flags))
+
+ def _JSSet(self, name, recursion_budget, weak=""):
+ result = self._Variable(name, "new %sSet()" % weak)
+ num_entries = random.randint(0, 3)
+ for i in range(num_entries):
+ element_name = "%s_e%d" % (name, i)
+ if weak:
+ result += self._JSObject(element_name, recursion_budget - 1)
+ else:
+ result += self._Object(element_name, recursion_budget - 1)
+ result.append("%s.add(%s)" % (name, element_name))
+ return result
+
+ def _JSSetIterator(self, name, recursion_budget):
+ set_name = name + "_set"
+ result = self._JSSet(set_name, recursion_budget)
+ iterator_type = random.randint(2, 3)
+ return (result + self._Variable(name, "%%SetCreateIterator(%s, %d)" %
+ (set_name, iterator_type)))
+
+ def _JSTypedArray(self, name, recursion_budget):
+ arraytype = random.choice(["Int8", "Int16", "Int32", "Uint8", "Uint16",
+ "Uint32", "Float32", "Float64", "Uint8Clamped"])
+ ctor_type = random.randint(0, 3)
+ if ctor_type == 0:
+ length = random.randint(0, 1000)
+ return self._Variable(name, "new %sArray(%d)" % (arraytype, length),
+ fallback="new %sArray(8)" % arraytype)
+ elif ctor_type == 1:
+ input_name = name + "_typedarray"
+ result = self._JSTypedArray(input_name, recursion_budget - 1)
+ return (result +
+ self._Variable(name, "new %sArray(%s)" % (arraytype, input_name),
+ fallback="new %sArray(8)" % arraytype))
+ elif ctor_type == 2:
+ arraylike_name = name + "_arraylike"
+ result = self._JSObject(arraylike_name, recursion_budget - 1)
+ length = random.randint(0, 1000)
+ result.append("try { %s.length = %d; } catch(e) {}" %
+ (arraylike_name, length))
+ return (result +
+ self._Variable(name,
+ "new %sArray(%s)" % (arraytype, arraylike_name),
+ fallback="new %sArray(8)" % arraytype))
+ else:
+ die = random.random()
+ buffer_name = name + "_buffer"
+ args = [buffer_name]
+ result = self._JSArrayBuffer(buffer_name, recursion_budget)
+ if die < 0.67:
+ offset_name = name + "_offset"
+ args.append(offset_name)
+ result += self._Int32(offset_name)
+ if die < 0.33:
+ length_name = name + "_length"
+ args.append(length_name)
+ result += self._Int32(length_name)
+ return (result +
+ self._Variable(name,
+ "new %sArray(%s)" % (arraytype, ", ".join(args)),
+ fallback="new %sArray(8)" % arraytype))
+
+ def _JSWeakCollection(self, name, recursion_budget):
+ ctor = random.choice([self._JSMap, self._JSSet])
+ return ctor(name, recursion_budget, weak="Weak")
+
+ def _PropertyDetails(self, name, recursion_budget):
+ # TODO(jkummerow): Be more clever here?
+ return self._Int32(name)
+
+ def _JSObject(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.4:
+ function = random.choice([self._PlainObject, self._PlainArray,
+ self._PlainFunction])
+ elif die < 0.5:
+ return self._Variable(name, "this") # Global object.
+ else:
+ function = random.choice([self._JSArrayBuffer, self._JSDataView,
+ self._JSDate, self._JSFunctionProxy,
+ self._JSGeneratorObject, self._JSMap,
+ self._JSMapIterator, self._JSRegExp,
+ self._JSSet, self._JSSetIterator,
+ self._JSTypedArray, self._JSValue,
+ self._JSWeakCollection])
+ result = function(name, recursion_budget)
+ self._AddAccessors(name, result, recursion_budget)
+ self._AddProperties(name, result, recursion_budget)
+ self._AddElements(name, result, recursion_budget)
+ return result
+
+ def _JSReceiver(self, name, recursion_budget):
+ if random.random() < 0.9: return self._JSObject(name, recursion_budget)
+ return self._JSProxy(name, recursion_budget)
+
+ def _HeapObject(self, name, recursion_budget):
+ die = random.random()
+ if die < 0.9: return self._JSReceiver(name, recursion_budget)
+ elif die < 0.95: return self._Oddball(name, recursion_budget)
+ else: return self._Name(name, recursion_budget)
+
+ def _Object(self, name, recursion_budget):
+ if recursion_budget <= 0:
+ function = random.choice([self._Oddball, self._Number, self._Name,
+ self._JSValue, self._JSRegExp])
+ return function(name, recursion_budget)
+ if random.random() < 0.2:
+ return self._Smi(name, recursion_budget)
+ return self._HeapObject(name, recursion_budget)
+
+ GENERATORS = {
+ "Boolean": ["true", _Boolean],
+ "HeapObject": ["new Object()", _HeapObject],
+ "Int32": ["32", _Int32],
+ "JSArray": ["new Array()", _JSArray],
+ "JSArrayBuffer": ["new ArrayBuffer(8)", _JSArrayBuffer],
+ "JSDataView": ["new DataView(new ArrayBuffer(8))", _JSDataView],
+ "JSDate": ["new Date()", _JSDate],
+ "JSFunction": ["function() {}", _JSFunction],
+ "JSFunctionProxy": ["Proxy.createFunction({}, function() {})",
+ _JSFunctionProxy],
+ "JSGeneratorObject": ["(function*(){ yield 1; })()", _JSGeneratorObject],
+ "JSMap": ["new Map()", _JSMap],
+ "JSMapIterator": ["%MapCreateIterator(new Map(), 3)", _JSMapIterator],
+ "JSObject": ["new Object()", _JSObject],
+ "JSProxy": ["Proxy.create({})", _JSProxy],
+ "JSReceiver": ["new Object()", _JSReceiver],
+ "JSRegExp": ["/ab/g", _JSRegExp],
+ "JSSet": ["new Set()", _JSSet],
+ "JSSetIterator": ["%SetCreateIterator(new Set(), 2)", _JSSetIterator],
+ "JSTypedArray": ["new Int32Array(2)", _JSTypedArray],
+ "JSValue": ["new String('foo')", _JSValue],
+ "JSWeakCollection": ["new WeakMap()", _JSWeakCollection],
+ "Name": ["\"name\"", _Name],
+ "Number": ["1.5", _Number],
+ "Object": ["new Object()", _Object],
+ "PropertyDetails": ["513", _PropertyDetails],
+ "SeqString": ["\"seqstring\"", _SeqString],
+ "Smi": ["1", _Smi],
+ "StrictMode": ["1", _StrictMode],
+ "String": ["\"foo\"", _String],
+ "Symbol": ["Symbol(\"symbol\")", _Symbol],
+ "Uint32": ["32", _Uint32],
+ }
class ArgParser(object):
@@ -254,7 +726,6 @@
double_arg_parser, number_arg_parser, strict_mode_arg_parser,
boolean_arg_parser, property_details_parser]
-
def SetArgsLength(self, match):
self.argslength = int(match.group(1))
@@ -285,6 +756,7 @@
s.append(")")
return "".join(s)
+
# Parses HEADERFILENAME to find out which runtime functions are "inline".
def FindInlineRuntimeFunctions():
inline_functions = []
@@ -391,47 +863,141 @@
if t in NON_JS_TYPES:
decision = cctest_fuzzable_functions
else:
- assert t in JS_TYPE_GENERATORS, \
+ assert Generator.IsTypeSupported(t), \
("type generator not found for %s, function: %s" % (t, f))
decision.append(f)
return (js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions)
-def GenerateJSTestcaseForFunction(f):
+def _GetKnownGoodArgs(function, generator):
+ custom_input = CUSTOM_KNOWN_GOOD_INPUT.get(function.name, None)
+ definitions = []
+ argslist = []
+ for i in range(function.argslength):
+ if custom_input and custom_input[i] is not None:
+ name = "arg%d" % i
+ definitions.append("var %s = %s;" % (name, custom_input[i]))
+ else:
+ arg = function.args[i]
+ name = arg.name
+ definitions += generator.RandomVariable(name, arg.type, simple=True)
+ argslist.append(name)
+ return (definitions, argslist)
+
+
+def _GenerateTestcase(function, definitions, argslist, throws):
s = ["// Copyright 2014 the V8 project authors. All rights reserved.",
"// AUTO-GENERATED BY tools/generate-runtime-tests.py, DO NOT MODIFY",
- "// Flags: --allow-natives-syntax --harmony"]
- call = "%%%s%s(" % (f.inline, f.name)
- custom = CUSTOM_KNOWN_GOOD_INPUT.get(f.name, None)
- for i in range(f.argslength):
- if custom and custom[i] is not None:
- (name, value) = ("arg%d" % i, custom[i])
- else:
- arg = f.args[i]
- (name, value) = (arg.name, JS_TYPE_GENERATORS[arg.type])
- s.append("var %s = %s;" % (name, value))
- if i > 0: call += ", "
- call += name
- call += ");"
- if f.name in THROWS:
+ "// Flags: --allow-natives-syntax --harmony"] + definitions
+ call = "%%%s%s(%s);" % (function.inline, function.name, ", ".join(argslist))
+ if throws:
s.append("try {")
s.append(call);
s.append("} catch(e) {}")
else:
s.append(call)
testcase = "\n".join(s)
- path = os.path.join(BASEPATH, f.Filename())
+ return testcase
+
+
+def GenerateJSTestcaseForFunction(function):
+ gen = Generator()
+ (definitions, argslist) = _GetKnownGoodArgs(function, gen)
+ testcase = _GenerateTestcase(function, definitions, argslist,
+ function.name in THROWS)
+ path = os.path.join(BASEPATH, function.Filename())
with open(path, "w") as f:
f.write("%s\n" % testcase)
+
def GenerateTestcases(functions):
shutil.rmtree(BASEPATH) # Re-generate everything.
os.makedirs(BASEPATH)
for f in functions:
GenerateJSTestcaseForFunction(f)
-def PrintUsage():
- print """Usage: %(this_script)s ACTION
+
+def _SaveFileName(save_path, process_id, save_file_index):
+ return "%s/fuzz_%d_%d.js" % (save_path, process_id, save_file_index)
+
+
+def RunFuzzer(process_id, options, stop_running):
+ base_file_name = "/dev/shm/runtime_fuzz_%d" % process_id
+ test_file_name = "%s.js" % base_file_name
+ stderr_file_name = "%s.out" % base_file_name
+ save_file_index = 0
+ while os.path.exists(_SaveFileName(options.save_path, process_id,
+ save_file_index)):
+ save_file_index += 1
+ MAX_SLEEP_TIME = 0.1
+ INITIAL_SLEEP_TIME = 0.001
+ SLEEP_TIME_FACTOR = 1.5
+
+ functions = FindRuntimeFunctions()
+ (js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
+ ClassifyFunctions(functions)
+
+ try:
+ for i in range(options.num_tests):
+ if stop_running.is_set(): break
+ function = random.choice(js_fuzzable_functions) # TODO: others too
+ if function.argslength == 0: continue
+ args = []
+ definitions = []
+ gen = Generator()
+ for i in range(function.argslength):
+ arg = function.args[i]
+ argname = "arg%d%s" % (i, arg.name)
+ args.append(argname)
+ definitions += gen.RandomVariable(argname, arg.type, simple=False)
+ testcase = _GenerateTestcase(function, definitions, args, True)
+ with open(test_file_name, "w") as f:
+ f.write("%s\n" % testcase)
+ with open("/dev/null", "w") as devnull:
+ with open(stderr_file_name, "w") as stderr:
+ process = subprocess.Popen(
+ [options.binary, "--allow-natives-syntax", "--harmony",
+ "--enable-slow-asserts", test_file_name],
+ stdout=devnull, stderr=stderr)
+ end_time = time.time() + options.timeout
+ timed_out = False
+ exit_code = None
+ sleep_time = INITIAL_SLEEP_TIME
+ while exit_code is None:
+ if time.time() >= end_time:
+ # Kill the process and wait for it to exit.
+ os.kill(process.pid, signal.SIGTERM)
+ exit_code = process.wait()
+ timed_out = True
+ else:
+ exit_code = process.poll()
+ time.sleep(sleep_time)
+ sleep_time = sleep_time * SLEEP_TIME_FACTOR
+ if sleep_time > MAX_SLEEP_TIME:
+ sleep_time = MAX_SLEEP_TIME
+ if exit_code != 0 and not timed_out:
+ oom = False
+ with open(stderr_file_name, "r") as stderr:
+ for line in stderr:
+ if line.strip() == "# Allocation failed - process out of memory":
+ oom = True
+ break
+ if oom: continue
+ save_name = _SaveFileName(options.save_path, process_id,
+ save_file_index)
+ shutil.copyfile(test_file_name, save_name)
+ save_file_index += 1
+ except KeyboardInterrupt:
+ stop_running.set()
+ except Exception, e:
+ print e
+ finally:
+ os.remove(test_file_name)
+ os.remove(stderr_file_name)
+
+
+def BuildOptionParser():
+ usage = """Usage: %%prog [options] ACTION
where ACTION can be:
@@ -441,21 +1007,47 @@
generate Parse source code for runtime functions, and auto-generate
test cases for them. Warning: this will nuke and re-create
%(path)s.
-""" % {"path": os.path.relpath(BASEPATH), "this_script": THIS_SCRIPT}
+fuzz Generate fuzz tests, run them, save those that crashed (see options).
+""" % {"path": os.path.relpath(BASEPATH)}
-if __name__ == "__main__":
- if len(sys.argv) != 2:
- PrintUsage()
- sys.exit(1)
- action = sys.argv[1]
- if action in ["-h", "--help", "help"]:
- PrintUsage()
- sys.exit(0)
+ o = optparse.OptionParser(usage=usage)
+ o.add_option("--binary", default="out/x64.debug/d8",
+ help="d8 binary used for running fuzz tests (default: %default)")
+ o.add_option("-n", "--num-tests", default=1000, type="int",
+ help="Number of fuzz tests to generate per worker process"
+ " (default: %default)")
+ o.add_option("--save-path", default="~/runtime_fuzz_output",
+ help="Path to directory where failing tests will be stored"
+ " (default: %default)")
+ o.add_option("--timeout", default=20, type="int",
+ help="Timeout for each fuzz test (in seconds, default:"
+ "%default)")
+ return o
+
+
+def Main():
+ parser = BuildOptionParser()
+ (options, args) = parser.parse_args()
+ options.save_path = os.path.expanduser(options.save_path)
+
+ if len(args) != 1 or args[0] == "help":
+ parser.print_help()
+ return 1
+ action = args[0]
functions = FindRuntimeFunctions()
(js_fuzzable_functions, cctest_fuzzable_functions, unknown_functions) = \
ClassifyFunctions(functions)
+ if action == "test":
+ gen = Generator()
+ vartype = "JSTypedArray"
+ print("simple: %s" % gen.RandomVariable("x", vartype, True))
+ for i in range(10):
+ print("----")
+ print("%s" % "\n".join(gen.RandomVariable("x", vartype, False)))
+ return 0
+
if action == "info":
print("%d functions total; js_fuzzable_functions: %d, "
"cctest_fuzzable_functions: %d, unknown_functions: %d"
@@ -464,49 +1056,76 @@
print("unknown functions:")
for f in unknown_functions:
print(f)
- sys.exit(0)
+ return 0
if action == "check":
- error = False
+ errors = 0
+
def CheckCount(actual, expected, description):
- global error
if len(actual) != expected:
print("Expected to detect %d %s, but found %d." % (
expected, description, len(actual)))
print("If this change is intentional, please update the expectations"
" at the top of %s." % THIS_SCRIPT)
- error = True
- CheckCount(functions, EXPECTED_FUNCTION_COUNT, "functions in total")
- CheckCount(js_fuzzable_functions, EXPECTED_FUZZABLE_COUNT,
- "JavaScript-fuzzable functions")
- CheckCount(cctest_fuzzable_functions, EXPECTED_CCTEST_COUNT,
- "cctest-fuzzable functions")
- CheckCount(unknown_functions, EXPECTED_UNKNOWN_COUNT,
- "functions with incomplete type information")
+ return 1
+ return 0
+
+ errors += CheckCount(functions, EXPECTED_FUNCTION_COUNT,
+ "functions in total")
+ errors += CheckCount(js_fuzzable_functions, EXPECTED_FUZZABLE_COUNT,
+ "JavaScript-fuzzable functions")
+ errors += CheckCount(cctest_fuzzable_functions, EXPECTED_CCTEST_COUNT,
+ "cctest-fuzzable functions")
+ errors += CheckCount(unknown_functions, EXPECTED_UNKNOWN_COUNT,
+ "functions with incomplete type information")
def CheckTestcasesExisting(functions):
- global error
+ errors = 0
for f in functions:
if not os.path.isfile(os.path.join(BASEPATH, f.Filename())):
print("Missing testcase for %s, please run '%s generate'" %
(f.name, THIS_SCRIPT))
- error = True
+ errors += 1
files = filter(lambda filename: not filename.startswith("."),
os.listdir(BASEPATH))
if (len(files) != len(functions)):
unexpected_files = set(files) - set([f.Filename() for f in functions])
for f in unexpected_files:
print("Unexpected testcase: %s" % os.path.join(BASEPATH, f))
- error = True
+ errors += 1
print("Run '%s generate' to automatically clean these up."
% THIS_SCRIPT)
- CheckTestcasesExisting(js_fuzzable_functions)
+ return errors
- if error:
- sys.exit(1)
+ errors += CheckTestcasesExisting(js_fuzzable_functions)
+
+ if errors > 0:
+ return 1
print("Generated runtime tests: all good.")
- sys.exit(0)
+ return 0
if action == "generate":
GenerateTestcases(js_fuzzable_functions)
- sys.exit(0)
+ return 0
+
+ if action == "fuzz":
+ processes = []
+ if not os.path.isdir(options.save_path):
+ os.makedirs(options.save_path)
+ stop_running = multiprocessing.Event()
+ for i in range(multiprocessing.cpu_count()):
+ args = (i, options, stop_running)
+ p = multiprocessing.Process(target=RunFuzzer, args=args)
+ p.start()
+ processes.append(p)
+ try:
+ for i in range(len(processes)):
+ processes[i].join()
+ except KeyboardInterrupt:
+ stop_running.set()
+ for i in range(len(processes)):
+ processes[i].join()
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(Main())
diff --git a/tools/gyp/v8.gyp b/tools/gyp/v8.gyp
index e6a5bd1..1d4f9ff 100644
--- a/tools/gyp/v8.gyp
+++ b/tools/gyp/v8.gyp
@@ -313,8 +313,6 @@
'../../src/dateparser-inl.h',
'../../src/dateparser.cc',
'../../src/dateparser.h',
- '../../src/debug-agent.cc',
- '../../src/debug-agent.h',
'../../src/debug.cc',
'../../src/debug.h',
'../../src/deoptimizer.cc',
@@ -502,8 +500,6 @@
'../../src/platform/mutex.h',
'../../src/platform/semaphore.cc',
'../../src/platform/semaphore.h',
- '../../src/platform/socket.cc',
- '../../src/platform/socket.h',
'../../src/preparse-data-format.h',
'../../src/preparse-data.cc',
'../../src/preparse-data.h',
@@ -869,7 +865,7 @@
}],
['_toolset=="target"', {
'libraries': [
- '-lbacktrace', '-lsocket'
+ '-lbacktrace'
],
}],
],
@@ -932,7 +928,7 @@
['OS=="solaris"', {
'link_settings': {
'libraries': [
- '-lsocket -lnsl',
+ '-lnsl',
]},
'sources': [
'../../src/platform-solaris.cc',
diff --git a/tools/run-tests.py b/tools/run-tests.py
index 346926c..6b07574 100755
--- a/tools/run-tests.py
+++ b/tools/run-tests.py
@@ -463,44 +463,39 @@
return 0
# Run the tests, either locally or distributed on the network.
- try:
- start_time = time.time()
- progress_indicator = progress.PROGRESS_INDICATORS[options.progress]()
- if options.junitout:
- progress_indicator = progress.JUnitTestProgressIndicator(
- progress_indicator, options.junitout, options.junittestsuite)
+ start_time = time.time()
+ progress_indicator = progress.PROGRESS_INDICATORS[options.progress]()
+ if options.junitout:
+ progress_indicator = progress.JUnitTestProgressIndicator(
+ progress_indicator, options.junitout, options.junittestsuite)
- run_networked = not options.no_network
- if not run_networked:
- print("Network distribution disabled, running tests locally.")
- elif utils.GuessOS() != "linux":
- print("Network distribution is only supported on Linux, sorry!")
+ run_networked = not options.no_network
+ if not run_networked:
+ print("Network distribution disabled, running tests locally.")
+ elif utils.GuessOS() != "linux":
+ print("Network distribution is only supported on Linux, sorry!")
+ run_networked = False
+ peers = []
+ if run_networked:
+ peers = network_execution.GetPeers()
+ if not peers:
+ print("No connection to distribution server; running tests locally.")
run_networked = False
- peers = []
- if run_networked:
- peers = network_execution.GetPeers()
- if not peers:
- print("No connection to distribution server; running tests locally.")
- run_networked = False
- elif len(peers) == 1:
- print("No other peers on the network; running tests locally.")
- run_networked = False
- elif num_tests <= 100:
- print("Less than 100 tests, running them locally.")
- run_networked = False
+ elif len(peers) == 1:
+ print("No other peers on the network; running tests locally.")
+ run_networked = False
+ elif num_tests <= 100:
+ print("Less than 100 tests, running them locally.")
+ run_networked = False
- if run_networked:
- runner = network_execution.NetworkedRunner(suites, progress_indicator,
- ctx, peers, workspace)
- else:
- runner = execution.Runner(suites, progress_indicator, ctx)
+ if run_networked:
+ runner = network_execution.NetworkedRunner(suites, progress_indicator,
+ ctx, peers, workspace)
+ else:
+ runner = execution.Runner(suites, progress_indicator, ctx)
- exit_code = runner.Run(options.j)
- if runner.terminate:
- return exit_code
- overall_duration = time.time() - start_time
- except KeyboardInterrupt:
- raise
+ exit_code = runner.Run(options.j)
+ overall_duration = time.time() - start_time
if options.time:
verbose.PrintTestDurations(suites, overall_duration)
diff --git a/tools/testrunner/local/commands.py b/tools/testrunner/local/commands.py
index 4f3dc51..d6445d0 100644
--- a/tools/testrunner/local/commands.py
+++ b/tools/testrunner/local/commands.py
@@ -64,49 +64,46 @@
def RunProcess(verbose, timeout, args, **rest):
- try:
- if verbose: print "#", " ".join(args)
- popen_args = args
- prev_error_mode = SEM_INVALID_VALUE
- if utils.IsWindows():
- popen_args = subprocess.list2cmdline(args)
- # Try to change the error mode to avoid dialogs on fatal errors. Don't
- # touch any existing error mode flags by merging the existing error mode.
- # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
- error_mode = SEM_NOGPFAULTERRORBOX
- prev_error_mode = Win32SetErrorMode(error_mode)
- Win32SetErrorMode(error_mode | prev_error_mode)
- process = subprocess.Popen(
- shell=utils.IsWindows(),
- args=popen_args,
- **rest
- )
- if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE):
- Win32SetErrorMode(prev_error_mode)
- # Compute the end time - if the process crosses this limit we
- # consider it timed out.
- if timeout is None: end_time = None
- else: end_time = time.time() + timeout
- timed_out = False
- # Repeatedly check the exit code from the process in a
- # loop and keep track of whether or not it times out.
- exit_code = None
- sleep_time = INITIAL_SLEEP_TIME
- while exit_code is None:
- if (not end_time is None) and (time.time() >= end_time):
- # Kill the process and wait for it to exit.
- KillProcessWithID(process.pid)
- exit_code = process.wait()
- timed_out = True
- else:
- exit_code = process.poll()
- time.sleep(sleep_time)
- sleep_time = sleep_time * SLEEP_TIME_FACTOR
- if sleep_time > MAX_SLEEP_TIME:
- sleep_time = MAX_SLEEP_TIME
- return (exit_code, timed_out)
- except KeyboardInterrupt:
- raise
+ if verbose: print "#", " ".join(args)
+ popen_args = args
+ prev_error_mode = SEM_INVALID_VALUE
+ if utils.IsWindows():
+ popen_args = subprocess.list2cmdline(args)
+ # Try to change the error mode to avoid dialogs on fatal errors. Don't
+ # touch any existing error mode flags by merging the existing error mode.
+ # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx.
+ error_mode = SEM_NOGPFAULTERRORBOX
+ prev_error_mode = Win32SetErrorMode(error_mode)
+ Win32SetErrorMode(error_mode | prev_error_mode)
+ process = subprocess.Popen(
+ shell=utils.IsWindows(),
+ args=popen_args,
+ **rest
+ )
+ if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE):
+ Win32SetErrorMode(prev_error_mode)
+ # Compute the end time - if the process crosses this limit we
+ # consider it timed out.
+ if timeout is None: end_time = None
+ else: end_time = time.time() + timeout
+ timed_out = False
+ # Repeatedly check the exit code from the process in a
+ # loop and keep track of whether or not it times out.
+ exit_code = None
+ sleep_time = INITIAL_SLEEP_TIME
+ while exit_code is None:
+ if (not end_time is None) and (time.time() >= end_time):
+ # Kill the process and wait for it to exit.
+ KillProcessWithID(process.pid)
+ exit_code = process.wait()
+ timed_out = True
+ else:
+ exit_code = process.poll()
+ time.sleep(sleep_time)
+ sleep_time = sleep_time * SLEEP_TIME_FACTOR
+ if sleep_time > MAX_SLEEP_TIME:
+ sleep_time = MAX_SLEEP_TIME
+ return (exit_code, timed_out)
def PrintError(string):
@@ -142,11 +139,9 @@
stdout=fd_out,
stderr=fd_err
)
- except KeyboardInterrupt:
- raise
- except:
- raise
finally:
+ # TODO(machenbach): A keyboard interrupt before the assignment to
+ # fd_out|err can lead to reference errors here.
os.close(fd_out)
os.close(fd_err)
out = file(outname).read()
diff --git a/tools/testrunner/local/execution.py b/tools/testrunner/local/execution.py
index f4a4020..80d881b 100644
--- a/tools/testrunner/local/execution.py
+++ b/tools/testrunner/local/execution.py
@@ -26,19 +26,14 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-import multiprocessing
import os
-import threading
import time
+from pool import Pool
from . import commands
from . import utils
-BREAK_NOW = -1
-EXCEPTION = -2
-
-
class Job(object):
def __init__(self, command, dep_command, test_id, timeout, verbose):
self.command = command
@@ -49,24 +44,17 @@
def RunTest(job):
- try:
- start_time = time.time()
- if job.dep_command is not None:
- dep_output = commands.Execute(job.dep_command, job.verbose, job.timeout)
- # TODO(jkummerow): We approximate the test suite specific function
- # IsFailureOutput() by just checking the exit code here. Currently
- # only cctests define dependencies, for which this simplification is
- # correct.
- if dep_output.exit_code != 0:
- return (job.id, dep_output, time.time() - start_time)
- output = commands.Execute(job.command, job.verbose, job.timeout)
- return (job.id, output, time.time() - start_time)
- except KeyboardInterrupt:
- return (-1, BREAK_NOW, 0)
- except Exception, e:
- print(">>> EXCEPTION: %s" % e)
- return (-1, EXCEPTION, 0)
-
+ start_time = time.time()
+ if job.dep_command is not None:
+ dep_output = commands.Execute(job.dep_command, job.verbose, job.timeout)
+ # TODO(jkummerow): We approximate the test suite specific function
+ # IsFailureOutput() by just checking the exit code here. Currently
+ # only cctests define dependencies, for which this simplification is
+ # correct.
+ if dep_output.exit_code != 0:
+ return (job.id, dep_output, time.time() - start_time)
+ output = commands.Execute(job.command, job.verbose, job.timeout)
+ return (job.id, output, time.time() - start_time)
class Runner(object):
@@ -83,8 +71,6 @@
self.remaining = num_tests
self.failed = []
self.crashed = 0
- self.terminate = False
- self.lock = threading.Lock()
def Run(self, jobs):
self.indicator.Starting()
@@ -95,8 +81,11 @@
return 0
def _RunInternal(self, jobs):
- pool = multiprocessing.Pool(processes=jobs)
+ pool = Pool(jobs)
test_map = {}
+ # TODO(machenbach): Instead of filling the queue completely before
+ # pool.imap_unordered, make this a generator that already starts testing
+ # while the queue is filled.
queue = []
queued_exception = None
for test in self.tests:
@@ -119,22 +108,11 @@
else:
dep_command = None
job = Job(command, dep_command, test.id, timeout, self.context.verbose)
- queue.append(job)
+ queue.append([job])
try:
- kChunkSize = 1
- it = pool.imap_unordered(RunTest, queue, kChunkSize)
+ it = pool.imap_unordered(RunTest, queue)
for result in it:
- test_id = result[0]
- if test_id < 0:
- if result[1] == BREAK_NOW:
- self.terminate = True
- else:
- continue
- if self.terminate:
- pool.terminate()
- pool.join()
- raise BreakNowException("User pressed Ctrl+C or IO went wrong")
- test = test_map[test_id]
+ test = test_map[result[0]]
self.indicator.AboutToRun(test)
test.output = result[1]
test.duration = result[2]
@@ -147,18 +125,10 @@
self.succeeded += 1
self.remaining -= 1
self.indicator.HasRun(test, has_unexpected_output)
- except KeyboardInterrupt:
+ finally:
pool.terminate()
- pool.join()
- raise
- except Exception, e:
- print("Exception: %s" % e)
- pool.terminate()
- pool.join()
- raise
if queued_exception:
raise queued_exception
- return
def GetCommand(self, test):
diff --git a/tools/testrunner/local/pool.py b/tools/testrunner/local/pool.py
new file mode 100644
index 0000000..8f629f9
--- /dev/null
+++ b/tools/testrunner/local/pool.py
@@ -0,0 +1,136 @@
+#!/usr/bin/env python
+# 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.
+
+from multiprocessing import Event, Process, Queue
+
+class NormalResult():
+ def __init__(self, result):
+ self.result = result
+ self.exception = False
+ self.break_now = False
+
+
+class ExceptionResult():
+ def __init__(self):
+ self.exception = True
+ self.break_now = False
+
+
+class BreakResult():
+ def __init__(self):
+ self.exception = False
+ self.break_now = True
+
+
+def Worker(fn, work_queue, done_queue, done):
+ """Worker to be run in a child process.
+ The worker stops on two conditions. 1. When the poison pill "STOP" is
+ reached or 2. when the event "done" is set."""
+ try:
+ for args in iter(work_queue.get, "STOP"):
+ if done.is_set():
+ break
+ try:
+ done_queue.put(NormalResult(fn(*args)))
+ except Exception, e:
+ print(">>> EXCEPTION: %s" % e)
+ done_queue.put(ExceptionResult())
+ except KeyboardInterrupt:
+ done_queue.put(BreakResult())
+
+
+class Pool():
+ """Distributes tasks to a number of worker processes.
+ New tasks can be added dynamically even after the workers have been started.
+ Requirement: Tasks can only be added from the parent process, e.g. while
+ consuming the results generator."""
+
+ # Factor to calculate the maximum number of items in the work/done queue.
+ # Necessary to not overflow the queue's pipe if a keyboard interrupt happens.
+ BUFFER_FACTOR = 4
+
+ def __init__(self, num_workers):
+ self.num_workers = num_workers
+ self.processes = []
+ self.terminated = False
+
+ # Invariant: count >= #work_queue + #done_queue. It is greater when a
+ # worker takes an item from the work_queue and before the result is
+ # submitted to the done_queue. It is equal when no worker is working,
+ # e.g. when all workers have finished, and when no results are processed.
+ # Count is only accessed by the parent process. Only the parent process is
+ # allowed to remove items from the done_queue and to add items to the
+ # work_queue.
+ self.count = 0
+ self.work_queue = Queue()
+ self.done_queue = Queue()
+ self.done = Event()
+
+ def imap_unordered(self, fn, gen):
+ """Maps function "fn" to items in generator "gen" on the worker processes
+ in an arbitrary order. The items are expected to be lists of arguments to
+ the function. Returns a results iterator."""
+ try:
+ gen = iter(gen)
+ self.advance = self._advance_more
+
+ for w in xrange(self.num_workers):
+ p = Process(target=Worker, args=(fn,
+ self.work_queue,
+ self.done_queue,
+ self.done))
+ self.processes.append(p)
+ p.start()
+
+ self.advance(gen)
+ while self.count > 0:
+ result = self.done_queue.get()
+ self.count -= 1
+ if result.exception:
+ # Ignore items with unexpected exceptions.
+ continue
+ elif result.break_now:
+ # A keyboard interrupt happened in one of the worker processes.
+ raise KeyboardInterrupt
+ else:
+ yield result.result
+ self.advance(gen)
+ finally:
+ self.terminate()
+
+ def _advance_more(self, gen):
+ while self.count < self.num_workers * self.BUFFER_FACTOR:
+ try:
+ self.work_queue.put(gen.next())
+ self.count += 1
+ except StopIteration:
+ self.advance = self._advance_empty
+ break
+
+ def _advance_empty(self, gen):
+ pass
+
+ def add(self, args):
+ """Adds an item to the work queue. Can be called dynamically while
+ processing the results from imap_unordered."""
+ self.work_queue.put(args)
+ self.count += 1
+
+ def terminate(self):
+ if self.terminated:
+ return
+ self.terminated = True
+
+ # For exceptional tear down set the "done" event to stop the workers before
+ # they empty the queue buffer.
+ self.done.set()
+
+ for p in self.processes:
+ # During normal tear down the workers block on get(). Feed a poison pill
+ # per worker to make them stop.
+ self.work_queue.put("STOP")
+
+ for p in self.processes:
+ p.join()
diff --git a/tools/testrunner/local/pool_unittest.py b/tools/testrunner/local/pool_unittest.py
new file mode 100644
index 0000000..bf2b3f8
--- /dev/null
+++ b/tools/testrunner/local/pool_unittest.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+# 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.
+
+import unittest
+
+from pool import Pool
+
+def Run(x):
+ if x == 10:
+ raise Exception("Expected exception triggered by test.")
+ return x
+
+class PoolTest(unittest.TestCase):
+ def testNormal(self):
+ results = set()
+ pool = Pool(3)
+ for result in pool.imap_unordered(Run, [[x] for x in range(0, 10)]):
+ results.add(result)
+ self.assertEquals(set(range(0, 10)), results)
+
+ def testException(self):
+ results = set()
+ pool = Pool(3)
+ for result in pool.imap_unordered(Run, [[x] for x in range(0, 12)]):
+ # Item 10 will not appear in results due to an internal exception.
+ results.add(result)
+ expect = set(range(0, 12))
+ expect.remove(10)
+ self.assertEquals(expect, results)
+
+ def testAdd(self):
+ results = set()
+ pool = Pool(3)
+ for result in pool.imap_unordered(Run, [[x] for x in range(0, 10)]):
+ results.add(result)
+ if result < 30:
+ pool.add([result + 20])
+ self.assertEquals(set(range(0, 10) + range(20, 30) + range(40, 50)),
+ results)