| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/report.h" | 5 #include "vm/report.h" |
| 6 | 6 |
| 7 #include "vm/code_patcher.h" | 7 #include "vm/code_patcher.h" |
| 8 #include "vm/exceptions.h" | 8 #include "vm/exceptions.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
| 11 #include "vm/object.h" | 11 #include "vm/object.h" |
| 12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
| 13 #include "vm/symbols.h" | 13 #include "vm/symbols.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 | 16 |
| 17 DEFINE_FLAG(int, stacktrace_depth_on_warning, 5, | 17 DEFINE_FLAG(int, stacktrace_depth_on_warning, 5, |
| 18 "Maximal number of stack frames to print after a runtime warning."); | 18 "Maximal number of stack frames to print after a runtime warning."); |
| 19 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); | 19 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings."); |
| 20 DEFINE_FLAG(bool, warn_on_javascript_compatibility, false, | 20 DEFINE_FLAG(bool, warn_on_javascript_compatibility, false, |
| 21 "Warn on incompatibilities between vm and dart2js."); | 21 "Warn on incompatibilities between vm and dart2js."); |
| 22 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); | 22 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors."); |
| 23 | 23 |
| 24 DECLARE_FLAG(bool, always_megamorphic_calls); | 24 DECLARE_FLAG(bool, always_megamorphic_calls); |
| 25 | 25 |
| 26 RawString* Report::PrependSnippet(Kind kind, | 26 RawString* Report::PrependSnippet(Kind kind, |
| 27 const Script& script, | 27 const Script& script, |
| 28 intptr_t token_pos, | 28 intptr_t token_pos, |
| 29 bool report_after_token, |
| 29 const String& message) { | 30 const String& message) { |
| 30 const char* message_header; | 31 const char* message_header; |
| 31 switch (kind) { | 32 switch (kind) { |
| 32 case kWarning: message_header = "warning"; break; | 33 case kWarning: message_header = "warning"; break; |
| 33 case kJSWarning: message_header = "javascript compatibility warning"; break; | 34 case kJSWarning: message_header = "javascript compatibility warning"; break; |
| 34 case kError: message_header = "error"; break; | 35 case kError: message_header = "error"; break; |
| 35 case kMalformedType: message_header = "malformed type"; break; | 36 case kMalformedType: message_header = "malformed type"; break; |
| 36 case kMalboundedType: message_header = "malbounded type"; break; | 37 case kMalboundedType: message_header = "malbounded type"; break; |
| 37 case kBailout: message_header = "bailout"; break; | 38 case kBailout: message_header = "bailout"; break; |
| 38 default: message_header = ""; UNREACHABLE(); | 39 default: message_header = ""; UNREACHABLE(); |
| 39 } | 40 } |
| 40 String& result = String::Handle(); | 41 String& result = String::Handle(); |
| 41 if (!script.IsNull()) { | 42 if (!script.IsNull()) { |
| 42 const String& script_url = String::Handle(script.url()); | 43 const String& script_url = String::Handle(script.url()); |
| 43 if (token_pos >= 0) { | 44 if (token_pos >= 0) { |
| 44 intptr_t line, column; | 45 intptr_t line, column, token_len; |
| 45 script.GetTokenLocation(token_pos, &line, &column); | 46 script.GetTokenLocation(token_pos, &line, &column, &token_len); |
| 47 if (report_after_token) { |
| 48 column += token_len; |
| 49 } |
| 46 // Only report the line position if we have the original source. We still | 50 // Only report the line position if we have the original source. We still |
| 47 // need to get a valid column so that we can report the ^ mark below the | 51 // need to get a valid column so that we can report the ^ mark below the |
| 48 // snippet. | 52 // snippet. |
| 49 // Allocate formatted strings in old sapce as they may be created during | 53 // Allocate formatted strings in old sapce as they may be created during |
| 50 // optimizing compilation. Those strings are created rarely and should not | 54 // optimizing compilation. Those strings are created rarely and should not |
| 51 // polute old space. | 55 // polute old space. |
| 52 if (script.HasSource()) { | 56 if (script.HasSource()) { |
| 53 result = String::NewFormatted(Heap::kOld, | 57 result = String::NewFormatted(Heap::kOld, |
| 54 "'%s': %s: line %" Pd " pos %" Pd ": ", | 58 "'%s': %s: line %" Pd " pos %" Pd ": ", |
| 55 script_url.ToCString(), | 59 script_url.ToCString(), |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 LongJumpV(prev_error, script, token_pos, format, args); | 117 LongJumpV(prev_error, script, token_pos, format, args); |
| 114 va_end(args); | 118 va_end(args); |
| 115 UNREACHABLE(); | 119 UNREACHABLE(); |
| 116 } | 120 } |
| 117 | 121 |
| 118 | 122 |
| 119 void Report::LongJumpV(const Error& prev_error, | 123 void Report::LongJumpV(const Error& prev_error, |
| 120 const Script& script, intptr_t token_pos, | 124 const Script& script, intptr_t token_pos, |
| 121 const char* format, va_list args) { | 125 const char* format, va_list args) { |
| 122 const Error& error = Error::Handle(LanguageError::NewFormattedV( | 126 const Error& error = Error::Handle(LanguageError::NewFormattedV( |
| 123 prev_error, script, token_pos, | 127 prev_error, script, token_pos, Report::AtLocation, |
| 124 kError, Heap::kNew, | 128 kError, Heap::kNew, |
| 125 format, args)); | 129 format, args)); |
| 126 LongJump(error); | 130 LongJump(error); |
| 127 UNREACHABLE(); | 131 UNREACHABLE(); |
| 128 } | 132 } |
| 129 | 133 |
| 130 | 134 |
| 131 void Report::MessageF(Kind kind, const Script& script, intptr_t token_pos, | 135 void Report::MessageF(Kind kind, const Script& script, intptr_t token_pos, |
| 132 const char* format, ...) { | 136 bool report_after_token, const char* format, ...) { |
| 133 va_list args; | 137 va_list args; |
| 134 va_start(args, format); | 138 va_start(args, format); |
| 135 MessageV(kind, script, token_pos, format, args); | 139 MessageV(kind, script, token_pos, report_after_token, format, args); |
| 136 va_end(args); | 140 va_end(args); |
| 137 } | 141 } |
| 138 | 142 |
| 139 | 143 |
| 140 void Report::MessageV(Kind kind, const Script& script, intptr_t token_pos, | 144 void Report::MessageV(Kind kind, |
| 145 const Script& script, |
| 146 intptr_t token_pos, |
| 147 bool report_after_token, |
| 141 const char* format, va_list args) { | 148 const char* format, va_list args) { |
| 142 if (kind < kError) { | 149 if (kind < kError) { |
| 143 // Reporting a warning. | 150 // Reporting a warning. |
| 144 if (FLAG_silent_warnings) { | 151 if (FLAG_silent_warnings) { |
| 145 return; | 152 return; |
| 146 } | 153 } |
| 147 if (!FLAG_warning_as_error) { | 154 if (!FLAG_warning_as_error) { |
| 148 const String& msg = String::Handle(String::NewFormattedV(format, args)); | 155 const String& msg = String::Handle(String::NewFormattedV(format, args)); |
| 149 const String& snippet_msg = String::Handle( | 156 const String& snippet_msg = String::Handle( |
| 150 PrependSnippet(kind, script, token_pos, msg)); | 157 PrependSnippet(kind, script, token_pos, report_after_token, msg)); |
| 151 OS::Print("%s", snippet_msg.ToCString()); | 158 OS::Print("%s", snippet_msg.ToCString()); |
| 152 if (kind == kJSWarning) { | 159 if (kind == kJSWarning) { |
| 153 TraceJSWarning(script, token_pos, msg); | 160 TraceJSWarning(script, token_pos, msg); |
| 154 // Do not print stacktrace if we have not executed Dart code yet. | 161 // Do not print stacktrace if we have not executed Dart code yet. |
| 155 if (Thread::Current()->top_exit_frame_info() != 0) { | 162 if (Thread::Current()->top_exit_frame_info() != 0) { |
| 156 const Stacktrace& stacktrace = | 163 const Stacktrace& stacktrace = |
| 157 Stacktrace::Handle(Exceptions::CurrentStacktrace()); | 164 Stacktrace::Handle(Exceptions::CurrentStacktrace()); |
| 158 intptr_t idx = 0; | 165 intptr_t idx = 0; |
| 159 OS::Print("%s", stacktrace.ToCStringInternal( | 166 OS::Print("%s", stacktrace.ToCStringInternal( |
| 160 &idx, FLAG_stacktrace_depth_on_warning)); | 167 &idx, FLAG_stacktrace_depth_on_warning)); |
| 161 } | 168 } |
| 162 } | 169 } |
| 163 return; | 170 return; |
| 164 } | 171 } |
| 165 } | 172 } |
| 166 // Reporting an error (or a warning as error). | 173 // Reporting an error (or a warning as error). |
| 167 const Error& error = Error::Handle( | 174 const Error& error = Error::Handle( |
| 168 LanguageError::NewFormattedV(Error::Handle(), // No previous error. | 175 LanguageError::NewFormattedV(Error::Handle(), // No previous error. |
| 169 script, token_pos, | 176 script, token_pos, report_after_token, |
| 170 kind, Heap::kNew, | 177 kind, Heap::kNew, |
| 171 format, args)); | 178 format, args)); |
| 172 if (kind == kJSWarning) { | 179 if (kind == kJSWarning) { |
| 173 Exceptions::ThrowJavascriptCompatibilityError(error.ToErrorCString()); | 180 Exceptions::ThrowJavascriptCompatibilityError(error.ToErrorCString()); |
| 174 UNREACHABLE(); | 181 UNREACHABLE(); |
| 175 } | 182 } |
| 176 LongJump(error); | 183 LongJump(error); |
| 177 UNREACHABLE(); | 184 UNREACHABLE(); |
| 178 } | 185 } |
| 179 | 186 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 ASSERT(FLAG_warn_on_javascript_compatibility); | 232 ASSERT(FLAG_warn_on_javascript_compatibility); |
| 226 if (FLAG_silent_warnings) return; | 233 if (FLAG_silent_warnings) return; |
| 227 Zone* zone = Thread::Current()->zone(); | 234 Zone* zone = Thread::Current()->zone(); |
| 228 const Code& caller_code = Code::Handle(zone, | 235 const Code& caller_code = Code::Handle(zone, |
| 229 caller_frame->LookupDartCode()); | 236 caller_frame->LookupDartCode()); |
| 230 ASSERT(!caller_code.IsNull()); | 237 ASSERT(!caller_code.IsNull()); |
| 231 const uword caller_pc = caller_frame->pc(); | 238 const uword caller_pc = caller_frame->pc(); |
| 232 const intptr_t token_pos = caller_code.GetTokenIndexOfPC(caller_pc); | 239 const intptr_t token_pos = caller_code.GetTokenIndexOfPC(caller_pc); |
| 233 const Function& caller = Function::Handle(zone, caller_code.function()); | 240 const Function& caller = Function::Handle(zone, caller_code.function()); |
| 234 const Script& script = Script::Handle(zone, caller.script()); | 241 const Script& script = Script::Handle(zone, caller.script()); |
| 235 MessageF(kJSWarning, script, token_pos, "%s", msg); | 242 MessageF(kJSWarning, script, token_pos, Report::AtLocation, "%s", msg); |
| 236 } | 243 } |
| 237 | 244 |
| 238 | 245 |
| 239 void Report::TraceJSWarning(const Script& script, | 246 void Report::TraceJSWarning(const Script& script, |
| 240 intptr_t token_pos, | 247 intptr_t token_pos, |
| 241 const String& message) { | 248 const String& message) { |
| 242 const int64_t micros = OS::GetCurrentTimeMicros(); | 249 const int64_t micros = OS::GetCurrentTimeMicros(); |
| 243 Isolate* isolate = Isolate::Current(); | 250 Isolate* isolate = Isolate::Current(); |
| 244 TraceBuffer* trace_buffer = isolate->trace_buffer(); | 251 TraceBuffer* trace_buffer = isolate->trace_buffer(); |
| 245 if (trace_buffer == NULL) { | 252 if (trace_buffer == NULL) { |
| 246 TraceBuffer::Init(isolate); | 253 TraceBuffer::Init(isolate); |
| 247 trace_buffer = isolate->trace_buffer(); | 254 trace_buffer = isolate->trace_buffer(); |
| 248 } | 255 } |
| 249 JSONStream js; | 256 JSONStream js; |
| 250 { | 257 { |
| 251 JSONObject trace_warning(&js); | 258 JSONObject trace_warning(&js); |
| 252 trace_warning.AddProperty("type", "JSCompatibilityWarning"); | 259 trace_warning.AddProperty("type", "JSCompatibilityWarning"); |
| 253 trace_warning.AddProperty("script", script); | 260 trace_warning.AddProperty("script", script); |
| 254 trace_warning.AddProperty("tokenPos", token_pos); | 261 trace_warning.AddProperty("tokenPos", token_pos); |
| 255 trace_warning.AddProperty("message", message); | 262 trace_warning.AddProperty("message", message); |
| 256 } | 263 } |
| 257 trace_buffer->Trace(micros, js.ToCString(), true); // Already escaped. | 264 trace_buffer->Trace(micros, js.ToCString(), true); // Already escaped. |
| 258 } | 265 } |
| 259 | 266 |
| 260 } // namespace dart | 267 } // namespace dart |
| 261 | 268 |
| OLD | NEW |