bool VM::initRepl() { ErrorReporter reporter; Module* core = addModule(reporter, String::create("core"), NULL); if (reporter.numErrors() > 0) return false; if (!core->compile(*this)) return false; scheduler_.runModule(core); return true; }
bool Module::compile(VM& vm) { ASSERT(!ast_.isNull(), "Must parse module before compiling."); ErrorReporter reporter; Compiler::compileModule(vm, reporter, ast_, this); // Now that we've compiled it, we can throw away the AST. ast_ = NULL; return reporter.numErrors() == 0; }
void XCScheme::parseBuildAction(const pugi::xml_node& node, const ErrorReporter& reporter) { // Get the BuildableReference node BuildRef br; const pugi::xml_node brNode = node.first_child(); // Get the product name getXMLProperty(brNode, "BuildableName", br.productName, VALUE_REQUIRED, reporter); // Get the target name getXMLProperty(brNode, "BlueprintName", br.targetName, VALUE_REQUIRED, reporter); // Get the container (project) for the target getXMLProperty(brNode, "ReferencedContainer", br.container, VALUE_REQUIRED, reporter); br.container = br.container.substr(10); // Get target id getXMLProperty(brNode, "BlueprintIdentifier", br.id, VALUE_REQUIRED, reporter); // Check that all fields were read if (br.productName.empty() || br.targetName.empty() || br.container.empty() || br.id.empty()) { reporter.reportError("BuildableReference is incomplete."); return; } // Get the value of buildForArchiving String shouldArchive; getXMLProperty(node, "buildForArchiving", shouldArchive, VALUE_REQUIRED, reporter); if (shouldArchive == "YES") { m_targets.push_back(br); } else { SBLog::info() << "Ignoring BuildableReference to \"" << br.targetName << "\" target because it is not archivable." << std::endl; } }
// TODO: hacky, parses arbitrary code string into a module void ParserTests::testCode(const char* sourceString, const char* expected) { gc<String> code = String::create(sourceString); ErrorReporter reporter; gc<SourceFile> source = new SourceFile(String::create("<file>"), code); Parser parser(source, reporter); gc<ModuleAst> module = parser.parseModule(); int numErrors = reporter.numErrors(); EXPECT_EQUAL(0, numErrors); if (numErrors == 0) { gc<String> text = module->body()->toString(); EXPECT_EQUAL(expected, *text); } }
void getXMLProperty(const pugi::xml_node& node, const String& propName, String& ret, GetterBehavior opt, const ErrorReporter& reporter) { const pugi::xml_attribute attrib = node.attribute(propName.c_str()); if (attrib) ret = attrib.value(); else if (opt == VALUE_REQUIRED) reporter.reportError("Failed reading \"" + propName + "\" property."); }
gc<Object> VM::evaluateReplExpression(gc<Expr> expr) { ErrorReporter reporter; if (replModule_ == NULL) { replModule_ = new Module(String::create("<repl>"), String::create("")); modules_.add(replModule_); // Implicitly import core. importModule(reporter, replModule_, NULL, String::create("core")); } // Compile it. Compiler::compileExpression(*this, reporter, expr, replModule_); if (reporter.numErrors() > 0) return gc<Object>(); return scheduler_.runModule(replModule_); }
void parseConfigFile(Options& opts, const string& filename, ErrorReporter& error_reporter) { ifstream cfgstream(filename.c_str(), ifstream::in); if (!cfgstream) { error_reporter.error(filename) << "Failed to open config file\n"; return; } CfgStreamParser csp(filename, opts, error_reporter); csp.scanStream(cfgstream); }
bool Module::parse(ErrorReporter& reporter) { ASSERT(ast_.isNull(), "Module is already parsed."); gc<String> code = readFile(path_); if (code.isNull()) { reporter.error(NULL, "Could not read \"%s\".", path_->cString()); return false; } source_ = new SourceFile(path_, code); Parser parser(source_, reporter); ast_ = parser.parseModule(); return !ast_.isNull(); }
void VMError::report_and_die() { // Don't allocate large buffer on stack static char buffer[O_BUFLEN]; // An error could happen before tty is initialized or after it has been // destroyed. Here we use a very simple unbuffered fdStream for printing. // Only out.print_raw() and out.print_raw_cr() should be used, as other // printing methods need to allocate large buffer on stack. To format a // string, use jio_snprintf() with a static buffer or use staticBufferStream. static fdStream out(defaultStream::output_fd()); // How many errors occurred in error handler when reporting first_error. static int recursive_error_count; // We will first print a brief message to standard out (verbose = false), // then save detailed information in log file (verbose = true). static bool out_done = false; // done printing to standard out static bool log_done = false; // done saving error log static bool transmit_report_done = false; // done error reporting static fdStream log; // error log if (SuppressFatalErrorMessage) { os::abort(); } jlong mytid = os::current_thread_id(); if (first_error == NULL && Atomic::cmpxchg_ptr(this, &first_error, NULL) == NULL) { // first time first_error_tid = mytid; set_error_reported(); if (ShowMessageBoxOnError || PauseAtExit) { show_message_box(buffer, sizeof(buffer)); // User has asked JVM to abort. Reset ShowMessageBoxOnError so the // WatcherThread can kill JVM if the error handler hangs. ShowMessageBoxOnError = false; } // Write a minidump on Windows, check core dump limits on Linux/Solaris os::check_or_create_dump(_siginfo, _context, buffer, sizeof(buffer)); // reset signal handlers or exception filter; make sure recursive crashes // are handled properly. reset_signal_handlers(); } else { // If UseOsErrorReporting we call this for each level of the call stack // while searching for the exception handler. Only the first level needs // to be reported. if (UseOSErrorReporting && log_done) return; // This is not the first error, see if it happened in a different thread // or in the same thread during error reporting. if (first_error_tid != mytid) { jio_snprintf(buffer, sizeof(buffer), "[thread " INT64_FORMAT " also had an error]", mytid); out.print_raw_cr(buffer); // error reporting is not MT-safe, block current thread os::infinite_sleep(); } else { if (recursive_error_count++ > 30) { out.print_raw_cr("[Too many errors, abort]"); os::die(); } jio_snprintf(buffer, sizeof(buffer), "[error occurred during error reporting %s, id 0x%x]", first_error ? first_error->_current_step_info : "", _id); if (log.is_open()) { log.cr(); log.print_raw_cr(buffer); log.cr(); } else { out.cr(); out.print_raw_cr(buffer); out.cr(); } } } // print to screen if (!out_done) { first_error->_verbose = false; staticBufferStream sbs(buffer, sizeof(buffer), &out); first_error->report(&sbs); out_done = true; first_error->_current_step = 0; // reset current_step first_error->_current_step_info = ""; // reset current_step string } // print to error log file if (!log_done) { first_error->_verbose = true; // see if log file is already open if (!log.is_open()) { // open log file int fd = -1; if (ErrorFile != NULL) { bool copy_ok = Arguments::copy_expand_pid(ErrorFile, strlen(ErrorFile), buffer, sizeof(buffer)); if (copy_ok) { fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); } } if (fd == -1) { const char *cwd = os::get_current_directory(buffer, sizeof(buffer)); size_t len = strlen(cwd); // either user didn't specify, or the user's location failed, // so use the default name in the current directory jio_snprintf(&buffer[len], sizeof(buffer)-len, "%shs_err_pid%u.log", os::file_separator(), os::current_process_id()); fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); } if (fd == -1) { const char * tmpdir = os::get_temp_directory(); // try temp directory if it exists. if (tmpdir != NULL && tmpdir[0] != '\0') { jio_snprintf(buffer, sizeof(buffer), "%s%shs_err_pid%u.log", tmpdir, os::file_separator(), os::current_process_id()); fd = open(buffer, O_RDWR | O_CREAT | O_TRUNC, 0666); } } if (fd != -1) { out.print_raw("# An error report file with more information is saved as:\n# "); out.print_raw_cr(buffer); os::set_error_file(buffer); log.set_fd(fd); } else { out.print_raw_cr("# Can not save log file, dump to screen.."); log.set_fd(defaultStream::output_fd()); /* Error reporting currently needs dumpfile. * Maybe implement direct streaming in the future.*/ transmit_report_done = true; } } staticBufferStream sbs(buffer, O_BUFLEN, &log); first_error->report(&sbs); first_error->_current_step = 0; // reset current_step first_error->_current_step_info = ""; // reset current_step string // Run error reporting to determine whether or not to report the crash. if (!transmit_report_done && should_report_bug(first_error->_id)) { transmit_report_done = true; FILE* hs_err = ::fdopen(log.fd(), "r"); if (NULL != hs_err) { ErrorReporter er; er.call(hs_err, buffer, O_BUFLEN); } } if (log.fd() != defaultStream::output_fd()) { close(log.fd()); } log.set_fd(-1); log_done = true; } static bool skip_OnError = false; if (!skip_OnError && OnError && OnError[0]) { skip_OnError = true; out.print_raw_cr("#"); out.print_raw ("# -XX:OnError=\""); out.print_raw (OnError); out.print_raw_cr("\""); char* cmd; const char* ptr = OnError; while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ out.print_raw ("# Executing "); #if defined(LINUX) || defined(_ALLBSD_SOURCE) out.print_raw ("/bin/sh -c "); #elif defined(SOLARIS) out.print_raw ("/usr/bin/sh -c "); #endif out.print_raw ("\""); out.print_raw (cmd); out.print_raw_cr("\" ..."); os::fork_and_exec(cmd); } // done with OnError OnError = NULL; } static bool skip_bug_url = !should_report_bug(first_error->_id); if (!skip_bug_url) { skip_bug_url = true; out.print_raw_cr("#"); print_bug_submit_message(&out, _thread); } if (!UseOSErrorReporting) { // os::abort() will call abort hooks, try it first. static bool skip_os_abort = false; if (!skip_os_abort) { skip_os_abort = true; bool dump_core = should_report_bug(first_error->_id); os::abort(dump_core); } // if os::abort() doesn't abort, try os::die(); os::die(); } }
void VMError::report_and_die(int id, const char* message, const char* detail_fmt, va_list detail_args, Thread* thread, address pc, void* siginfo, void* context, const char* filename, int lineno, size_t size) { // Don't allocate large buffer on stack static char buffer[O_BUFLEN]; out.set_scratch_buffer(buffer, sizeof(buffer)); log.set_scratch_buffer(buffer, sizeof(buffer)); // How many errors occurred in error handler when reporting first_error. static int recursive_error_count; // We will first print a brief message to standard out (verbose = false), // then save detailed information in log file (verbose = true). static bool out_done = false; // done printing to standard out static bool log_done = false; // done saving error log static bool transmit_report_done = false; // done error reporting if (SuppressFatalErrorMessage) { os::abort(CreateCoredumpOnCrash); } intptr_t mytid = os::current_thread_id(); if (first_error_tid == -1 && Atomic::cmpxchg_ptr(mytid, &first_error_tid, -1) == -1) { // Initialize time stamps to use the same base. out.time_stamp().update_to(1); log.time_stamp().update_to(1); _id = id; _message = message; _thread = thread; _pc = pc; _siginfo = siginfo; _context = context; _filename = filename; _lineno = lineno; _size = size; jio_vsnprintf(_detail_msg, sizeof(_detail_msg), detail_fmt, detail_args); // first time set_error_reported(); if (ShowMessageBoxOnError || PauseAtExit) { show_message_box(buffer, sizeof(buffer)); // User has asked JVM to abort. Reset ShowMessageBoxOnError so the // WatcherThread can kill JVM if the error handler hangs. ShowMessageBoxOnError = false; } os::check_dump_limit(buffer, sizeof(buffer)); // reset signal handlers or exception filter; make sure recursive crashes // are handled properly. reset_signal_handlers(); TRACE_VM_ERROR(); } else { // If UseOsErrorReporting we call this for each level of the call stack // while searching for the exception handler. Only the first level needs // to be reported. if (UseOSErrorReporting && log_done) return; // This is not the first error, see if it happened in a different thread // or in the same thread during error reporting. if (first_error_tid != mytid) { char msgbuf[64]; jio_snprintf(msgbuf, sizeof(msgbuf), "[thread " INTX_FORMAT " also had an error]", mytid); out.print_raw_cr(msgbuf); // error reporting is not MT-safe, block current thread os::infinite_sleep(); } else { if (recursive_error_count++ > 30) { out.print_raw_cr("[Too many errors, abort]"); os::die(); } jio_snprintf(buffer, sizeof(buffer), "[error occurred during error reporting (%s), id 0x%x]", _current_step_info, _id); if (log.is_open()) { log.cr(); log.print_raw_cr(buffer); log.cr(); } else { out.cr(); out.print_raw_cr(buffer); out.cr(); } } } // print to screen if (!out_done) { report(&out, false); out_done = true; _current_step = 0; _current_step_info = ""; } // print to error log file if (!log_done) { // see if log file is already open if (!log.is_open()) { // open log file int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); if (fd != -1) { out.print_raw("# An error report file with more information is saved as:\n# "); out.print_raw_cr(buffer); log.set_fd(fd); } else { out.print_raw_cr("# Can not save log file, dump to screen.."); log.set_fd(defaultStream::output_fd()); /* Error reporting currently needs dumpfile. * Maybe implement direct streaming in the future.*/ transmit_report_done = true; } } report(&log, true); _current_step = 0; _current_step_info = ""; // Run error reporting to determine whether or not to report the crash. if (!transmit_report_done && should_report_bug(_id)) { transmit_report_done = true; const int fd2 = ::dup(log.fd()); FILE* const hs_err = ::fdopen(fd2, "r"); if (NULL != hs_err) { ErrorReporter er; er.call(hs_err, buffer, O_BUFLEN); } ::fclose(hs_err); } if (log.fd() != defaultStream::output_fd()) { close(log.fd()); } log.set_fd(-1); log_done = true; } static bool skip_replay = ReplayCompiles; // Do not overwrite file during replay if (DumpReplayDataOnError && _thread && _thread->is_Compiler_thread() && !skip_replay) { skip_replay = true; ciEnv* env = ciEnv::current(); if (env != NULL) { int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer)); if (fd != -1) { FILE* replay_data_file = os::open(fd, "w"); if (replay_data_file != NULL) { fileStream replay_data_stream(replay_data_file, /*need_close=*/true); env->dump_replay_data_unsafe(&replay_data_stream); out.print_raw("#\n# Compiler replay data is saved as:\n# "); out.print_raw_cr(buffer); } else { int e = errno; out.print_raw("#\n# Can't open file to dump replay data. Error: "); out.print_raw_cr(os::strerror(e)); } } } } static bool skip_bug_url = !should_report_bug(_id); if (!skip_bug_url) { skip_bug_url = true; out.print_raw_cr("#"); print_bug_submit_message(&out, _thread); } static bool skip_OnError = false; if (!skip_OnError && OnError && OnError[0]) { skip_OnError = true; // Flush output and finish logs before running OnError commands. ostream_abort(); out.print_raw_cr("#"); out.print_raw ("# -XX:OnError=\""); out.print_raw (OnError); out.print_raw_cr("\""); char* cmd; const char* ptr = OnError; while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ out.print_raw ("# Executing "); #if defined(LINUX) || defined(_ALLBSD_SOURCE) out.print_raw ("/bin/sh -c "); #elif defined(SOLARIS) out.print_raw ("/usr/bin/sh -c "); #endif out.print_raw ("\""); out.print_raw (cmd); out.print_raw_cr("\" ..."); if (os::fork_and_exec(cmd) < 0) { out.print_cr("os::fork_and_exec failed: %s (%s=%d)", os::strerror(errno), os::errno_name(errno), errno); } } // done with OnError OnError = NULL; } if (!UseOSErrorReporting) { // os::abort() will call abort hooks, try it first. static bool skip_os_abort = false; if (!skip_os_abort) { skip_os_abort = true; bool dump_core = should_report_bug(_id); os::abort(dump_core && CreateCoredumpOnCrash, _siginfo, _context); } // if os::abort() doesn't abort, try os::die(); os::die(); } }
void VMError::report_and_die() { // Don't allocate large buffer on stack static char buffer[O_BUFLEN]; // How many errors occurred in error handler when reporting first_error. static int recursive_error_count; // We will first print a brief message to standard out (verbose = false), // then save detailed information in log file (verbose = true). static bool out_done = false; // done printing to standard out static bool log_done = false; // done saving error log static bool transmit_report_done = false; // done error reporting // disble NMT to avoid further exception MemTracker::shutdown(MemTracker::NMT_error_reporting); if (SuppressFatalErrorMessage) { os::abort(); } jlong mytid = os::current_thread_id(); if (first_error == NULL && Atomic::cmpxchg_ptr(this, &first_error, NULL) == NULL) { // first time first_error_tid = mytid; set_error_reported(); if (ShowMessageBoxOnError || PauseAtExit) { show_message_box(buffer, sizeof(buffer)); // User has asked JVM to abort. Reset ShowMessageBoxOnError so the // WatcherThread can kill JVM if the error handler hangs. ShowMessageBoxOnError = false; } // Write a minidump on Windows, check core dump limits on Linux/Solaris os::check_or_create_dump(_siginfo, _context, buffer, sizeof(buffer)); // reset signal handlers or exception filter; make sure recursive crashes // are handled properly. reset_signal_handlers(); } else { // If UseOsErrorReporting we call this for each level of the call stack // while searching for the exception handler. Only the first level needs // to be reported. if (UseOSErrorReporting && log_done) return; // This is not the first error, see if it happened in a different thread // or in the same thread during error reporting. if (first_error_tid != mytid) { char msgbuf[64]; jio_snprintf(msgbuf, sizeof(msgbuf), "[thread " INT64_FORMAT " also had an error]", mytid); out.print_raw_cr(msgbuf); // error reporting is not MT-safe, block current thread os::infinite_sleep(); } else { if (recursive_error_count++ > 30) { out.print_raw_cr("[Too many errors, abort]"); os::die(); } jio_snprintf(buffer, sizeof(buffer), "[error occurred during error reporting %s, id 0x%x]", first_error ? first_error->_current_step_info : "", _id); if (log.is_open()) { log.cr(); log.print_raw_cr(buffer); log.cr(); } else { out.cr(); out.print_raw_cr(buffer); out.cr(); } } } // print to screen if (!out_done) { first_error->_verbose = false; staticBufferStream sbs(buffer, sizeof(buffer), &out); first_error->report(&sbs); out_done = true; first_error->_current_step = 0; // reset current_step first_error->_current_step_info = ""; // reset current_step string } // print to error log file if (!log_done) { first_error->_verbose = true; // see if log file is already open if (!log.is_open()) { // open log file int fd = prepare_log_file(ErrorFile, "hs_err_pid%p.log", buffer, sizeof(buffer)); if (fd != -1) { out.print_raw("# An error report file with more information is saved as:\n# "); out.print_raw_cr(buffer); os::set_error_file(buffer); log.set_fd(fd); } else { out.print_raw_cr("# Can not save log file, dump to screen.."); log.set_fd(defaultStream::output_fd()); /* Error reporting currently needs dumpfile. * Maybe implement direct streaming in the future.*/ transmit_report_done = true; } } staticBufferStream sbs(buffer, O_BUFLEN, &log); first_error->report(&sbs); first_error->_current_step = 0; // reset current_step first_error->_current_step_info = ""; // reset current_step string // Run error reporting to determine whether or not to report the crash. if (!transmit_report_done && should_report_bug(first_error->_id)) { transmit_report_done = true; FILE* hs_err = os::open(log.fd(), "r"); if (NULL != hs_err) { ErrorReporter er; er.call(hs_err, buffer, O_BUFLEN); } } if (log.fd() != defaultStream::output_fd()) { close(log.fd()); } log.set_fd(-1); log_done = true; } static bool skip_OnError = false; if (!skip_OnError && OnError && OnError[0]) { skip_OnError = true; out.print_raw_cr("#"); out.print_raw ("# -XX:OnError=\""); out.print_raw (OnError); out.print_raw_cr("\""); char* cmd; const char* ptr = OnError; while ((cmd = next_OnError_command(buffer, sizeof(buffer), &ptr)) != NULL){ out.print_raw ("# Executing "); #if defined(LINUX) || defined(_ALLBSD_SOURCE) out.print_raw ("/bin/sh -c "); #elif defined(SOLARIS) out.print_raw ("/usr/bin/sh -c "); #endif out.print_raw ("\""); out.print_raw (cmd); out.print_raw_cr("\" ..."); os::fork_and_exec(cmd); } // done with OnError OnError = NULL; } static bool skip_replay = ReplayCompiles; // Do not overwrite file during replay if (DumpReplayDataOnError && _thread && _thread->is_Compiler_thread() && !skip_replay) { skip_replay = true; ciEnv* env = ciEnv::current(); if (env != NULL) { int fd = prepare_log_file(ReplayDataFile, "replay_pid%p.log", buffer, sizeof(buffer)); if (fd != -1) { FILE* replay_data_file = os::open(fd, "w"); if (replay_data_file != NULL) { fileStream replay_data_stream(replay_data_file, /*need_close=*/true); env->dump_replay_data_unsafe(&replay_data_stream); out.print_raw("#\n# Compiler replay data is saved as:\n# "); out.print_raw_cr(buffer); } else { out.print_raw("#\n# Can't open file to dump replay data. Error: "); out.print_raw_cr(strerror(os::get_last_error())); } } } } static bool skip_bug_url = !should_report_bug(first_error->_id); if (!skip_bug_url) { skip_bug_url = true; out.print_raw_cr("#"); print_bug_submit_message(&out, _thread); } if (!UseOSErrorReporting) { // os::abort() will call abort hooks, try it first. static bool skip_os_abort = false; if (!skip_os_abort) { skip_os_abort = true; bool dump_core = should_report_bug(first_error->_id); os::abort(dump_core); } // if os::abort() doesn't abort, try os::die(); os::die(); } }
bool VM::runProgram(gc<String> path) { // Remember where the program is so we can import modules from there. programDir_ = path::dir(path::real(path)); // Traverse the import graph. ErrorReporter reporter; addModule(reporter, NULL, path); if (reporter.numErrors() > 0) return false; // Sort the modules by their imports so that dependencies are run before // modules that depend on them. // See: http://en.wikipedia.org/wiki/Topological_sorting // Clone the import graph so we can destructively modify it. // TODO(bob): This does lots of array copies since ImportGraph stores an // array directly. Do something smarter here. Array<ImportGraph> graph; for (int i = 0; i < modules_.count(); i++) { graph.add(ImportGraph(modules_[i])); } Array<Module*> modules; while (graph.count() > 0) { bool madeProgress = false; for (int i = 0; i < graph.count(); i++) { // See if all of this module's imports are accounted for. if (graph[i].imports.count() == 0) { // They are, so it's ready to process. modules.add(graph[i].module); // And now everything that imports it doesn't have to worry about it // anymore. for (int j = 0; j < graph.count(); j++) { for (int k = 0; k < graph[j].imports.count(); k++) { if (graph[j].imports[k] == graph[i].module) { graph[j].imports.removeAt(k); k--; } } } graph.removeAt(i); i--; madeProgress = true; } } // Bail if there is an import cycle. // TODO(bob): Better error-handling. if (!madeProgress) return false; } // Compile all modules before running any of them. for (int i = 0; i < modules.count(); i++) { if (!modules[i]->compile(*this)) return false; } scheduler_.run(modules); return true; }