Index: src/d8.cc |
diff --git a/src/d8.cc b/src/d8.cc |
index 5f57350093943821ac9157cb8cf2bca452ecc236..08735142bc53c06ac69bff4d2d67fae3ec2570b7 100644 |
--- a/src/d8.cc |
+++ b/src/d8.cc |
@@ -26,33 +26,49 @@ |
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
+#ifdef V8_SHARED |
+#define USING_V8_SHARED |
+#endif |
+ |
#ifdef COMPRESS_STARTUP_DATA_BZ2 |
#include <bzlib.h> |
#endif |
+ |
#include <errno.h> |
#include <stdlib.h> |
+#include <string.h> |
-#include "v8.h" |
+#ifdef USING_V8_SHARED |
+#include <assert.h> |
+#include "../include/v8-testing.h" |
+#endif // USING_V8_SHARED |
#include "d8.h" |
+ |
+#ifndef USING_V8_SHARED |
+#include "api.h" |
+#include "checks.h" |
#include "d8-debug.h" |
#include "debug.h" |
-#include "api.h" |
#include "natives.h" |
#include "platform.h" |
+#include "v8.h" |
+#endif // USING_V8_SHARED |
#if !defined(_WIN32) && !defined(_WIN64) |
#include <unistd.h> // NOLINT |
#endif |
-namespace v8 { |
- |
+#ifdef USING_V8_SHARED |
+#define ASSERT(condition) assert(condition) |
+#endif // USING_V8_SHARED |
-const char* Shell::kHistoryFileName = ".d8_history"; |
-const char* Shell::kPrompt = "d8> "; |
+namespace v8 { |
+#ifndef USING_V8_SHARED |
LineEditor *LineEditor::first_ = NULL; |
+const char* Shell::kHistoryFileName = ".d8_history"; |
LineEditor::LineEditor(Type type, const char* name) |
@@ -98,17 +114,22 @@ CounterMap* Shell::counter_map_; |
i::OS::MemoryMappedFile* Shell::counters_file_ = NULL; |
CounterCollection Shell::local_counters_; |
CounterCollection* Shell::counters_ = &local_counters_; |
+i::Mutex* Shell::context_mutex_(i::OS::CreateMutex()); |
Persistent<Context> Shell::utility_context_; |
+#endif // USING_V8_SHARED |
+ |
Persistent<Context> Shell::evaluation_context_; |
-i::Mutex* Shell::context_mutex_(i::OS::CreateMutex()); |
ShellOptions Shell::options; |
+const char* Shell::kPrompt = "d8> "; |
+#ifndef USING_V8_SHARED |
bool CounterMap::Match(void* key1, void* key2) { |
const char* name1 = reinterpret_cast<const char*>(key1); |
const char* name2 = reinterpret_cast<const char*>(key2); |
return strcmp(name1, name2) == 0; |
} |
+#endif // USING_V8_SHARED |
// Converts a V8 value to a C string. |
@@ -122,17 +143,22 @@ bool Shell::ExecuteString(Handle<String> source, |
Handle<Value> name, |
bool print_result, |
bool report_exceptions) { |
+#ifndef USING_V8_SHARED |
+ bool FLAG_debugger = i::FLAG_debugger; |
+#else |
+ bool FLAG_debugger = false; |
+#endif // USING_V8_SHARED |
HandleScope handle_scope; |
TryCatch try_catch; |
options.script_executed = true; |
- if (i::FLAG_debugger) { |
+ if (FLAG_debugger) { |
// When debugging make exceptions appear to be uncaught. |
try_catch.SetVerbose(true); |
} |
Handle<Script> script = Script::Compile(source, name); |
if (script.IsEmpty()) { |
// Print errors that happened during compilation. |
- if (report_exceptions && !i::FLAG_debugger) |
+ if (report_exceptions && !FLAG_debugger) |
ReportException(&try_catch); |
return false; |
} else { |
@@ -140,7 +166,7 @@ bool Shell::ExecuteString(Handle<String> source, |
if (result.IsEmpty()) { |
ASSERT(try_catch.HasCaught()); |
// Print errors that happened during execution. |
- if (report_exceptions && !i::FLAG_debugger) |
+ if (report_exceptions && !FLAG_debugger) |
ReportException(&try_catch); |
return false; |
} else { |
@@ -196,15 +222,20 @@ Handle<Value> Shell::Read(const Arguments& args) { |
Handle<Value> Shell::ReadLine(const Arguments& args) { |
- i::SmartPointer<char> line(i::ReadLine("")); |
- if (*line == NULL) { |
- return Null(); |
- } |
- size_t len = strlen(*line); |
- if (len > 0 && line[len - 1] == '\n') { |
- --len; |
- } |
- return String::New(*line, len); |
+ static const int kBufferSize = 256; |
+ char buffer[kBufferSize]; |
+ Handle<String> accumulator = String::New(""); |
+ bool linebreak; |
+ int length; |
+ do { // Repeat if the line ends with an escape '\'. |
+ // fgets got an error. Just give up. |
+ if (fgets(buffer, kBufferSize, stdin) == NULL) return Null(); |
+ length = strlen(buffer); |
+ linebreak = (length > 1 && buffer[length-2] == '\\'); |
+ if (linebreak) buffer[length-2] = '\n'; |
+ accumulator = String::Concat(accumulator, String::New(buffer, length-1)); |
+ } while (linebreak); |
+ return accumulator; |
} |
@@ -236,6 +267,10 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args, |
return ThrowException( |
String::New("Array constructor needs one parameter.")); |
} |
+ static const int kMaxLength = 0x3fffffff; |
+#ifndef USING_V8_SHARED |
+ ASSERT(kMaxLength == i::ExternalArray::kMaxLength); |
+#endif // USING_V8_SHARED |
size_t length = 0; |
if (args[0]->IsUint32()) { |
length = args[0]->Uint32Value(); |
@@ -244,7 +279,7 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args, |
if (raw_length < 0) { |
return ThrowException(String::New("Array length must not be negative.")); |
} |
- if (raw_length > i::ExternalArray::kMaxLength) { |
+ if (raw_length > kMaxLength) { |
return ThrowException( |
String::New("Array length exceeds maximum length.")); |
} |
@@ -252,7 +287,7 @@ Handle<Value> Shell::CreateExternalArray(const Arguments& args, |
} else { |
return ThrowException(String::New("Array length must be a number.")); |
} |
- if (length > static_cast<size_t>(i::ExternalArray::kMaxLength)) { |
+ if (length > static_cast<size_t>(kMaxLength)) { |
return ThrowException(String::New("Array length exceeds maximum length.")); |
} |
void* data = calloc(length, element_size); |
@@ -332,7 +367,9 @@ Handle<Value> Shell::Yield(const Arguments& args) { |
Handle<Value> Shell::Quit(const Arguments& args) { |
int exit_code = args[0]->Int32Value(); |
+#ifndef USING_V8_SHARED |
OnExit(); |
+#endif // USING_V8_SHARED |
exit(exit_code); |
return Undefined(); |
} |
@@ -381,6 +418,7 @@ void Shell::ReportException(v8::TryCatch* try_catch) { |
} |
+#ifndef USING_V8_SHARED |
Handle<Array> Shell::GetCompletions(Handle<String> text, Handle<String> full) { |
HandleScope handle_scope; |
Context::Scope context_scope(utility_context_); |
@@ -414,9 +452,11 @@ Handle<Value> Shell::DebugCommandToJSONRequest(Handle<String> command) { |
Handle<Value> val = Handle<Function>::Cast(fun)->Call(global, kArgc, argv); |
return val; |
} |
-#endif |
+#endif // ENABLE_DEBUGGER_SUPPORT |
+#endif // USING_V8_SHARED |
+#ifndef USING_V8_SHARED |
int32_t* Counter::Bind(const char* name, bool is_histogram) { |
int i; |
for (i = 0; i < kMaxNameSize - 1 && name[i]; i++) |
@@ -448,8 +488,8 @@ Counter* CounterCollection::GetNextCounter() { |
void Shell::MapCounters(const char* name) { |
- counters_file_ = i::OS::MemoryMappedFile::create(name, |
- sizeof(CounterCollection), &local_counters_); |
+ counters_file_ = i::OS::MemoryMappedFile::create( |
+ name, sizeof(CounterCollection), &local_counters_); |
void* memory = (counters_file_ == NULL) ? |
NULL : counters_file_->memory(); |
if (memory == NULL) { |
@@ -514,6 +554,7 @@ void Shell::AddHistogramSample(void* histogram, int sample) { |
counter->AddSample(sample); |
} |
+ |
void Shell::InstallUtilityScript() { |
Locker lock; |
HandleScope scope; |
@@ -532,7 +573,7 @@ void Shell::InstallUtilityScript() { |
utility_context_->Global()->Set(String::New("$debug"), |
Utils::ToLocal(js_debug)); |
debug->debug_context()->set_security_token(HEAP->undefined_value()); |
-#endif |
+#endif // ENABLE_DEBUGGER_SUPPORT |
// Run the d8 shell utility script in the utility context |
int source_index = i::NativesCollection<i::D8>::GetIndex("d8"); |
@@ -550,10 +591,10 @@ void Shell::InstallUtilityScript() { |
// in the debugger. |
i::Handle<i::Object> compiled_script = Utils::OpenHandle(*script); |
i::Handle<i::Script> script_object = compiled_script->IsJSFunction() |
- ? i::Handle<i::Script>(i::Script::cast( |
- i::JSFunction::cast(*compiled_script)->shared()->script())) |
- : i::Handle<i::Script>(i::Script::cast( |
- i::SharedFunctionInfo::cast(*compiled_script)->script())); |
+ ? i::Handle<i::Script>(i::Script::cast( |
+ i::JSFunction::cast(*compiled_script)->shared()->script())) |
+ : i::Handle<i::Script>(i::Script::cast( |
+ i::SharedFunctionInfo::cast(*compiled_script)->script())); |
script_object->set_type(i::Smi::FromInt(i::Script::TYPE_NATIVE)); |
#ifdef ENABLE_DEBUGGER_SUPPORT |
@@ -561,8 +602,9 @@ void Shell::InstallUtilityScript() { |
if (i::FLAG_debugger && !i::FLAG_debugger_agent) { |
v8::Debug::SetDebugEventListener(HandleDebugEvent); |
} |
-#endif |
+#endif // ENABLE_DEBUGGER_SUPPORT |
} |
+#endif // USING_V8_SHARED |
#ifdef COMPRESS_STARTUP_DATA_BZ2 |
@@ -629,9 +671,11 @@ Handle<ObjectTemplate> Shell::CreateGlobalTemplate() { |
global_template->Set(String::New("lol_is_enabled"), Boolean::New(false)); |
#endif |
+#ifndef USING_V8_SHARED |
Handle<ObjectTemplate> os_templ = ObjectTemplate::New(); |
AddOSMethods(os_templ); |
global_template->Set(String::New("os"), os_templ); |
+#endif // USING_V8_SHARED |
return global_template; |
} |
@@ -647,6 +691,7 @@ void Shell::Initialize() { |
} |
#endif |
+#ifndef USING_V8_SHARED |
Shell::counter_map_ = new CounterMap(); |
// Set up counters |
if (i::StrLength(i::FLAG_map_counters) != 0) |
@@ -656,9 +701,10 @@ void Shell::Initialize() { |
V8::SetCreateHistogramFunction(CreateHistogram); |
V8::SetAddHistogramSampleFunction(AddHistogramSample); |
} |
- |
+#endif // USING_V8_SHARED |
if (options.test_shell) return; |
+#ifndef USING_V8_SHARED |
Locker lock; |
HandleScope scope; |
Handle<ObjectTemplate> global_template = CreateGlobalTemplate(); |
@@ -669,18 +715,22 @@ void Shell::Initialize() { |
if (i::FLAG_debugger_agent) { |
v8::Debug::EnableAgent("d8 shell", i::FLAG_debugger_port, true); |
} |
-#endif |
+#endif // ENABLE_DEBUGGER_SUPPORT |
+#endif // USING_V8_SHARED |
} |
Persistent<Context> Shell::CreateEvaluationContext() { |
+#ifndef USING_V8_SHARED |
// This needs to be a critical section since this is not thread-safe |
i::ScopedLock lock(context_mutex_); |
+#endif // USING_V8_SHARED |
// Initialize the global objects |
Handle<ObjectTemplate> global_template = CreateGlobalTemplate(); |
Persistent<Context> context = Context::New(NULL, global_template); |
Context::Scope scope(context); |
+#ifndef USING_V8_SHARED |
i::JSArguments js_args = i::FLAG_js_arguments; |
i::Handle<i::FixedArray> arguments_array = |
FACTORY->NewFixedArray(js_args.argc()); |
@@ -692,11 +742,13 @@ Persistent<Context> Shell::CreateEvaluationContext() { |
i::Handle<i::JSArray> arguments_jsarray = |
FACTORY->NewJSArrayWithElements(arguments_array); |
context->Global()->Set(String::New("arguments"), |
- Utils::ToLocal(arguments_jsarray)); |
+ Utils::ToLocal(arguments_jsarray)); |
+#endif // USING_V8_SHARED |
return context; |
} |
+#ifndef USING_V8_SHARED |
void Shell::OnExit() { |
if (i::FLAG_dump_counters) { |
printf("+----------------------------------------+-------------+\n"); |
@@ -716,12 +768,17 @@ void Shell::OnExit() { |
if (counters_file_ != NULL) |
delete counters_file_; |
} |
+#endif // USING_V8_SHARED |
static char* ReadChars(const char* name, int* size_out) { |
// Release the V8 lock while reading files. |
v8::Unlocker unlocker(Isolate::GetCurrent()); |
+#ifndef USING_V8_SHARED |
FILE* file = i::OS::FOpen(name, "rb"); |
+#else |
+ FILE* file = fopen(name, "rb"); // TODO: reading from a directory hangs! |
+#endif // USING_V8_SHARED |
if (file == NULL) return NULL; |
fseek(file, 0, SEEK_END); |
@@ -740,6 +797,7 @@ static char* ReadChars(const char* name, int* size_out) { |
} |
+#ifndef USING_V8_SHARED |
static char* ReadToken(char* data, char token) { |
char* next = i::OS::StrChr(data, token); |
if (next != NULL) { |
@@ -759,6 +817,7 @@ static char* ReadLine(char* data) { |
static char* ReadWord(char* data) { |
return ReadToken(data, ' '); |
} |
+#endif // USING_V8_SHARED |
// Reads a file into a v8 string. |
@@ -773,34 +832,44 @@ Handle<String> Shell::ReadFile(const char* name) { |
void Shell::RunShell() { |
+ Locker locker; |
+ Context::Scope context_scope(evaluation_context_); |
+ HandleScope handle_scope; |
+ Handle<String> name = String::New("(d8)"); |
+#ifndef USING_V8_SHARED |
LineEditor* editor = LineEditor::Get(); |
printf("V8 version %s [console: %s]\n", V8::GetVersion(), editor->name()); |
if (i::FLAG_debugger) { |
printf("JavaScript debugger enabled\n"); |
} |
- |
editor->Open(); |
while (true) { |
- Locker locker; |
- HandleScope handle_scope; |
- Context::Scope context_scope(evaluation_context_); |
i::SmartPointer<char> input = editor->Prompt(Shell::kPrompt); |
- if (input.is_empty()) |
- break; |
+ if (input.is_empty()) break; |
editor->AddHistory(*input); |
- Handle<String> name = String::New("(d8)"); |
ExecuteString(String::New(*input), name, true, true); |
} |
editor->Close(); |
+#else |
+ printf("V8 version %s [D8 light using shared library]\n", V8::GetVersion()); |
+ static const int kBufferSize = 256; |
+ while (true) { |
+ char buffer[kBufferSize]; |
+ printf("%s", Shell::kPrompt); |
+ if (fgets(buffer, kBufferSize, stdin) == NULL) break; |
+ ExecuteString(String::New(buffer), name, true, true); |
+ } |
+#endif // USING_V8_SHARED |
printf("\n"); |
} |
+#ifndef USING_V8_SHARED |
class ShellThread : public i::Thread { |
public: |
ShellThread(int no, i::Vector<const char> files) |
- : Thread("d8:ShellThread"), |
- no_(no), files_(files) { } |
+ : Thread("d8:ShellThread"), |
+ no_(no), files_(files) { } |
virtual void Run(); |
private: |
int no_; |
@@ -848,6 +917,7 @@ void ShellThread::Run() { |
ptr = next_line; |
} |
} |
+#endif // USING_V8_SHARED |
void SourceGroup::ExitShell(int exit_code) { |
@@ -894,7 +964,11 @@ void SourceGroup::Execute() { |
Handle<String> SourceGroup::ReadFile(const char* name) { |
- FILE* file = fopen(name, "rb"); |
+#ifndef USING_V8_SHARED |
+ FILE* file = i::OS::FOpen(name, "rb"); |
+#else |
+ FILE* file = fopen(name, "rb"); // TODO: reading from a directory hangs! |
+#endif // USING_V8_SHARED |
if (file == NULL) return Handle<String>(); |
fseek(file, 0, SEEK_END); |
@@ -914,6 +988,7 @@ Handle<String> SourceGroup::ReadFile(const char* name) { |
} |
+#ifndef USING_V8_SHARED |
i::Thread::Options SourceGroup::GetThreadOptions() { |
i::Thread::Options options; |
options.name = "IsolateThread"; |
@@ -965,6 +1040,7 @@ void SourceGroup::WaitForThread() { |
done_semaphore_->Wait(); |
} |
} |
+#endif // USING_V8_SHARED |
bool Shell::SetOptions(int argc, char* argv[]) { |
@@ -986,12 +1062,26 @@ bool Shell::SetOptions(int argc, char* argv[]) { |
options.test_shell = true; |
argv[i] = NULL; |
} else if (strcmp(argv[i], "--preemption") == 0) { |
+#ifdef USING_V8_SHARED |
+ printf("D8 with shared library does not support multi-threading\n"); |
+ return false; |
+#else |
options.use_preemption = true; |
argv[i] = NULL; |
+#endif // USING_V8_SHARED |
} else if (strcmp(argv[i], "--no-preemption") == 0) { |
+#ifdef USING_V8_SHARED |
+ printf("D8 with shared library does not support multi-threading\n"); |
+ return false; |
+#else |
options.use_preemption = false; |
argv[i] = NULL; |
+#endif // USING_V8_SHARED |
} else if (strcmp(argv[i], "--preemption-interval") == 0) { |
+#ifdef USING_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; |
@@ -1007,15 +1097,33 @@ bool Shell::SetOptions(int argc, char* argv[]) { |
printf("Missing value for --preemption-interval\n"); |
return false; |
} |
+#endif // USING_V8_SHARED |
} else if (strcmp(argv[i], "-f") == 0) { |
// Ignore any -f flags for compatibility with other stand-alone |
// JavaScript engines. |
continue; |
} else if (strcmp(argv[i], "--isolate") == 0) { |
+#ifdef USING_V8_SHARED |
+ printf("D8 with shared library does not support multi-threading\n"); |
+ return false; |
+#endif // USING_V8_SHARED |
options.num_isolates++; |
} |
+#ifdef USING_V8_SHARED |
+ else if (strcmp(argv[i], "--dump-counters") == 0) { |
+ printf("D8 with shared library does not include counters\n"); |
+ return false; |
+ } else if (strcmp(argv[i], "-p") == 0) { |
+ printf("D8 with shared library does not support multi-threading\n"); |
+ return false; |
+ } else if (strcmp(argv[i], "--debugger") == 0) { |
+ printf("Javascript debugger not included\n"); |
+ return false; |
+ } |
+#endif // USING_V8_SHARED |
} |
+#ifndef USING_V8_SHARED |
// Run parallel threads if we are not using --isolate |
for (int i = 1; i < argc; i++) { |
if (argv[i] == NULL) continue; |
@@ -1038,6 +1146,7 @@ bool Shell::SetOptions(int argc, char* argv[]) { |
options.parallel_files->Add(i::Vector<const char>(files, size)); |
} |
} |
+#endif // USING_V8_SHARED |
v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
@@ -1058,13 +1167,15 @@ bool Shell::SetOptions(int argc, char* argv[]) { |
current->End(argc); |
return true; |
-} |
+} |
int Shell::RunMain(int argc, char* argv[]) { |
+#ifndef USING_V8_SHARED |
i::List<i::Thread*> threads(1); |
- |
+#endif // USING_V8_SHARED |
{ |
+#ifndef USING_V8_SHARED |
if (options.parallel_files != NULL) |
for (int i = 0; i < options.parallel_files->length(); i++) { |
i::Vector<const char> files = options.parallel_files->at(i); |
@@ -1076,6 +1187,7 @@ int Shell::RunMain(int argc, char* argv[]) { |
for (int i = 1; i < options.num_isolates; ++i) { |
options.isolate_sources[i].StartExecuteInThread(); |
} |
+#endif // USING_V8_SHARED |
Locker lock; |
HandleScope scope; |
@@ -1090,14 +1202,18 @@ int Shell::RunMain(int argc, char* argv[]) { |
} else { |
context.Dispose(); |
} |
+ |
+#ifndef USING_V8_SHARED |
// Start preemption if threads have been created and preemption is enabled. |
if (options.parallel_files != NULL |
&& threads.length() > 0 |
&& options.use_preemption) { |
Locker::StartPreemption(options.preemption_interval); |
} |
+#endif // USING_V8_SHARED |
} |
+#ifndef USING_V8_SHARED |
for (int i = 1; i < options.num_isolates; ++i) { |
options.isolate_sources[i].WaitForThread(); |
} |
@@ -1110,6 +1226,7 @@ int Shell::RunMain(int argc, char* argv[]) { |
} |
OnExit(); |
+#endif // USING_V8_SHARED |
return 0; |
} |
@@ -1136,14 +1253,15 @@ int Shell::Main(int argc, char* argv[]) { |
result = RunMain(argc, argv); |
} |
-#ifdef ENABLE_DEBUGGER_SUPPORT |
+ |
+#if !defined(USING_V8_SHARED) && defined(ENABLE_DEBUGGER_SUPPORT) |
// Run remote debugger if requested, but never on --test |
if (i::FLAG_remote_debugger && !options.test_shell) { |
InstallUtilityScript(); |
RunRemoteDebugger(i::FLAG_debugger_port); |
return 0; |
} |
-#endif |
+#endif // !USING_V8_SHARED && ENABLE_DEBUGGER_SUPPORT |
// Run interactive shell if explicitly requested or if no script has been |
// executed, but never on --test |
@@ -1151,7 +1269,9 @@ int Shell::Main(int argc, char* argv[]) { |
if (( options.interactive_shell |
|| !options.script_executed ) |
&& !options.test_shell ) { |
+#ifndef USING_V8_SHARED |
InstallUtilityScript(); |
+#endif // USING_V8_SHARED |
RunShell(); |
} |