v8  3.25.30(node0.11.13)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
debug-agent.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifdef ENABLE_DEBUGGER_SUPPORT
29 
30 #include "v8.h"
31 #include "debug.h"
32 #include "debug-agent.h"
33 #include "platform/socket.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 // Public V8 debugger API message handler function. This function just delegates
39 // to the debugger agent through it's data parameter.
40 void DebuggerAgentMessageHandler(const v8::Debug::Message& message) {
41  Isolate* isolate = reinterpret_cast<Isolate*>(message.GetIsolate());
42  DebuggerAgent* agent = isolate->debugger_agent_instance();
43  ASSERT(agent != NULL);
44  agent->DebuggerMessage(message);
45 }
46 
47 
48 DebuggerAgent::DebuggerAgent(Isolate* isolate, const char* name, int port)
49  : Thread(name),
50  isolate_(isolate),
51  name_(StrDup(name)),
52  port_(port),
53  server_(new Socket),
54  terminate_(false),
55  session_(NULL),
56  terminate_now_(0),
57  listening_(0) {
58  ASSERT(isolate_->debugger_agent_instance() == NULL);
59  isolate_->set_debugger_agent_instance(this);
60 }
61 
62 
63 DebuggerAgent::~DebuggerAgent() {
64  isolate_->set_debugger_agent_instance(NULL);
65  delete server_;
66 }
67 
68 
69 // Debugger agent main thread.
70 void DebuggerAgent::Run() {
71  // Allow this socket to reuse port even if still in TIME_WAIT.
72  server_->SetReuseAddress(true);
73 
74  // First bind the socket to the requested port.
75  bool bound = false;
76  while (!bound && !terminate_) {
77  bound = server_->Bind(port_);
78 
79  // If an error occurred wait a bit before retrying. The most common error
80  // would be that the port is already in use so this avoids a busy loop and
81  // make the agent take over the port when it becomes free.
82  if (!bound) {
83  const TimeDelta kTimeout = TimeDelta::FromSeconds(1);
84  PrintF("Failed to open socket on port %d, "
85  "waiting %d ms before retrying\n", port_,
86  static_cast<int>(kTimeout.InMilliseconds()));
87  if (!terminate_now_.WaitFor(kTimeout)) {
88  if (terminate_) return;
89  }
90  }
91  }
92 
93  // Accept connections on the bound port.
94  while (!terminate_) {
95  bool ok = server_->Listen(1);
96  listening_.Signal();
97  if (ok) {
98  // Accept the new connection.
99  Socket* client = server_->Accept();
100  ok = client != NULL;
101  if (ok) {
102  // Create and start a new session.
103  CreateSession(client);
104  }
105  }
106  }
107 }
108 
109 
110 void DebuggerAgent::Shutdown() {
111  // Set the termination flag.
112  terminate_ = true;
113 
114  // Signal termination and make the server exit either its listen call or its
115  // binding loop. This makes sure that no new sessions can be established.
116  terminate_now_.Signal();
117  server_->Shutdown();
118  Join();
119 
120  // Close existing session if any.
121  CloseSession();
122 }
123 
124 
125 void DebuggerAgent::WaitUntilListening() {
126  listening_.Wait();
127 }
128 
129 static const char* kCreateSessionMessage =
130  "Remote debugging session already active\r\n";
131 
132 void DebuggerAgent::CreateSession(Socket* client) {
133  LockGuard<RecursiveMutex> session_access_guard(&session_access_);
134 
135  // If another session is already established terminate this one.
136  if (session_ != NULL) {
137  int len = StrLength(kCreateSessionMessage);
138  int res = client->Send(kCreateSessionMessage, len);
139  delete client;
140  USE(res);
141  return;
142  }
143 
144  // Create a new session and hook up the debug message handler.
145  session_ = new DebuggerAgentSession(this, client);
146  isolate_->debugger()->SetMessageHandler(DebuggerAgentMessageHandler);
147  session_->Start();
148 }
149 
150 
151 void DebuggerAgent::CloseSession() {
152  LockGuard<RecursiveMutex> session_access_guard(&session_access_);
153 
154  // Terminate the session.
155  if (session_ != NULL) {
156  session_->Shutdown();
157  session_->Join();
158  delete session_;
159  session_ = NULL;
160  }
161 }
162 
163 
164 void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
165  LockGuard<RecursiveMutex> session_access_guard(&session_access_);
166 
167  // Forward the message handling to the session.
168  if (session_ != NULL) {
169  v8::String::Value val(message.GetJSON());
170  session_->DebuggerMessage(Vector<uint16_t>(const_cast<uint16_t*>(*val),
171  val.length()));
172  }
173 }
174 
175 
176 DebuggerAgentSession::~DebuggerAgentSession() {
177  delete client_;
178 }
179 
180 
181 void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
182  // Don't do anything during termination.
183  if (terminate_) {
184  return;
185  }
186 
187  // Terminate the session.
188  LockGuard<RecursiveMutex> session_access_guard(&session_access_);
189  ASSERT(session == session_);
190  if (session == session_) {
191  session_->Shutdown();
192  delete session_;
193  session_ = NULL;
194  }
195 }
196 
197 
198 void DebuggerAgentSession::Run() {
199  // Send the hello message.
200  bool ok = DebuggerAgentUtil::SendConnectMessage(client_, agent_->name_.get());
201  if (!ok) return;
202 
203  while (true) {
204  // Read data from the debugger front end.
205  SmartArrayPointer<char> message =
206  DebuggerAgentUtil::ReceiveMessage(client_);
207 
208  const char* msg = message.get();
209  bool is_closing_session = (msg == NULL);
210 
211  if (msg == NULL) {
212  // If we lost the connection, then simulate a disconnect msg:
213  msg = "{\"seq\":1,\"type\":\"request\",\"command\":\"disconnect\"}";
214 
215  } else {
216  // Check if we're getting a disconnect request:
217  const char* disconnectRequestStr =
218  "\"type\":\"request\",\"command\":\"disconnect\"}";
219  const char* result = strstr(msg, disconnectRequestStr);
220  if (result != NULL) {
221  is_closing_session = true;
222  }
223  }
224 
225  // Convert UTF-8 to UTF-16.
226  unibrow::Utf8Decoder<128> decoder(msg, StrLength(msg));
227  int utf16_length = decoder.Utf16Length();
228  ScopedVector<uint16_t> temp(utf16_length + 1);
229  decoder.WriteUtf16(temp.start(), utf16_length);
230 
231  // Send the request received to the debugger.
232  v8::Debug::SendCommand(temp.start(),
233  utf16_length,
234  NULL,
235  reinterpret_cast<v8::Isolate*>(agent_->isolate()));
236 
237  if (is_closing_session) {
238  // Session is closed.
239  agent_->OnSessionClosed(this);
240  return;
241  }
242  }
243 }
244 
245 
246 void DebuggerAgentSession::DebuggerMessage(Vector<uint16_t> message) {
247  DebuggerAgentUtil::SendMessage(client_, message);
248 }
249 
250 
251 void DebuggerAgentSession::Shutdown() {
252  // Shutdown the socket to end the blocking receive.
253  client_->Shutdown();
254 }
255 
256 
257 const char* const DebuggerAgentUtil::kContentLength = "Content-Length";
258 
259 
260 SmartArrayPointer<char> DebuggerAgentUtil::ReceiveMessage(Socket* conn) {
261  int received;
262 
263  // Read header.
264  int content_length = 0;
265  while (true) {
266  const int kHeaderBufferSize = 80;
267  char header_buffer[kHeaderBufferSize];
268  int header_buffer_position = 0;
269  char c = '\0'; // One character receive buffer.
270  char prev_c = '\0'; // Previous character.
271 
272  // Read until CRLF.
273  while (!(c == '\n' && prev_c == '\r')) {
274  prev_c = c;
275  received = conn->Receive(&c, 1);
276  if (received == 0) {
277  PrintF("Error %d\n", Socket::GetLastError());
278  return SmartArrayPointer<char>();
279  }
280 
281  // Add character to header buffer.
282  if (header_buffer_position < kHeaderBufferSize) {
283  header_buffer[header_buffer_position++] = c;
284  }
285  }
286 
287  // Check for end of header (empty header line).
288  if (header_buffer_position == 2) { // Receive buffer contains CRLF.
289  break;
290  }
291 
292  // Terminate header.
293  ASSERT(header_buffer_position > 1); // At least CRLF is received.
294  ASSERT(header_buffer_position <= kHeaderBufferSize);
295  header_buffer[header_buffer_position - 2] = '\0';
296 
297  // Split header.
298  char* key = header_buffer;
299  char* value = NULL;
300  for (int i = 0; header_buffer[i] != '\0'; i++) {
301  if (header_buffer[i] == ':') {
302  header_buffer[i] = '\0';
303  value = header_buffer + i + 1;
304  while (*value == ' ') {
305  value++;
306  }
307  break;
308  }
309  }
310 
311  // Check that key is Content-Length.
312  if (strcmp(key, kContentLength) == 0) {
313  // Get the content length value if present and within a sensible range.
314  if (value == NULL || strlen(value) > 7) {
315  return SmartArrayPointer<char>();
316  }
317  for (int i = 0; value[i] != '\0'; i++) {
318  // Bail out if illegal data.
319  if (value[i] < '0' || value[i] > '9') {
320  return SmartArrayPointer<char>();
321  }
322  content_length = 10 * content_length + (value[i] - '0');
323  }
324  } else {
325  // For now just print all other headers than Content-Length.
326  PrintF("%s: %s\n", key, value != NULL ? value : "(no value)");
327  }
328  }
329 
330  // Return now if no body.
331  if (content_length == 0) {
332  return SmartArrayPointer<char>();
333  }
334 
335  // Read body.
336  char* buffer = NewArray<char>(content_length + 1);
337  received = ReceiveAll(conn, buffer, content_length);
338  if (received < content_length) {
339  PrintF("Error %d\n", Socket::GetLastError());
340  return SmartArrayPointer<char>();
341  }
342  buffer[content_length] = '\0';
343 
344  return SmartArrayPointer<char>(buffer);
345 }
346 
347 
348 bool DebuggerAgentUtil::SendConnectMessage(Socket* conn,
349  const char* embedding_host) {
350  static const int kBufferSize = 80;
351  char buffer[kBufferSize]; // Sending buffer.
352  bool ok;
353  int len;
354 
355  // Send the header.
356  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
357  "Type: connect\r\n");
358  ok = conn->Send(buffer, len);
359  if (!ok) return false;
360 
361  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
362  "V8-Version: %s\r\n", v8::V8::GetVersion());
363  ok = conn->Send(buffer, len);
364  if (!ok) return false;
365 
366  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
367  "Protocol-Version: 1\r\n");
368  ok = conn->Send(buffer, len);
369  if (!ok) return false;
370 
371  if (embedding_host != NULL) {
372  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
373  "Embedding-Host: %s\r\n", embedding_host);
374  ok = conn->Send(buffer, len);
375  if (!ok) return false;
376  }
377 
378  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
379  "%s: 0\r\n", kContentLength);
380  ok = conn->Send(buffer, len);
381  if (!ok) return false;
382 
383  // Terminate header with empty line.
384  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
385  ok = conn->Send(buffer, len);
386  if (!ok) return false;
387 
388  // No body for connect message.
389 
390  return true;
391 }
392 
393 
394 bool DebuggerAgentUtil::SendMessage(Socket* conn,
395  const Vector<uint16_t> message) {
396  static const int kBufferSize = 80;
397  char buffer[kBufferSize]; // Sending buffer both for header and body.
398 
399  // Calculate the message size in UTF-8 encoding.
400  int utf8_len = 0;
402  for (int i = 0; i < message.length(); i++) {
403  uint16_t character = message[i];
404  utf8_len += unibrow::Utf8::Length(character, previous);
405  previous = character;
406  }
407 
408  // Send the header.
409  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
410  "%s: %d\r\n", kContentLength, utf8_len);
411  if (conn->Send(buffer, len) < len) {
412  return false;
413  }
414 
415  // Terminate header with empty line.
416  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
417  if (conn->Send(buffer, len) < len) {
418  return false;
419  }
420 
421  // Send message body as UTF-8.
422  int buffer_position = 0; // Current buffer position.
424  for (int i = 0; i < message.length(); i++) {
425  // Write next UTF-8 encoded character to buffer.
426  uint16_t character = message[i];
427  buffer_position +=
428  unibrow::Utf8::Encode(buffer + buffer_position, character, previous);
429  ASSERT(buffer_position <= kBufferSize);
430 
431  // Send buffer if full or last character is encoded.
432  if (kBufferSize - buffer_position <
434  i == message.length() - 1) {
435  if (unibrow::Utf16::IsLeadSurrogate(character)) {
436  const int kEncodedSurrogateLength =
438  ASSERT(buffer_position >= kEncodedSurrogateLength);
439  len = buffer_position - kEncodedSurrogateLength;
440  if (conn->Send(buffer, len) < len) {
441  return false;
442  }
443  for (int i = 0; i < kEncodedSurrogateLength; i++) {
444  buffer[i] = buffer[buffer_position + i];
445  }
446  buffer_position = kEncodedSurrogateLength;
447  } else {
448  len = buffer_position;
449  if (conn->Send(buffer, len) < len) {
450  return false;
451  }
452  buffer_position = 0;
453  }
454  }
455  previous = character;
456  }
457 
458  return true;
459 }
460 
461 
462 bool DebuggerAgentUtil::SendMessage(Socket* conn,
463  const v8::Handle<v8::String> request) {
464  static const int kBufferSize = 80;
465  char buffer[kBufferSize]; // Sending buffer both for header and body.
466 
467  // Convert the request to UTF-8 encoding.
468  v8::String::Utf8Value utf8_request(request);
469 
470  // Send the header.
471  int len = OS::SNPrintF(Vector<char>(buffer, kBufferSize),
472  "Content-Length: %d\r\n", utf8_request.length());
473  if (conn->Send(buffer, len) < len) {
474  return false;
475  }
476 
477  // Terminate header with empty line.
478  len = OS::SNPrintF(Vector<char>(buffer, kBufferSize), "\r\n");
479  if (conn->Send(buffer, len) < len) {
480  return false;
481  }
482 
483  // Send message body as UTF-8.
484  len = utf8_request.length();
485  if (conn->Send(*utf8_request, len) < len) {
486  return false;
487  }
488 
489  return true;
490 }
491 
492 
493 // Receive the full buffer before returning unless an error occours.
494 int DebuggerAgentUtil::ReceiveAll(Socket* conn, char* data, int len) {
495  int total_received = 0;
496  while (total_received < len) {
497  int received = conn->Receive(data + total_received, len - total_received);
498  if (received == 0) {
499  return total_received;
500  }
501  total_received += received;
502  }
503  return total_received;
504 }
505 
506 } } // namespace v8::internal
507 
508 #endif // ENABLE_DEBUGGER_SUPPORT
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
Definition: flags.cc:269
void PrintF(const char *format,...)
Definition: v8utils.cc:40
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
Definition: flags.cc:665
#define ASSERT(condition)
Definition: checks.h:329
unsigned short uint16_t
Definition: unicode.cc:46
static const int kMaxExtraUtf8BytesForOneUtf16CodeUnit
Definition: unicode.h:127
static const char * GetVersion()
Definition: api.cc:5120
virtual Isolate * GetIsolate() const =0
static uchar Length(uchar chr, int previous)
Definition: unicode-inl.h:163
static const int kUtf8BytesToCodeASurrogate
Definition: unicode.h:130
virtual Handle< String > GetJSON() const =0
static unsigned Encode(char *out, uchar c, int previous, bool replace_invalid=false)
Definition: unicode-inl.h:114
int StrLength(const char *string)
Definition: utils.h:253
static int SNPrintF(Vector< char > str, const char *format,...)
void USE(T)
Definition: globals.h:341
static bool IsLeadSurrogate(int code)
Definition: unicode.h:108
char * StrDup(const char *str)
Definition: allocation.cc:89
static void SendCommand(const uint16_t *command, int length, ClientData *client_data=NULL, Isolate *isolate=NULL)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
Definition: flags.cc:505
static const int kNoPreviousCharacter
Definition: unicode.h:120