The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / execution.cc @ 40c0f755

History | View | Annotate | Download (19.6 KB)

1
// Copyright 2006-2008 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
#include <stdlib.h>
29

    
30
#include "v8.h"
31

    
32
#include "api.h"
33
#include "codegen-inl.h"
34

    
35
#ifdef ARM
36
#include "simulator-arm.h"
37
#else  // ia32
38
#include "simulator-ia32.h"
39
#endif
40

    
41
#include "debug.h"
42
#include "v8threads.h"
43

    
44
namespace v8 { namespace internal {
45

    
46

    
47
static Handle<Object> Invoke(bool construct,
48
                             Handle<JSFunction> func,
49
                             Handle<Object> receiver,
50
                             int argc,
51
                             Object*** args,
52
                             bool* has_pending_exception) {
53
  // Make sure we have a real function, not a boilerplate function.
54
  ASSERT(!func->IsBoilerplate());
55

    
56
  // Entering JavaScript.
57
  VMState state(JS);
58

    
59
  // Guard the stack against too much recursion.
60
  StackGuard guard;
61

    
62
  // Placeholder for return value.
63
  Object* value = reinterpret_cast<Object*>(kZapValue);
64

    
65
  typedef Object* (*JSEntryFunction)(
66
    byte* entry,
67
    Object* function,
68
    Object* receiver,
69
    int argc,
70
    Object*** args);
71

    
72
  Handle<Code> code;
73
  if (construct) {
74
    JSConstructEntryStub stub;
75
    code = stub.GetCode();
76
  } else {
77
    JSEntryStub stub;
78
    code = stub.GetCode();
79
  }
80

    
81
  {
82
    // Save and restore context around invocation and block the
83
    // allocation of handles without explicit handle scopes.
84
    SaveContext save;
85
    NoHandleAllocation na;
86
    JSEntryFunction entry = FUNCTION_CAST<JSEntryFunction>(code->entry());
87

    
88
    // Call the function through the right JS entry stub.
89
    value = CALL_GENERATED_CODE(entry, func->code()->entry(), *func,
90
                                *receiver, argc, args);
91
  }
92

    
93
#ifdef DEBUG
94
  value->Verify();
95
#endif
96

    
97
  // Update the pending exception flag and return the value.
98
  *has_pending_exception = value->IsException();
99
  ASSERT(*has_pending_exception == Top::has_pending_exception());
100
  if (*has_pending_exception) {
101
    Top::ReportPendingMessages();
102
    return Handle<Object>();
103
  } else {
104
    Top::clear_pending_message();
105
  }
106

    
107
  return Handle<Object>(value);
108
}
109

    
110

    
111
Handle<Object> Execution::Call(Handle<JSFunction> func,
112
                               Handle<Object> receiver,
113
                               int argc,
114
                               Object*** args,
115
                               bool* pending_exception) {
116
  return Invoke(false, func, receiver, argc, args, pending_exception);
117
}
118

    
119

    
120
Handle<Object> Execution::New(Handle<JSFunction> func, int argc,
121
                              Object*** args, bool* pending_exception) {
122
  return Invoke(true, func, Top::global(), argc, args, pending_exception);
123
}
124

    
125

    
126
Handle<Object> Execution::TryCall(Handle<JSFunction> func,
127
                                  Handle<Object> receiver,
128
                                  int argc,
129
                                  Object*** args,
130
                                  bool* caught_exception) {
131
  // Enter a try-block while executing the JavaScript code. To avoid
132
  // duplicate error printing it must be non-verbose.  Also, to avoid
133
  // creating message objects during stack overflow we shouldn't
134
  // capture messages.
135
  v8::TryCatch catcher;
136
  catcher.SetVerbose(false);
137
  catcher.SetCaptureMessage(false);
138

    
139
  Handle<Object> result = Invoke(false, func, receiver, argc, args,
140
                                 caught_exception);
141

    
142
  if (*caught_exception) {
143
    ASSERT(catcher.HasCaught());
144
    ASSERT(Top::has_pending_exception());
145
    ASSERT(Top::external_caught_exception());
146
    Top::optional_reschedule_exception(true);
147
    result = v8::Utils::OpenHandle(*catcher.Exception());
148
  }
149

    
150
  ASSERT(!Top::has_pending_exception());
151
  ASSERT(!Top::external_caught_exception());
152
  return result;
153
}
154

    
155

    
156
Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) {
157
  ASSERT(!object->IsJSFunction());
158

    
159
  // If you return a function from here, it will be called when an
160
  // attempt is made to call the given object as a function.
161

    
162
  // The regular expression code here is really meant more as an
163
  // example than anything else. KJS does not support calling regular
164
  // expressions as functions, but SpiderMonkey does.
165
  if (FLAG_call_regexp) {
166
    bool is_regexp =
167
        object->IsHeapObject() &&
168
        (HeapObject::cast(*object)->map()->constructor() ==
169
         *Top::regexp_function());
170

    
171
    if (is_regexp) {
172
      Handle<String> exec = Factory::exec_symbol();
173
      return Handle<Object>(object->GetProperty(*exec));
174
    }
175
  }
176

    
177
  // Objects created through the API can have an instance-call handler
178
  // that should be used when calling the object as a function.
179
  if (object->IsHeapObject() &&
180
      HeapObject::cast(*object)->map()->has_instance_call_handler()) {
181
    return Handle<JSFunction>(
182
        Top::global_context()->call_as_function_delegate());
183
  }
184

    
185
  return Factory::undefined_value();
186
}
187

    
188

    
189
// Static state for stack guards.
190
StackGuard::ThreadLocal StackGuard::thread_local_;
191

    
192

    
193
StackGuard::StackGuard() {
194
  // NOTE: Overall the StackGuard code assumes that the stack grows towards
195
  // lower addresses.
196
  ExecutionAccess access;
197
  if (thread_local_.nesting_++ == 0) {
198
    // Initial StackGuard is being set. We will set the stack limits based on
199
    // the current stack pointer allowing the stack to grow kLimitSize from
200
    // here.
201

    
202
    // Ensure that either the stack limits are unset (kIllegalLimit) or that
203
    // they indicate a pending interruption. The interrupt limit will be
204
    // temporarily reset through the code below and reestablished if the
205
    // interrupt flags indicate that an interrupt is pending.
206
    ASSERT(thread_local_.jslimit_ == kIllegalLimit ||
207
           (thread_local_.jslimit_ == kInterruptLimit &&
208
            thread_local_.interrupt_flags_ != 0));
209
    ASSERT(thread_local_.climit_ == kIllegalLimit ||
210
           (thread_local_.climit_ == kInterruptLimit &&
211
            thread_local_.interrupt_flags_ != 0));
212

    
213
    thread_local_.initial_jslimit_ = thread_local_.jslimit_ =
214
        GENERATED_CODE_STACK_LIMIT(kLimitSize);
215
    // NOTE: The check for overflow is not safe as there is no guarantee that
216
    // the running thread has its stack in all memory up to address 0x00000000.
217
    thread_local_.initial_climit_ = thread_local_.climit_ =
218
        reinterpret_cast<uintptr_t>(this) >= kLimitSize ?
219
            reinterpret_cast<uintptr_t>(this) - kLimitSize : 0;
220

    
221
    if (thread_local_.interrupt_flags_ != 0) {
222
      set_limits(kInterruptLimit, access);
223
    }
224
  }
225
  // Ensure that proper limits have been set.
226
  ASSERT(thread_local_.jslimit_ != kIllegalLimit &&
227
         thread_local_.climit_ != kIllegalLimit);
228
  ASSERT(thread_local_.initial_jslimit_ != kIllegalLimit &&
229
         thread_local_.initial_climit_ != kIllegalLimit);
230
}
231

    
232

    
233
StackGuard::~StackGuard() {
234
  ExecutionAccess access;
235
  if (--thread_local_.nesting_ == 0) {
236
    set_limits(kIllegalLimit, access);
237
  }
238
}
239

    
240

    
241
bool StackGuard::IsStackOverflow() {
242
  ExecutionAccess access;
243
  return (thread_local_.jslimit_ != kInterruptLimit &&
244
          thread_local_.climit_ != kInterruptLimit);
245
}
246

    
247

    
248
void StackGuard::EnableInterrupts() {
249
  ExecutionAccess access;
250
  if (IsSet(access)) {
251
    set_limits(kInterruptLimit, access);
252
  }
253
}
254

    
255

    
256
void StackGuard::SetStackLimit(uintptr_t limit) {
257
  ExecutionAccess access;
258
  // If the current limits are special (eg due to a pending interrupt) then
259
  // leave them alone.
260
  if (thread_local_.jslimit_ == thread_local_.initial_jslimit_) {
261
    thread_local_.jslimit_ = limit;
262
  }
263
  if (thread_local_.climit_ == thread_local_.initial_climit_) {
264
    thread_local_.climit_ = limit;
265
  }
266
  thread_local_.initial_climit_ = limit;
267
  thread_local_.initial_jslimit_ = limit;
268
}
269

    
270

    
271
void StackGuard::DisableInterrupts() {
272
  ExecutionAccess access;
273
  reset_limits(access);
274
}
275

    
276

    
277
bool StackGuard::IsSet(const ExecutionAccess& lock) {
278
  return thread_local_.interrupt_flags_ != 0;
279
}
280

    
281

    
282
bool StackGuard::IsInterrupted() {
283
  ExecutionAccess access;
284
  return thread_local_.interrupt_flags_ & INTERRUPT;
285
}
286

    
287

    
288
void StackGuard::Interrupt() {
289
  ExecutionAccess access;
290
  thread_local_.interrupt_flags_ |= INTERRUPT;
291
  set_limits(kInterruptLimit, access);
292
}
293

    
294

    
295
bool StackGuard::IsPreempted() {
296
  ExecutionAccess access;
297
  return thread_local_.interrupt_flags_ & PREEMPT;
298
}
299

    
300

    
301
void StackGuard::Preempt() {
302
  ExecutionAccess access;
303
  thread_local_.interrupt_flags_ |= PREEMPT;
304
  set_limits(kInterruptLimit, access);
305
}
306

    
307

    
308
bool StackGuard::IsDebugBreak() {
309
  ExecutionAccess access;
310
  return thread_local_.interrupt_flags_ & DEBUGBREAK;
311
}
312

    
313

    
314
void StackGuard::DebugBreak() {
315
  ExecutionAccess access;
316
  thread_local_.interrupt_flags_ |= DEBUGBREAK;
317
  set_limits(kInterruptLimit, access);
318
}
319

    
320

    
321
bool StackGuard::IsDebugCommand() {
322
  ExecutionAccess access;
323
  return thread_local_.interrupt_flags_ & DEBUGCOMMAND;
324
}
325

    
326

    
327
void StackGuard::DebugCommand() {
328
  if (FLAG_debugger_auto_break) {
329
    ExecutionAccess access;
330
    thread_local_.interrupt_flags_ |= DEBUGCOMMAND;
331
    set_limits(kInterruptLimit, access);
332
  }
333
}
334

    
335

    
336
void StackGuard::Continue(InterruptFlag after_what) {
337
  ExecutionAccess access;
338
  thread_local_.interrupt_flags_ &= ~static_cast<int>(after_what);
339
  if (thread_local_.interrupt_flags_ == 0) {
340
    reset_limits(access);
341
  }
342
}
343

    
344

    
345
int StackGuard::ArchiveSpacePerThread() {
346
  return sizeof(ThreadLocal);
347
}
348

    
349

    
350
char* StackGuard::ArchiveStackGuard(char* to) {
351
  ExecutionAccess access;
352
  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
353
  ThreadLocal blank;
354
  thread_local_ = blank;
355
  return to + sizeof(ThreadLocal);
356
}
357

    
358

    
359
char* StackGuard::RestoreStackGuard(char* from) {
360
  ExecutionAccess access;
361
  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
362
  return from + sizeof(ThreadLocal);
363
}
364

    
365

    
366
// --- C a l l s   t o   n a t i v e s ---
367

    
368
#define RETURN_NATIVE_CALL(name, argc, argv, has_pending_exception) \
369
  do {                                                              \
370
    Object** args[argc] = argv;                                     \
371
    ASSERT(has_pending_exception != NULL);                          \
372
    return Call(Top::name##_fun(), Top::builtins(), argc, args,     \
373
                has_pending_exception);                             \
374
  } while (false)
375

    
376

    
377
Handle<Object> Execution::ToBoolean(Handle<Object> obj) {
378
  // See the similar code in runtime.js:ToBoolean.
379
  if (obj->IsBoolean()) return obj;
380
  bool result = true;
381
  if (obj->IsString()) {
382
    result = Handle<String>::cast(obj)->length() != 0;
383
  } else if (obj->IsNull() || obj->IsUndefined()) {
384
    result = false;
385
  } else if (obj->IsNumber()) {
386
    double value = obj->Number();
387
    result = !((value == 0) || isnan(value));
388
  }
389
  return Handle<Object>(Heap::ToBoolean(result));
390
}
391

    
392

    
393
Handle<Object> Execution::ToNumber(Handle<Object> obj, bool* exc) {
394
  RETURN_NATIVE_CALL(to_number, 1, { obj.location() }, exc);
395
}
396

    
397

    
398
Handle<Object> Execution::ToString(Handle<Object> obj, bool* exc) {
399
  RETURN_NATIVE_CALL(to_string, 1, { obj.location() }, exc);
400
}
401

    
402

    
403
Handle<Object> Execution::ToDetailString(Handle<Object> obj, bool* exc) {
404
  RETURN_NATIVE_CALL(to_detail_string, 1, { obj.location() }, exc);
405
}
406

    
407

    
408
Handle<Object> Execution::ToObject(Handle<Object> obj, bool* exc) {
409
  if (obj->IsJSObject()) return obj;
410
  RETURN_NATIVE_CALL(to_object, 1, { obj.location() }, exc);
411
}
412

    
413

    
414
Handle<Object> Execution::ToInteger(Handle<Object> obj, bool* exc) {
415
  RETURN_NATIVE_CALL(to_integer, 1, { obj.location() }, exc);
416
}
417

    
418

    
419
Handle<Object> Execution::ToUint32(Handle<Object> obj, bool* exc) {
420
  RETURN_NATIVE_CALL(to_uint32, 1, { obj.location() }, exc);
421
}
422

    
423

    
424
Handle<Object> Execution::ToInt32(Handle<Object> obj, bool* exc) {
425
  RETURN_NATIVE_CALL(to_int32, 1, { obj.location() }, exc);
426
}
427

    
428

    
429
Handle<Object> Execution::NewDate(double time, bool* exc) {
430
  Handle<Object> time_obj = Factory::NewNumber(time);
431
  RETURN_NATIVE_CALL(create_date, 1, { time_obj.location() }, exc);
432
}
433

    
434

    
435
#undef RETURN_NATIVE_CALL
436

    
437

    
438
Handle<Object> Execution::CharAt(Handle<String> string, uint32_t index) {
439
  int int_index = static_cast<int>(index);
440
  if (int_index < 0 || int_index >= string->length()) {
441
    return Factory::undefined_value();
442
  }
443

    
444
  Handle<Object> char_at =
445
      GetProperty(Top::builtins(), Factory::char_at_symbol());
446
  if (!char_at->IsJSFunction()) {
447
    return Factory::undefined_value();
448
  }
449

    
450
  bool caught_exception;
451
  Handle<Object> index_object = Factory::NewNumberFromInt(int_index);
452
  Object** index_arg[] = { index_object.location() };
453
  Handle<Object> result = TryCall(Handle<JSFunction>::cast(char_at),
454
                                  string,
455
                                  ARRAY_SIZE(index_arg),
456
                                  index_arg,
457
                                  &caught_exception);
458
  if (caught_exception) {
459
    return Factory::undefined_value();
460
  }
461
  return result;
462
}
463

    
464

    
465
Handle<JSFunction> Execution::InstantiateFunction(
466
    Handle<FunctionTemplateInfo> data, bool* exc) {
467
  // Fast case: see if the function has already been instantiated
468
  int serial_number = Smi::cast(data->serial_number())->value();
469
  Object* elm =
470
      Top::global_context()->function_cache()->GetElement(serial_number);
471
  if (elm->IsJSFunction()) return Handle<JSFunction>(JSFunction::cast(elm));
472
  // The function has not yet been instantiated in this context; do it.
473
  Object** args[1] = { Handle<Object>::cast(data).location() };
474
  Handle<Object> result =
475
      Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
476
  if (*exc) return Handle<JSFunction>::null();
477
  return Handle<JSFunction>::cast(result);
478
}
479

    
480

    
481
Handle<JSObject> Execution::InstantiateObject(Handle<ObjectTemplateInfo> data,
482
                                              bool* exc) {
483
  if (data->property_list()->IsUndefined() &&
484
      !data->constructor()->IsUndefined()) {
485
    // Initialization to make gcc happy.
486
    Object* result = NULL;
487
    {
488
      HandleScope scope;
489
      Handle<FunctionTemplateInfo> cons_template =
490
          Handle<FunctionTemplateInfo>(
491
              FunctionTemplateInfo::cast(data->constructor()));
492
      Handle<JSFunction> cons = InstantiateFunction(cons_template, exc);
493
      if (*exc) return Handle<JSObject>::null();
494
      Handle<Object> value = New(cons, 0, NULL, exc);
495
      if (*exc) return Handle<JSObject>::null();
496
      result = *value;
497
    }
498
    ASSERT(!*exc);
499
    return Handle<JSObject>(JSObject::cast(result));
500
  } else {
501
    Object** args[1] = { Handle<Object>::cast(data).location() };
502
    Handle<Object> result =
503
        Call(Top::instantiate_fun(), Top::builtins(), 1, args, exc);
504
    if (*exc) return Handle<JSObject>::null();
505
    return Handle<JSObject>::cast(result);
506
  }
507
}
508

    
509

    
510
void Execution::ConfigureInstance(Handle<Object> instance,
511
                                  Handle<Object> instance_template,
512
                                  bool* exc) {
513
  Object** args[2] = { instance.location(), instance_template.location() };
514
  Execution::Call(Top::configure_instance_fun(), Top::builtins(), 2, args, exc);
515
}
516

    
517

    
518
Handle<String> Execution::GetStackTraceLine(Handle<Object> recv,
519
                                            Handle<JSFunction> fun,
520
                                            Handle<Object> pos,
521
                                            Handle<Object> is_global) {
522
  const int argc = 4;
523
  Object** args[argc] = { recv.location(),
524
                          Handle<Object>::cast(fun).location(),
525
                          pos.location(),
526
                          is_global.location() };
527
  bool caught_exception = false;
528
  Handle<Object> result = TryCall(Top::get_stack_trace_line_fun(),
529
                                  Top::builtins(), argc, args,
530
                                  &caught_exception);
531
  if (caught_exception || !result->IsString()) return Factory::empty_symbol();
532
  return Handle<String>::cast(result);
533
}
534

    
535

    
536
static Object* RuntimePreempt() {
537
  // Clear the preempt request flag.
538
  StackGuard::Continue(PREEMPT);
539

    
540
  ContextSwitcher::PreemptionReceived();
541

    
542
  if (Debug::InDebugger()) {
543
    // If currently in the debugger don't do any actual preemption but record
544
    // that preemption occoured while in the debugger.
545
    Debug::PreemptionWhileInDebugger();
546
  } else {
547
    // Perform preemption.
548
    v8::Unlocker unlocker;
549
    Thread::YieldCPU();
550
  }
551

    
552
  return Heap::undefined_value();
553
}
554

    
555

    
556
Object* Execution::DebugBreakHelper() {
557
  // Just continue if breaks are disabled.
558
  if (Debug::disable_break()) {
559
    return Heap::undefined_value();
560
  }
561

    
562
  // Don't break in system functions. If the current function is
563
  // either in the builtins object of some context or is in the debug
564
  // context just return with the debug break stack guard active.
565
  JavaScriptFrameIterator it;
566
  JavaScriptFrame* frame = it.frame();
567
  Object* fun = frame->function();
568
  if (fun->IsJSFunction()) {
569
    GlobalObject* global = JSFunction::cast(fun)->context()->global();
570
    if (global->IsJSBuiltinsObject() || Debug::IsDebugGlobal(global)) {
571
      return Heap::undefined_value();
572
    }
573
  }
574

    
575
  // Check for debug command break only.
576
  bool debug_command_only =
577
      StackGuard::IsDebugCommand() && !StackGuard::IsDebugBreak();
578

    
579
  // Clear the debug request flags.
580
  StackGuard::Continue(DEBUGBREAK);
581
  StackGuard::Continue(DEBUGCOMMAND);
582

    
583
  // If debug command only and already in debugger ignore it.
584
  if (debug_command_only && Debug::InDebugger()) {
585
    return Heap::undefined_value();
586
  }
587

    
588
  HandleScope scope;
589
  // Enter the debugger. Just continue if we fail to enter the debugger.
590
  EnterDebugger debugger;
591
  if (debugger.FailedToEnter()) {
592
    return Heap::undefined_value();
593
  }
594

    
595
  // Notify the debug event listeners.
596
  Debugger::OnDebugBreak(Factory::undefined_value(), debug_command_only);
597

    
598
  // Return to continue execution.
599
  return Heap::undefined_value();
600
}
601

    
602

    
603
Object* Execution::HandleStackGuardInterrupt() {
604
  if (StackGuard::IsDebugBreak() || StackGuard::IsDebugCommand()) {
605
    DebugBreakHelper();
606
  }
607
  if (StackGuard::IsPreempted()) RuntimePreempt();
608
  if (StackGuard::IsInterrupted()) {
609
    // interrupt
610
    StackGuard::Continue(INTERRUPT);
611
    return Top::StackOverflow();
612
  }
613
  return Heap::undefined_value();
614
}
615

    
616
// --- G C   E x t e n s i o n ---
617

    
618
const char* GCExtension::kSource = "native function gc();";
619

    
620

    
621
v8::Handle<v8::FunctionTemplate> GCExtension::GetNativeFunction(
622
    v8::Handle<v8::String> str) {
623
  return v8::FunctionTemplate::New(GCExtension::GC);
624
}
625

    
626

    
627
v8::Handle<v8::Value> GCExtension::GC(const v8::Arguments& args) {
628
  // All allocation spaces other than NEW_SPACE have the same effect.
629
  Heap::CollectGarbage(0, OLD_DATA_SPACE);
630
  return v8::Undefined();
631
}
632

    
633

    
634
static GCExtension kGCExtension;
635
v8::DeclareExtension kGCExtensionDeclaration(&kGCExtension);
636

    
637
} }  // namespace v8::internal