Commit 662dd448 authored by jochen@chromium.org's avatar jochen@chromium.org

Remove preemption thread and API

BUG=v8:3004
R=svenpanne@chromium.org, yangguo@chromium.org
LOG=y

Review URL: https://codereview.chromium.org/62283010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17967 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2340aa41
......@@ -5271,12 +5271,6 @@ class V8_EXPORT Locker {
~Locker();
V8_DEPRECATED("This will be remvoed.",
static void StartPreemption(Isolate *isolate, int every_n_ms));
V8_DEPRECATED("This will be removed",
static void StopPreemption(Isolate* isolate));
/**
* Returns whether or not the locker for a given isolate, is locked by the
* current thread.
......
......@@ -1379,43 +1379,6 @@ bool Shell::SetOptions(int argc, char* argv[]) {
} else if (strcmp(argv[i], "--send-idle-notification") == 0) {
options.send_idle_notification = true;
argv[i] = NULL;
} else if (strcmp(argv[i], "--preemption") == 0) {
#ifdef V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#else
options.use_preemption = true;
argv[i] = NULL;
#endif // V8_SHARED
} else if (strcmp(argv[i], "--nopreemption") == 0) {
#ifdef V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#else
options.use_preemption = false;
argv[i] = NULL;
#endif // V8_SHARED
} else if (strcmp(argv[i], "--preemption-interval") == 0) {
#ifdef V8_SHARED
printf("D8 with shared library does not support multi-threading\n");
return false;
#else
if (++i < argc) {
argv[i-1] = NULL;
char* end = NULL;
options.preemption_interval = strtol(argv[i], &end, 10); // NOLINT
if (options.preemption_interval <= 0
|| *end != '\0'
|| errno == ERANGE) {
printf("Invalid value for --preemption-interval '%s'\n", argv[i]);
return false;
}
argv[i] = NULL;
} else {
printf("Missing value for --preemption-interval\n");
return false;
}
#endif // V8_SHARED
} else if (strcmp(argv[i], "-f") == 0) {
// Ignore any -f flags for compatibility with other stand-alone
// JavaScript engines.
......@@ -1554,14 +1517,6 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) {
V8::IdleNotification(kLongIdlePauseInMs);
}
}
#ifndef V8_SHARED
// Start preemption if threads have been created and preemption is enabled.
if (threads.length() > 0
&& options.use_preemption) {
Locker::StartPreemption(isolate, options.preemption_interval);
}
#endif // V8_SHARED
}
#ifndef V8_SHARED
......@@ -1574,11 +1529,6 @@ int Shell::RunMain(Isolate* isolate, int argc, char* argv[]) {
thread->Join();
delete thread;
}
if (threads.length() > 0 && options.use_preemption) {
Locker lock(isolate);
Locker::StopPreemption(isolate);
}
#endif // V8_SHARED
return 0;
}
......
......@@ -219,8 +219,6 @@ class ShellOptions {
public:
ShellOptions() :
#ifndef V8_SHARED
use_preemption(true),
preemption_interval(10),
num_parallel_files(0),
parallel_files(NULL),
#endif // V8_SHARED
......@@ -245,8 +243,6 @@ class ShellOptions {
}
#ifndef V8_SHARED
bool use_preemption;
int preemption_interval;
int num_parallel_files;
char** parallel_files;
#endif // V8_SHARED
......
......@@ -814,8 +814,6 @@ static Object* RuntimePreempt(Isolate* isolate) {
// Clear the preempt request flag.
isolate->stack_guard()->Continue(PREEMPT);
ContextSwitcher::PreemptionReceived();
#ifdef ENABLE_DEBUGGER_SUPPORT
if (isolate->debug()->InDebugger()) {
// If currently in the debugger don't do any actual preemption but record
......
......@@ -611,10 +611,6 @@ DEFINE_int(hash_seed, 0,
DEFINE_bool(profile_deserialization, false,
"Print the time it takes to deserialize the snapshot.")
// v8.cc
DEFINE_bool(preemption, false,
"activate a 100ms timer that switches between V8 threads")
// Regexp
DEFINE_bool(regexp_optimization, true, "generate optimized regexp code")
......
......@@ -1549,7 +1549,6 @@ Isolate::Isolate()
write_iterator_(NULL),
global_handles_(NULL),
eternal_handles_(NULL),
context_switcher_(NULL),
thread_manager_(NULL),
fp_stubs_generated_(false),
has_installed_extensions_(false),
......@@ -1690,10 +1689,6 @@ void Isolate::Deinit() {
delete deoptimizer_data_;
deoptimizer_data_ = NULL;
if (FLAG_preemption) {
v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
v8::Locker::StopPreemption(reinterpret_cast<v8::Isolate*>(this));
}
builtins_.TearDown();
bootstrapper_->TearDown();
......@@ -1805,8 +1800,6 @@ Isolate::~Isolate() {
delete write_iterator_;
write_iterator_ = NULL;
delete context_switcher_;
context_switcher_ = NULL;
delete thread_manager_;
thread_manager_ = NULL;
......@@ -2038,11 +2031,6 @@ bool Isolate::Init(Deserializer* des) {
}
}
if (FLAG_preemption) {
v8::Locker locker(reinterpret_cast<v8::Isolate*>(this));
v8::Locker::StartPreemption(reinterpret_cast<v8::Isolate*>(this), 100);
}
#ifdef ENABLE_DEBUGGER_SUPPORT
debug_->SetUp(create_heap_objects);
#endif
......
......@@ -58,7 +58,6 @@ struct CodeStubInterfaceDescriptor;
class CodeTracer;
class CompilationCache;
class ContextSlotCache;
class ContextSwitcher;
class Counters;
class CpuFeatures;
class CpuProfiler;
......@@ -919,12 +918,6 @@ class Isolate {
ThreadManager* thread_manager() { return thread_manager_; }
ContextSwitcher* context_switcher() { return context_switcher_; }
void set_context_switcher(ContextSwitcher* switcher) {
context_switcher_ = switcher;
}
StringTracker* string_tracker() { return string_tracker_; }
unibrow::Mapping<unibrow::Ecma262UnCanonicalize>* jsregexp_uncanonicalize() {
......@@ -1293,7 +1286,6 @@ class Isolate {
ConsStringIteratorOp* write_iterator_;
GlobalHandles* global_handles_;
EternalHandles* eternal_handles_;
ContextSwitcher* context_switcher_;
ThreadManager* thread_manager_;
RuntimeState runtime_state_;
bool fp_stubs_generated_;
......
......@@ -133,18 +133,6 @@ Unlocker::~Unlocker() {
}
void Locker::StartPreemption(v8::Isolate* isolate, int every_n_ms) {
v8::internal::ContextSwitcher::StartPreemption(
reinterpret_cast<i::Isolate*>(isolate), every_n_ms);
}
void Locker::StopPreemption(v8::Isolate* isolate) {
v8::internal::ContextSwitcher::StopPreemption(
reinterpret_cast<i::Isolate*>(isolate));
}
namespace internal {
......@@ -419,63 +407,5 @@ void ThreadManager::TerminateExecution(ThreadId thread_id) {
}
ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
: Thread("v8:CtxtSwitcher"),
keep_going_(true),
sleep_ms_(every_n_ms),
isolate_(isolate) {
}
// Set the scheduling interval of V8 threads. This function starts the
// ContextSwitcher thread if needed.
void ContextSwitcher::StartPreemption(Isolate* isolate, int every_n_ms) {
ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
if (isolate->context_switcher() == NULL) {
// If the ContextSwitcher thread is not running at the moment start it now.
isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
isolate->context_switcher()->Start();
} else {
// ContextSwitcher thread is already running, so we just change the
// scheduling interval.
isolate->context_switcher()->sleep_ms_ = every_n_ms;
}
}
// Disable preemption of V8 threads. If multiple threads want to use V8 they
// must cooperatively schedule amongst them from this point on.
void ContextSwitcher::StopPreemption(Isolate* isolate) {
ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
if (isolate->context_switcher() != NULL) {
// The ContextSwitcher thread is running. We need to stop it and release
// its resources.
isolate->context_switcher()->keep_going_ = false;
// Wait for the ContextSwitcher thread to exit.
isolate->context_switcher()->Join();
// Thread has exited, now we can delete it.
delete(isolate->context_switcher());
isolate->set_context_switcher(NULL);
}
}
// Main loop of the ContextSwitcher thread: Preempt the currently running V8
// thread at regular intervals.
void ContextSwitcher::Run() {
while (keep_going_) {
OS::Sleep(sleep_ms_);
isolate()->stack_guard()->Preempt();
}
}
// Acknowledge the preemption by the receiving thread.
void ContextSwitcher::PreemptionReceived() {
// There is currently no accounting being done for this. But could be in the
// future, which is why we leave this in.
}
} // namespace internal
} // namespace v8
......@@ -139,34 +139,6 @@ class ThreadManager {
};
// The ContextSwitcher thread is used to schedule regular preemptions to
// multiple running V8 threads. Generally it is necessary to call
// StartPreemption if there is more than one thread running. If not, a single
// JavaScript can take full control of V8 and not allow other threads to run.
class ContextSwitcher: public Thread {
public:
// Set the preemption interval for the ContextSwitcher thread.
static void StartPreemption(Isolate* isolate, int every_n_ms);
// Stop sending preemption requests to threads.
static void StopPreemption(Isolate* isolate);
// Preempted thread needs to call back to the ContextSwitcher to acknowledge
// the handling of a preemption request.
static void PreemptionReceived();
private:
ContextSwitcher(Isolate* isolate, int every_n_ms);
Isolate* isolate() const { return isolate_; }
void Run();
bool keep_going_;
int sleep_ms_;
Isolate* isolate_;
};
} } // namespace v8::internal
#endif // V8_V8THREADS_H_
......@@ -14478,116 +14478,6 @@ THREADED_TEST(CrossContextNew) {
}
class ApplyInterruptTest {
public:
ApplyInterruptTest() : block_(0) {}
~ApplyInterruptTest() {}
void RunTest() {
gc_count_ = 0;
gc_during_apply_ = 0;
apply_success_ = false;
gc_success_ = false;
GCThread gc_thread(this);
gc_thread.Start();
v8::Isolate* isolate = CcTest::isolate();
v8::Locker::StartPreemption(isolate, 1);
LongRunningApply();
{
v8::Unlocker unlock(isolate);
gc_thread.Join();
}
v8::Locker::StopPreemption(isolate);
CHECK(apply_success_);
CHECK(gc_success_);
}
private:
// Number of garbage collections required.
static const int kRequiredGCs = 2;
class GCThread : public i::Thread {
public:
explicit GCThread(ApplyInterruptTest* test)
: Thread("GCThread"), test_(test) {}
virtual void Run() {
test_->CollectGarbage();
}
private:
ApplyInterruptTest* test_;
};
void CollectGarbage() {
block_.Wait();
while (gc_during_apply_ < kRequiredGCs) {
{
v8::Locker lock(CcTest::isolate());
v8::Isolate::Scope isolate_scope(CcTest::isolate());
CcTest::heap()->CollectAllGarbage(i::Heap::kNoGCFlags);
gc_count_++;
}
i::OS::Sleep(1);
}
gc_success_ = true;
}
void LongRunningApply() {
block_.Signal();
int rounds = 0;
while (gc_during_apply_ < kRequiredGCs) {
int gc_before = gc_count_;
{
const char* c_source =
"function do_very_little(bar) {"
" this.foo = bar;"
"}"
"for (var i = 0; i < 100000; i++) {"
" do_very_little.apply(this, ['bar']);"
"}";
Local<String> source = String::New(c_source);
Local<Script> script = Script::Compile(source);
Local<Value> result = script->Run();
// Check that no exception was thrown.
CHECK(!result.IsEmpty());
}
int gc_after = gc_count_;
gc_during_apply_ += gc_after - gc_before;
rounds++;
}
apply_success_ = true;
}
i::Semaphore block_;
int gc_count_;
int gc_during_apply_;
bool apply_success_;
bool gc_success_;
};
// Test that nothing bad happens if we get a preemption just when we were
// about to do an apply().
TEST(ApplyInterruption) {
v8::Locker lock(CcTest::isolate());
v8::V8::Initialize();
v8::HandleScope scope(CcTest::isolate());
Local<Context> local_env;
{
LocalContext env;
local_env = env.local();
}
// Local context should still be live.
CHECK(!local_env.IsEmpty());
local_env->Enter();
// Should complete without problems.
ApplyInterruptTest().RunTest();
local_env->Exit();
}
// Verify that we can clone an object
TEST(ObjectClone) {
LocalContext env;
......
......@@ -33,28 +33,6 @@
#include "cctest.h"
TEST(Preemption) {
v8::Isolate* isolate = CcTest::isolate();
v8::Locker locker(isolate);
v8::V8::Initialize();
v8::HandleScope scope(isolate);
v8::Handle<v8::Context> context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
v8::Locker::StartPreemption(isolate, 100);
v8::Handle<v8::Script> script = v8::Script::Compile(
v8::String::New("var count = 0; var obj = new Object(); count++;\n"));
script->Run();
v8::Locker::StopPreemption(isolate);
v8::internal::OS::Sleep(500); // Make sure the timer fires.
script->Run();
}
enum Turn {
FILL_CACHE,
CLEAN_CACHE,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment