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 / api.cc @ f230a1cf

History | View | Annotate | Download (248 KB)

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
#include "api.h"
29

    
30
#include <string.h>  // For memcpy, strlen.
31
#include <cmath>  // For isnan.
32
#include "../include/v8-debug.h"
33
#include "../include/v8-profiler.h"
34
#include "../include/v8-testing.h"
35
#include "assert-scope.h"
36
#include "bootstrapper.h"
37
#include "code-stubs.h"
38
#include "compiler.h"
39
#include "conversions-inl.h"
40
#include "counters.h"
41
#include "cpu-profiler.h"
42
#include "debug.h"
43
#include "deoptimizer.h"
44
#include "execution.h"
45
#include "global-handles.h"
46
#include "heap-profiler.h"
47
#include "heap-snapshot-generator-inl.h"
48
#include "icu_util.h"
49
#include "json-parser.h"
50
#include "messages.h"
51
#ifdef COMPRESS_STARTUP_DATA_BZ2
52
#include "natives.h"
53
#endif
54
#include "parser.h"
55
#include "platform.h"
56
#include "platform/time.h"
57
#include "profile-generator-inl.h"
58
#include "property-details.h"
59
#include "property.h"
60
#include "runtime.h"
61
#include "runtime-profiler.h"
62
#include "scanner-character-streams.h"
63
#include "snapshot.h"
64
#include "unicode-inl.h"
65
#include "utils/random-number-generator.h"
66
#include "v8threads.h"
67
#include "version.h"
68
#include "vm-state-inl.h"
69

    
70

    
71
#define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
72

    
73
#define ENTER_V8(isolate)                                          \
74
  ASSERT((isolate)->IsInitialized());                              \
75
  i::VMState<i::OTHER> __state__((isolate))
76

    
77
namespace v8 {
78

    
79
#define ON_BAILOUT(isolate, location, code)                        \
80
  if (IsExecutionTerminatingCheck(isolate)) {                      \
81
    code;                                                          \
82
    UNREACHABLE();                                                 \
83
  }
84

    
85

    
86
#define EXCEPTION_PREAMBLE(isolate)                                         \
87
  (isolate)->handle_scope_implementer()->IncrementCallDepth();              \
88
  ASSERT(!(isolate)->external_caught_exception());                          \
89
  bool has_pending_exception = false
90

    
91

    
92
#define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback)           \
93
  do {                                                                         \
94
    i::HandleScopeImplementer* handle_scope_implementer =                      \
95
        (isolate)->handle_scope_implementer();                                 \
96
    handle_scope_implementer->DecrementCallDepth();                            \
97
    if (has_pending_exception) {                                               \
98
      if (handle_scope_implementer->CallDepthIsZero() &&                       \
99
          (isolate)->is_out_of_memory()) {                                     \
100
        if (!(isolate)->ignore_out_of_memory())                                \
101
          i::V8::FatalProcessOutOfMemory(NULL);                                \
102
      }                                                                        \
103
      bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
104
      (isolate)->OptionalRescheduleException(call_depth_is_zero);              \
105
      do_callback                                                              \
106
      return value;                                                            \
107
    }                                                                          \
108
    do_callback                                                                \
109
  } while (false)
110

    
111

    
112
#define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value)                    \
113
  EXCEPTION_BAILOUT_CHECK_GENERIC(                                             \
114
      isolate, value, i::V8::FireCallCompletedCallback(isolate);)
115

    
116

    
117
#define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
118
  EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
119

    
120

    
121
#define API_ENTRY_CHECK(isolate, msg)                                          \
122
  do {                                                                         \
123
    if (v8::Locker::IsActive()) {                                              \
124
      ApiCheck(isolate->thread_manager()->IsLockedByCurrentThread(),           \
125
               msg,                                                            \
126
               "Entering the V8 API without proper locking in place");         \
127
    }                                                                          \
128
  } while (false)
129

    
130

    
131
// --- E x c e p t i o n   B e h a v i o r ---
132

    
133

    
134
static void DefaultFatalErrorHandler(const char* location,
135
                                     const char* message) {
136
  i::Isolate* isolate = i::Isolate::Current();
137
  if (isolate->IsInitialized()) {
138
    i::VMState<i::OTHER> state(isolate);
139
    API_Fatal(location, message);
140
  } else {
141
    API_Fatal(location, message);
142
  }
143
}
144

    
145

    
146
static FatalErrorCallback GetFatalErrorHandler() {
147
  i::Isolate* isolate = i::Isolate::Current();
148
  if (isolate->exception_behavior() == NULL) {
149
    isolate->set_exception_behavior(DefaultFatalErrorHandler);
150
  }
151
  return isolate->exception_behavior();
152
}
153

    
154

    
155
void i::FatalProcessOutOfMemory(const char* location) {
156
  i::V8::FatalProcessOutOfMemory(location, false);
157
}
158

    
159

    
160
// When V8 cannot allocated memory FatalProcessOutOfMemory is called.
161
// The default fatal error handler is called and execution is stopped.
162
void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
163
  i::HeapStats heap_stats;
164
  int start_marker;
165
  heap_stats.start_marker = &start_marker;
166
  int new_space_size;
167
  heap_stats.new_space_size = &new_space_size;
168
  int new_space_capacity;
169
  heap_stats.new_space_capacity = &new_space_capacity;
170
  intptr_t old_pointer_space_size;
171
  heap_stats.old_pointer_space_size = &old_pointer_space_size;
172
  intptr_t old_pointer_space_capacity;
173
  heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
174
  intptr_t old_data_space_size;
175
  heap_stats.old_data_space_size = &old_data_space_size;
176
  intptr_t old_data_space_capacity;
177
  heap_stats.old_data_space_capacity = &old_data_space_capacity;
178
  intptr_t code_space_size;
179
  heap_stats.code_space_size = &code_space_size;
180
  intptr_t code_space_capacity;
181
  heap_stats.code_space_capacity = &code_space_capacity;
182
  intptr_t map_space_size;
183
  heap_stats.map_space_size = &map_space_size;
184
  intptr_t map_space_capacity;
185
  heap_stats.map_space_capacity = &map_space_capacity;
186
  intptr_t cell_space_size;
187
  heap_stats.cell_space_size = &cell_space_size;
188
  intptr_t cell_space_capacity;
189
  heap_stats.cell_space_capacity = &cell_space_capacity;
190
  intptr_t property_cell_space_size;
191
  heap_stats.property_cell_space_size = &property_cell_space_size;
192
  intptr_t property_cell_space_capacity;
193
  heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
194
  intptr_t lo_space_size;
195
  heap_stats.lo_space_size = &lo_space_size;
196
  int global_handle_count;
197
  heap_stats.global_handle_count = &global_handle_count;
198
  int weak_global_handle_count;
199
  heap_stats.weak_global_handle_count = &weak_global_handle_count;
200
  int pending_global_handle_count;
201
  heap_stats.pending_global_handle_count = &pending_global_handle_count;
202
  int near_death_global_handle_count;
203
  heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
204
  int free_global_handle_count;
205
  heap_stats.free_global_handle_count = &free_global_handle_count;
206
  intptr_t memory_allocator_size;
207
  heap_stats.memory_allocator_size = &memory_allocator_size;
208
  intptr_t memory_allocator_capacity;
209
  heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
210
  int objects_per_type[LAST_TYPE + 1] = {0};
211
  heap_stats.objects_per_type = objects_per_type;
212
  int size_per_type[LAST_TYPE + 1] = {0};
213
  heap_stats.size_per_type = size_per_type;
214
  int os_error;
215
  heap_stats.os_error = &os_error;
216
  int end_marker;
217
  heap_stats.end_marker = &end_marker;
218
  i::Isolate* isolate = i::Isolate::Current();
219
  if (isolate->heap()->HasBeenSetUp()) {
220
    // BUG(1718): Don't use the take_snapshot since we don't support
221
    // HeapIterator here without doing a special GC.
222
    isolate->heap()->RecordStats(&heap_stats, false);
223
  }
224
  isolate->SignalFatalError();
225
  FatalErrorCallback callback = GetFatalErrorHandler();
226
  const char* message = "Allocation failed - process out of memory";
227
  callback(location, message);
228
  // If the callback returns, we stop execution.
229
  FATAL("API fatal error handler returned after process out of memory");
230
}
231

    
232

    
233
bool Utils::ReportApiFailure(const char* location, const char* message) {
234
  FatalErrorCallback callback = GetFatalErrorHandler();
235
  callback(location, message);
236
  i::Isolate* isolate = i::Isolate::Current();
237
  isolate->SignalFatalError();
238
  return false;
239
}
240

    
241

    
242
bool V8::IsDead() {
243
  i::Isolate* isolate = i::Isolate::Current();
244
  return isolate->IsDead();
245
}
246

    
247

    
248
static inline bool ApiCheck(bool condition,
249
                            const char* location,
250
                            const char* message) {
251
  return condition ? true : Utils::ReportApiFailure(location, message);
252
}
253

    
254

    
255
static bool ReportEmptyHandle(const char* location) {
256
  FatalErrorCallback callback = GetFatalErrorHandler();
257
  callback(location, "Reading from empty handle");
258
  return true;
259
}
260

    
261

    
262
static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
263
  if (!isolate->IsInitialized()) return false;
264
  if (isolate->has_scheduled_exception()) {
265
    return isolate->scheduled_exception() ==
266
        isolate->heap()->termination_exception();
267
  }
268
  return false;
269
}
270

    
271

    
272
static inline bool EmptyCheck(const char* location, v8::Handle<v8::Data> obj) {
273
  return obj.IsEmpty() ? ReportEmptyHandle(location) : false;
274
}
275

    
276

    
277
static inline bool EmptyCheck(const char* location, const v8::Data* obj) {
278
  return (obj == 0) ? ReportEmptyHandle(location) : false;
279
}
280

    
281

    
282
// --- S t a t i c s ---
283

    
284

    
285
static bool InitializeHelper(i::Isolate* isolate) {
286
  // If the isolate has a function entry hook, it needs to re-build all its
287
  // code stubs with entry hooks embedded, so let's deserialize a snapshot.
288
  if (isolate == NULL || isolate->function_entry_hook() == NULL) {
289
    if (i::Snapshot::Initialize())
290
      return true;
291
  }
292
  return i::V8::Initialize(NULL);
293
}
294

    
295

    
296
static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
297
                                               const char* location) {
298
  if (isolate != NULL) {
299
    if (isolate->IsInitialized()) return true;
300
  }
301
  ASSERT(isolate == i::Isolate::Current());
302
  return ApiCheck(InitializeHelper(isolate), location, "Error initializing V8");
303
}
304

    
305

    
306
// Some initializing API functions are called early and may be
307
// called on a thread different from static initializer thread.
308
// If Isolate API is used, Isolate::Enter() will initialize TLS so
309
// Isolate::Current() works. If it's a legacy case, then the thread
310
// may not have TLS initialized yet. However, in initializing APIs it
311
// may be too early to call EnsureInitialized() - some pre-init
312
// parameters still have to be configured.
313
static inline i::Isolate* EnterIsolateIfNeeded() {
314
  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
315
  if (isolate != NULL)
316
    return isolate;
317

    
318
  i::Isolate::EnterDefaultIsolate();
319
  isolate = i::Isolate::Current();
320
  return isolate;
321
}
322

    
323

    
324
StartupDataDecompressor::StartupDataDecompressor()
325
    : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) {
326
  for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
327
    raw_data[i] = NULL;
328
  }
329
}
330

    
331

    
332
StartupDataDecompressor::~StartupDataDecompressor() {
333
  for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
334
    i::DeleteArray(raw_data[i]);
335
  }
336
  i::DeleteArray(raw_data);
337
}
338

    
339

    
340
int StartupDataDecompressor::Decompress() {
341
  int compressed_data_count = V8::GetCompressedStartupDataCount();
342
  StartupData* compressed_data =
343
      i::NewArray<StartupData>(compressed_data_count);
344
  V8::GetCompressedStartupData(compressed_data);
345
  for (int i = 0; i < compressed_data_count; ++i) {
346
    char* decompressed = raw_data[i] =
347
        i::NewArray<char>(compressed_data[i].raw_size);
348
    if (compressed_data[i].compressed_size != 0) {
349
      int result = DecompressData(decompressed,
350
                                  &compressed_data[i].raw_size,
351
                                  compressed_data[i].data,
352
                                  compressed_data[i].compressed_size);
353
      if (result != 0) return result;
354
    } else {
355
      ASSERT_EQ(0, compressed_data[i].raw_size);
356
    }
357
    compressed_data[i].data = decompressed;
358
  }
359
  V8::SetDecompressedStartupData(compressed_data);
360
  i::DeleteArray(compressed_data);
361
  return 0;
362
}
363

    
364

    
365
StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() {
366
#ifdef COMPRESS_STARTUP_DATA_BZ2
367
  return StartupData::kBZip2;
368
#else
369
  return StartupData::kUncompressed;
370
#endif
371
}
372

    
373

    
374
enum CompressedStartupDataItems {
375
  kSnapshot = 0,
376
  kSnapshotContext,
377
  kLibraries,
378
  kExperimentalLibraries,
379
  kCompressedStartupDataCount
380
};
381

    
382

    
383
int V8::GetCompressedStartupDataCount() {
384
#ifdef COMPRESS_STARTUP_DATA_BZ2
385
  return kCompressedStartupDataCount;
386
#else
387
  return 0;
388
#endif
389
}
390

    
391

    
392
void V8::GetCompressedStartupData(StartupData* compressed_data) {
393
#ifdef COMPRESS_STARTUP_DATA_BZ2
394
  compressed_data[kSnapshot].data =
395
      reinterpret_cast<const char*>(i::Snapshot::data());
396
  compressed_data[kSnapshot].compressed_size = i::Snapshot::size();
397
  compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size();
398

    
399
  compressed_data[kSnapshotContext].data =
400
      reinterpret_cast<const char*>(i::Snapshot::context_data());
401
  compressed_data[kSnapshotContext].compressed_size =
402
      i::Snapshot::context_size();
403
  compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size();
404

    
405
  i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource();
406
  compressed_data[kLibraries].data =
407
      reinterpret_cast<const char*>(libraries_source.start());
408
  compressed_data[kLibraries].compressed_size = libraries_source.length();
409
  compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize();
410

    
411
  i::Vector<const i::byte> exp_libraries_source =
412
      i::ExperimentalNatives::GetScriptsSource();
413
  compressed_data[kExperimentalLibraries].data =
414
      reinterpret_cast<const char*>(exp_libraries_source.start());
415
  compressed_data[kExperimentalLibraries].compressed_size =
416
      exp_libraries_source.length();
417
  compressed_data[kExperimentalLibraries].raw_size =
418
      i::ExperimentalNatives::GetRawScriptsSize();
419
#endif
420
}
421

    
422

    
423
void V8::SetDecompressedStartupData(StartupData* decompressed_data) {
424
#ifdef COMPRESS_STARTUP_DATA_BZ2
425
  ASSERT_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size);
426
  i::Snapshot::set_raw_data(
427
      reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data));
428

    
429
  ASSERT_EQ(i::Snapshot::context_raw_size(),
430
            decompressed_data[kSnapshotContext].raw_size);
431
  i::Snapshot::set_context_raw_data(
432
      reinterpret_cast<const i::byte*>(
433
          decompressed_data[kSnapshotContext].data));
434

    
435
  ASSERT_EQ(i::Natives::GetRawScriptsSize(),
436
            decompressed_data[kLibraries].raw_size);
437
  i::Vector<const char> libraries_source(
438
      decompressed_data[kLibraries].data,
439
      decompressed_data[kLibraries].raw_size);
440
  i::Natives::SetRawScriptsSource(libraries_source);
441

    
442
  ASSERT_EQ(i::ExperimentalNatives::GetRawScriptsSize(),
443
            decompressed_data[kExperimentalLibraries].raw_size);
444
  i::Vector<const char> exp_libraries_source(
445
      decompressed_data[kExperimentalLibraries].data,
446
      decompressed_data[kExperimentalLibraries].raw_size);
447
  i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
448
#endif
449
}
450

    
451

    
452
void V8::SetFatalErrorHandler(FatalErrorCallback that) {
453
  i::Isolate* isolate = EnterIsolateIfNeeded();
454
  isolate->set_exception_behavior(that);
455
}
456

    
457

    
458
void V8::SetAllowCodeGenerationFromStringsCallback(
459
    AllowCodeGenerationFromStringsCallback callback) {
460
  i::Isolate* isolate = EnterIsolateIfNeeded();
461
  isolate->set_allow_code_gen_callback(callback);
462
}
463

    
464

    
465
void V8::SetFlagsFromString(const char* str, int length) {
466
  i::FlagList::SetFlagsFromString(str, length);
467
}
468

    
469

    
470
void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
471
  i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
472
}
473

    
474

    
475
v8::Handle<Value> ThrowException(v8::Handle<v8::Value> value) {
476
  return v8::Isolate::GetCurrent()->ThrowException(value);
477
}
478

    
479

    
480
RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
481

    
482

    
483
RegisteredExtension::RegisteredExtension(Extension* extension)
484
    : extension_(extension) { }
485

    
486

    
487
void RegisteredExtension::Register(RegisteredExtension* that) {
488
  that->next_ = first_extension_;
489
  first_extension_ = that;
490
}
491

    
492

    
493
void RegisteredExtension::UnregisterAll() {
494
  RegisteredExtension* re = first_extension_;
495
  while (re != NULL) {
496
    RegisteredExtension* next = re->next();
497
    delete re;
498
    re = next;
499
  }
500
}
501

    
502

    
503
void RegisterExtension(Extension* that) {
504
  RegisteredExtension* extension = new RegisteredExtension(that);
505
  RegisteredExtension::Register(extension);
506
}
507

    
508

    
509
Extension::Extension(const char* name,
510
                     const char* source,
511
                     int dep_count,
512
                     const char** deps,
513
                     int source_length)
514
    : name_(name),
515
      source_length_(source_length >= 0 ?
516
                     source_length :
517
                     (source ? static_cast<int>(strlen(source)) : 0)),
518
      source_(source, source_length_),
519
      dep_count_(dep_count),
520
      deps_(deps),
521
      auto_enable_(false) {
522
  CHECK(source != NULL || source_length_ == 0);
523
}
524

    
525

    
526
v8::Handle<Primitive> Undefined() {
527
  i::Isolate* isolate = i::Isolate::Current();
528
  if (!EnsureInitializedForIsolate(isolate, "v8::Undefined()")) {
529
    return v8::Handle<v8::Primitive>();
530
  }
531
  return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
532
}
533

    
534

    
535
v8::Handle<Primitive> Null() {
536
  i::Isolate* isolate = i::Isolate::Current();
537
  if (!EnsureInitializedForIsolate(isolate, "v8::Null()")) {
538
    return v8::Handle<v8::Primitive>();
539
  }
540
  return ToApiHandle<Primitive>(isolate->factory()->null_value());
541
}
542

    
543

    
544
v8::Handle<Boolean> True() {
545
  i::Isolate* isolate = i::Isolate::Current();
546
  if (!EnsureInitializedForIsolate(isolate, "v8::True()")) {
547
    return v8::Handle<Boolean>();
548
  }
549
  return ToApiHandle<Boolean>(isolate->factory()->true_value());
550
}
551

    
552

    
553
v8::Handle<Boolean> False() {
554
  i::Isolate* isolate = i::Isolate::Current();
555
  if (!EnsureInitializedForIsolate(isolate, "v8::False()")) {
556
    return v8::Handle<Boolean>();
557
  }
558
  return ToApiHandle<Boolean>(isolate->factory()->false_value());
559
}
560

    
561

    
562
ResourceConstraints::ResourceConstraints()
563
  : max_young_space_size_(0),
564
    max_old_space_size_(0),
565
    max_executable_size_(0),
566
    stack_limit_(NULL) { }
567

    
568

    
569
bool SetResourceConstraints(ResourceConstraints* constraints) {
570
  i::Isolate* isolate = EnterIsolateIfNeeded();
571

    
572
  int young_space_size = constraints->max_young_space_size();
573
  int old_gen_size = constraints->max_old_space_size();
574
  int max_executable_size = constraints->max_executable_size();
575
  if (young_space_size != 0 || old_gen_size != 0 || max_executable_size != 0) {
576
    // After initialization it's too late to change Heap constraints.
577
    // TODO(rmcilroy): fix this assert.
578
    // ASSERT(!isolate->IsInitialized());
579
    bool result = isolate->heap()->ConfigureHeap(young_space_size / 2,
580
                                                 old_gen_size,
581
                                                 max_executable_size);
582
    if (!result) return false;
583
  }
584
  if (constraints->stack_limit() != NULL) {
585
    uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
586
    isolate->stack_guard()->SetStackLimit(limit);
587
  }
588
  return true;
589
}
590

    
591

    
592
i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) {
593
  LOG_API(isolate, "Persistent::New");
594
  i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
595
#ifdef DEBUG
596
  (*obj)->Verify();
597
#endif  // DEBUG
598
  return result.location();
599
}
600

    
601

    
602
i::Object** V8::CopyPersistent(i::Object** obj) {
603
  i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj);
604
#ifdef DEBUG
605
  (*obj)->Verify();
606
#endif  // DEBUG
607
  return result.location();
608
}
609

    
610

    
611
void V8::MakeWeak(i::Object** object,
612
                  void* parameters,
613
                  WeakCallback weak_callback,
614
                  RevivableCallback weak_reference_callback) {
615
  i::GlobalHandles::MakeWeak(object,
616
                             parameters,
617
                             weak_callback,
618
                             weak_reference_callback);
619
}
620

    
621

    
622
void V8::ClearWeak(i::Object** obj) {
623
  i::GlobalHandles::ClearWeakness(obj);
624
}
625

    
626

    
627
void V8::DisposeGlobal(i::Object** obj) {
628
  i::GlobalHandles::Destroy(obj);
629
}
630

    
631

    
632
void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
633
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
634
  i::Object* object = *Utils::OpenHandle(value);
635
  isolate->eternal_handles()->Create(isolate, object, index);
636
}
637

    
638

    
639
Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
640
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
641
  return Utils::ToLocal(isolate->eternal_handles()->Get(index));
642
}
643

    
644

    
645
// --- H a n d l e s ---
646

    
647

    
648
HandleScope::HandleScope(Isolate* isolate) {
649
  Initialize(isolate);
650
}
651

    
652

    
653
void HandleScope::Initialize(Isolate* isolate) {
654
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
655
  API_ENTRY_CHECK(internal_isolate, "HandleScope::HandleScope");
656
  v8::ImplementationUtilities::HandleScopeData* current =
657
      internal_isolate->handle_scope_data();
658
  isolate_ = internal_isolate;
659
  prev_next_ = current->next;
660
  prev_limit_ = current->limit;
661
  is_closed_ = false;
662
  current->level++;
663
}
664

    
665

    
666
HandleScope::~HandleScope() {
667
  if (!is_closed_) {
668
    Leave();
669
  }
670
}
671

    
672

    
673
void HandleScope::Leave() {
674
  return i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
675
}
676

    
677

    
678
int HandleScope::NumberOfHandles() {
679
  i::Isolate* isolate = i::Isolate::Current();
680
  if (!EnsureInitializedForIsolate(isolate, "HandleScope::NumberOfHandles")) {
681
    return 0;
682
  }
683
  return i::HandleScope::NumberOfHandles(isolate);
684
}
685

    
686

    
687
i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
688
  return i::HandleScope::CreateHandle(isolate, value);
689
}
690

    
691

    
692
i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object,
693
                                      i::Object* value) {
694
  ASSERT(heap_object->IsHeapObject());
695
  return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value);
696
}
697

    
698

    
699
EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
700
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
701
  escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
702
  Initialize(v8_isolate);
703
}
704

    
705

    
706
i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
707
  ApiCheck(*escape_slot_ == isolate_->heap()->the_hole_value(),
708
           "EscapeableHandleScope::Escape",
709
           "Escape value set twice");
710
  if (escape_value == NULL) {
711
    *escape_slot_ = isolate_->heap()->undefined_value();
712
    return NULL;
713
  }
714
  *escape_slot_ = *escape_value;
715
  return escape_slot_;
716
}
717

    
718

    
719
void Context::Enter() {
720
  i::Handle<i::Context> env = Utils::OpenHandle(this);
721
  i::Isolate* isolate = env->GetIsolate();
722
  ENTER_V8(isolate);
723
  isolate->handle_scope_implementer()->EnterContext(env);
724
  isolate->handle_scope_implementer()->SaveContext(isolate->context());
725
  isolate->set_context(*env);
726
}
727

    
728

    
729
void Context::Exit() {
730
  // TODO(dcarney): fix this once chrome is fixed.
731
  i::Isolate* isolate = i::Isolate::Current();
732
  i::Handle<i::Context> context = i::Handle<i::Context>::null();
733
  ENTER_V8(isolate);
734
  if (!ApiCheck(isolate->handle_scope_implementer()->LeaveContext(context),
735
                "v8::Context::Exit()",
736
                "Cannot exit non-entered context")) {
737
    return;
738
  }
739
  // Content of 'last_context' could be NULL.
740
  i::Context* last_context =
741
      isolate->handle_scope_implementer()->RestoreContext();
742
  isolate->set_context(last_context);
743
}
744

    
745

    
746
static void* DecodeSmiToAligned(i::Object* value, const char* location) {
747
  ApiCheck(value->IsSmi(), location, "Not a Smi");
748
  return reinterpret_cast<void*>(value);
749
}
750

    
751

    
752
static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
753
  i::Smi* smi = reinterpret_cast<i::Smi*>(value);
754
  ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
755
  return smi;
756
}
757

    
758

    
759
static i::Handle<i::FixedArray> EmbedderDataFor(Context* context,
760
                                                int index,
761
                                                bool can_grow,
762
                                                const char* location) {
763
  i::Handle<i::Context> env = Utils::OpenHandle(context);
764
  bool ok =
765
      ApiCheck(env->IsNativeContext(), location, "Not a native context") &&
766
      ApiCheck(index >= 0, location, "Negative index");
767
  if (!ok) return i::Handle<i::FixedArray>();
768
  i::Handle<i::FixedArray> data(env->embedder_data());
769
  if (index < data->length()) return data;
770
  if (!can_grow) {
771
    Utils::ReportApiFailure(location, "Index too large");
772
    return i::Handle<i::FixedArray>();
773
  }
774
  int new_size = i::Max(index, data->length() << 1) + 1;
775
  data = env->GetIsolate()->factory()->CopySizeFixedArray(data, new_size);
776
  env->set_embedder_data(*data);
777
  return data;
778
}
779

    
780

    
781
v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
782
  const char* location = "v8::Context::GetEmbedderData()";
783
  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
784
  if (data.is_null()) return Local<Value>();
785
  i::Handle<i::Object> result(data->get(index), data->GetIsolate());
786
  return Utils::ToLocal(result);
787
}
788

    
789

    
790
void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
791
  const char* location = "v8::Context::SetEmbedderData()";
792
  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
793
  if (data.is_null()) return;
794
  i::Handle<i::Object> val = Utils::OpenHandle(*value);
795
  data->set(index, *val);
796
  ASSERT_EQ(*Utils::OpenHandle(*value),
797
            *Utils::OpenHandle(*GetEmbedderData(index)));
798
}
799

    
800

    
801
void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
802
  const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
803
  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
804
  if (data.is_null()) return NULL;
805
  return DecodeSmiToAligned(data->get(index), location);
806
}
807

    
808

    
809
void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
810
  const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
811
  i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
812
  data->set(index, EncodeAlignedAsSmi(value, location));
813
  ASSERT_EQ(value, GetAlignedPointerFromEmbedderData(index));
814
}
815

    
816

    
817
i::Object** v8::HandleScope::RawClose(i::Object** value) {
818
  if (!ApiCheck(!is_closed_,
819
                "v8::HandleScope::Close()",
820
                "Local scope has already been closed")) {
821
    return 0;
822
  }
823
  LOG_API(isolate_, "CloseHandleScope");
824

    
825
  // Read the result before popping the handle block.
826
  i::Object* result = NULL;
827
  if (value != NULL) {
828
    result = *value;
829
  }
830
  is_closed_ = true;
831
  Leave();
832

    
833
  if (value == NULL) {
834
    return NULL;
835
  }
836

    
837
  // Allocate a new handle on the previous handle block.
838
  i::Handle<i::Object> handle(result, isolate_);
839
  return handle.location();
840
}
841

    
842

    
843
// --- N e a n d e r ---
844

    
845

    
846
// A constructor cannot easily return an error value, therefore it is necessary
847
// to check for a dead VM with ON_BAILOUT before constructing any Neander
848
// objects.  To remind you about this there is no HandleScope in the
849
// NeanderObject constructor.  When you add one to the site calling the
850
// constructor you should check that you ensured the VM was not dead first.
851
NeanderObject::NeanderObject(int size) {
852
  i::Isolate* isolate = i::Isolate::Current();
853
  EnsureInitializedForIsolate(isolate, "v8::Nowhere");
854
  ENTER_V8(isolate);
855
  value_ = isolate->factory()->NewNeanderObject();
856
  i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
857
  value_->set_elements(*elements);
858
}
859

    
860

    
861
int NeanderObject::size() {
862
  return i::FixedArray::cast(value_->elements())->length();
863
}
864

    
865

    
866
NeanderArray::NeanderArray() : obj_(2) {
867
  obj_.set(0, i::Smi::FromInt(0));
868
}
869

    
870

    
871
int NeanderArray::length() {
872
  return i::Smi::cast(obj_.get(0))->value();
873
}
874

    
875

    
876
i::Object* NeanderArray::get(int offset) {
877
  ASSERT(0 <= offset);
878
  ASSERT(offset < length());
879
  return obj_.get(offset + 1);
880
}
881

    
882

    
883
// This method cannot easily return an error value, therefore it is necessary
884
// to check for a dead VM with ON_BAILOUT before calling it.  To remind you
885
// about this there is no HandleScope in this method.  When you add one to the
886
// site calling this method you should check that you ensured the VM was not
887
// dead first.
888
void NeanderArray::add(i::Handle<i::Object> value) {
889
  int length = this->length();
890
  int size = obj_.size();
891
  if (length == size - 1) {
892
    i::Factory* factory = i::Isolate::Current()->factory();
893
    i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size);
894
    for (int i = 0; i < length; i++)
895
      new_elms->set(i + 1, get(i));
896
    obj_.value()->set_elements(*new_elms);
897
  }
898
  obj_.set(length + 1, *value);
899
  obj_.set(0, i::Smi::FromInt(length + 1));
900
}
901

    
902

    
903
void NeanderArray::set(int index, i::Object* value) {
904
  if (index < 0 || index >= this->length()) return;
905
  obj_.set(index + 1, value);
906
}
907

    
908

    
909
// --- T e m p l a t e ---
910

    
911

    
912
static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
913
  that->set_tag(i::Smi::FromInt(type));
914
}
915

    
916

    
917
static void TemplateSet(i::Isolate* isolate,
918
                        v8::Template* templ,
919
                        int length,
920
                        v8::Handle<v8::Data>* data) {
921
  i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
922
  if (list->IsUndefined()) {
923
    list = NeanderArray().value();
924
    Utils::OpenHandle(templ)->set_property_list(*list);
925
  }
926
  NeanderArray array(list);
927
  array.add(Utils::OpenHandle(*v8::Integer::New(length)));
928
  for (int i = 0; i < length; i++) {
929
    i::Handle<i::Object> value = data[i].IsEmpty() ?
930
        i::Handle<i::Object>(isolate->factory()->undefined_value()) :
931
        Utils::OpenHandle(*data[i]);
932
    array.add(value);
933
  }
934
}
935

    
936

    
937
void Template::Set(v8::Handle<String> name,
938
                   v8::Handle<Data> value,
939
                   v8::PropertyAttribute attribute) {
940
  i::Isolate* isolate = i::Isolate::Current();
941
  ENTER_V8(isolate);
942
  i::HandleScope scope(isolate);
943
  const int kSize = 3;
944
  v8::Handle<v8::Data> data[kSize] = {
945
      name,
946
      value,
947
      v8::Integer::New(attribute)};
948
  TemplateSet(isolate, this, kSize, data);
949
}
950

    
951

    
952
void Template::SetAccessorProperty(
953
    v8::Local<v8::String> name,
954
    v8::Local<FunctionTemplate> getter,
955
    v8::Local<FunctionTemplate> setter,
956
    v8::PropertyAttribute attribute,
957
    v8::AccessControl access_control) {
958
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
959
  ENTER_V8(isolate);
960
  ASSERT(!name.IsEmpty());
961
  ASSERT(!getter.IsEmpty() || !setter.IsEmpty());
962
  i::HandleScope scope(isolate);
963
  const int kSize = 5;
964
  v8::Handle<v8::Data> data[kSize] = {
965
      name,
966
      getter,
967
      setter,
968
      v8::Integer::New(attribute),
969
      v8::Integer::New(access_control)};
970
  TemplateSet(isolate, this, kSize, data);
971
}
972

    
973

    
974
// --- F u n c t i o n   T e m p l a t e ---
975
static void InitializeFunctionTemplate(
976
      i::Handle<i::FunctionTemplateInfo> info) {
977
  info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
978
  info->set_flag(0);
979
}
980

    
981

    
982
Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
983
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
984
  ENTER_V8(isolate);
985
  i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(),
986
                              isolate);
987
  if (result->IsUndefined()) {
988
    result = Utils::OpenHandle(*ObjectTemplate::New());
989
    Utils::OpenHandle(this)->set_prototype_template(*result);
990
  }
991
  return ToApiHandle<ObjectTemplate>(result);
992
}
993

    
994

    
995
void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
996
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
997
  ENTER_V8(isolate);
998
  Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
999
}
1000

    
1001

    
1002
static Local<FunctionTemplate> FunctionTemplateNew(
1003
    i::Isolate* isolate,
1004
    FunctionCallback callback,
1005
    v8::Handle<Value> data,
1006
    v8::Handle<Signature> signature,
1007
    int length,
1008
    bool do_not_cache) {
1009
  i::Handle<i::Struct> struct_obj =
1010
      isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
1011
  i::Handle<i::FunctionTemplateInfo> obj =
1012
      i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
1013
  InitializeFunctionTemplate(obj);
1014
  obj->set_do_not_cache(do_not_cache);
1015
  int next_serial_number = 0;
1016
  if (!do_not_cache) {
1017
    next_serial_number = isolate->next_serial_number() + 1;
1018
    isolate->set_next_serial_number(next_serial_number);
1019
  }
1020
  obj->set_serial_number(i::Smi::FromInt(next_serial_number));
1021
  if (callback != 0) {
1022
    if (data.IsEmpty()) {
1023
      data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1024
    }
1025
    Utils::ToLocal(obj)->SetCallHandler(callback, data);
1026
  }
1027
  obj->set_length(length);
1028
  obj->set_undetectable(false);
1029
  obj->set_needs_access_check(false);
1030
  if (!signature.IsEmpty())
1031
    obj->set_signature(*Utils::OpenHandle(*signature));
1032
  return Utils::ToLocal(obj);
1033
}
1034

    
1035
Local<FunctionTemplate> FunctionTemplate::New(
1036
    FunctionCallback callback,
1037
    v8::Handle<Value> data,
1038
    v8::Handle<Signature> signature,
1039
    int length) {
1040
  i::Isolate* isolate = i::Isolate::Current();
1041
  EnsureInitializedForIsolate(isolate, "v8::FunctionTemplate::New()");
1042
  LOG_API(isolate, "FunctionTemplate::New");
1043
  ENTER_V8(isolate);
1044
  return FunctionTemplateNew(
1045
      isolate, callback, data, signature, length, false);
1046
}
1047

    
1048

    
1049
Local<Signature> Signature::New(Handle<FunctionTemplate> receiver,
1050
      int argc, Handle<FunctionTemplate> argv[]) {
1051
  i::Isolate* isolate = i::Isolate::Current();
1052
  EnsureInitializedForIsolate(isolate, "v8::Signature::New()");
1053
  LOG_API(isolate, "Signature::New");
1054
  ENTER_V8(isolate);
1055
  i::Handle<i::Struct> struct_obj =
1056
      isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
1057
  i::Handle<i::SignatureInfo> obj =
1058
      i::Handle<i::SignatureInfo>::cast(struct_obj);
1059
  if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
1060
  if (argc > 0) {
1061
    i::Handle<i::FixedArray> args = isolate->factory()->NewFixedArray(argc);
1062
    for (int i = 0; i < argc; i++) {
1063
      if (!argv[i].IsEmpty())
1064
        args->set(i, *Utils::OpenHandle(*argv[i]));
1065
    }
1066
    obj->set_args(*args);
1067
  }
1068
  return Utils::ToLocal(obj);
1069
}
1070

    
1071

    
1072
Local<AccessorSignature> AccessorSignature::New(
1073
      Handle<FunctionTemplate> receiver) {
1074
  return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
1075
}
1076

    
1077

    
1078
template<typename Operation>
1079
static Local<Operation> NewDescriptor(
1080
    Isolate* isolate,
1081
    const i::DeclaredAccessorDescriptorData& data,
1082
    Data* previous_descriptor) {
1083
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
1084
  i::Handle<i::DeclaredAccessorDescriptor> previous =
1085
      i::Handle<i::DeclaredAccessorDescriptor>();
1086
  if (previous_descriptor != NULL) {
1087
    previous = Utils::OpenHandle(
1088
      static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
1089
  }
1090
  i::Handle<i::DeclaredAccessorDescriptor> descriptor =
1091
      i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
1092
  return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor);
1093
}
1094

    
1095

    
1096
Local<RawOperationDescriptor>
1097
  ObjectOperationDescriptor::NewInternalFieldDereference(
1098
    Isolate* isolate,
1099
    int internal_field) {
1100
  i::DeclaredAccessorDescriptorData data;
1101
  data.type = i::kDescriptorObjectDereference;
1102
  data.object_dereference_descriptor.internal_field = internal_field;
1103
  return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
1104
}
1105

    
1106

    
1107
Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
1108
    Isolate* isolate,
1109
    int16_t byte_offset) {
1110
  i::DeclaredAccessorDescriptorData data;
1111
  data.type = i::kDescriptorPointerShift;
1112
  data.pointer_shift_descriptor.byte_offset = byte_offset;
1113
  return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1114
}
1115

    
1116

    
1117
Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
1118
    Isolate* isolate) {
1119
  i::DeclaredAccessorDescriptorData data;
1120
  data.type = i::kDescriptorReturnObject;
1121
  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1122
}
1123

    
1124

    
1125
Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
1126
    Isolate* isolate) {
1127
  i::DeclaredAccessorDescriptorData data;
1128
  data.type = i::kDescriptorPointerDereference;
1129
  return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1130
}
1131

    
1132

    
1133
Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
1134
    Isolate* isolate,
1135
    void* compare_value) {
1136
  i::DeclaredAccessorDescriptorData data;
1137
  data.type = i::kDescriptorPointerCompare;
1138
  data.pointer_compare_descriptor.compare_value = compare_value;
1139
  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1140
}
1141

    
1142

    
1143
Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
1144
    Isolate* isolate,
1145
    DeclaredAccessorDescriptorDataType data_type,
1146
    uint8_t bool_offset) {
1147
  i::DeclaredAccessorDescriptorData data;
1148
  data.type = i::kDescriptorPrimitiveValue;
1149
  data.primitive_value_descriptor.data_type = data_type;
1150
  data.primitive_value_descriptor.bool_offset = bool_offset;
1151
  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1152
}
1153

    
1154

    
1155
template<typename T>
1156
static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
1157
    Isolate* isolate,
1158
    T bitmask,
1159
    T compare_value,
1160
    RawOperationDescriptor* operation) {
1161
  i::DeclaredAccessorDescriptorData data;
1162
  data.type = i::kDescriptorBitmaskCompare;
1163
  data.bitmask_compare_descriptor.bitmask = bitmask;
1164
  data.bitmask_compare_descriptor.compare_value = compare_value;
1165
  data.bitmask_compare_descriptor.size = sizeof(T);
1166
  return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
1167
}
1168

    
1169

    
1170
Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
1171
    Isolate* isolate,
1172
    uint8_t bitmask,
1173
    uint8_t compare_value) {
1174
  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1175
}
1176

    
1177

    
1178
Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
1179
    Isolate* isolate,
1180
    uint16_t bitmask,
1181
    uint16_t compare_value) {
1182
  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1183
}
1184

    
1185

    
1186
Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
1187
    Isolate* isolate,
1188
    uint32_t bitmask,
1189
    uint32_t compare_value) {
1190
  return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1191
}
1192

    
1193

    
1194
Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
1195
  Handle<FunctionTemplate> types[1] = { type };
1196
  return TypeSwitch::New(1, types);
1197
}
1198

    
1199

    
1200
Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
1201
  i::Isolate* isolate = i::Isolate::Current();
1202
  EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()");
1203
  LOG_API(isolate, "TypeSwitch::New");
1204
  ENTER_V8(isolate);
1205
  i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
1206
  for (int i = 0; i < argc; i++)
1207
    vector->set(i, *Utils::OpenHandle(*types[i]));
1208
  i::Handle<i::Struct> struct_obj =
1209
      isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
1210
  i::Handle<i::TypeSwitchInfo> obj =
1211
      i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
1212
  obj->set_types(*vector);
1213
  return Utils::ToLocal(obj);
1214
}
1215

    
1216

    
1217
int TypeSwitch::match(v8::Handle<Value> value) {
1218
  i::Isolate* isolate = i::Isolate::Current();
1219
  LOG_API(isolate, "TypeSwitch::match");
1220
  USE(isolate);
1221
  i::Handle<i::Object> obj = Utils::OpenHandle(*value);
1222
  i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
1223
  i::FixedArray* types = i::FixedArray::cast(info->types());
1224
  for (int i = 0; i < types->length(); i++) {
1225
    if (obj->IsInstanceOf(i::FunctionTemplateInfo::cast(types->get(i))))
1226
      return i + 1;
1227
  }
1228
  return 0;
1229
}
1230

    
1231

    
1232
#define SET_FIELD_WRAPPED(obj, setter, cdata) do {    \
1233
    i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata);  \
1234
    (obj)->setter(*foreign);                          \
1235
  } while (false)
1236

    
1237

    
1238
void FunctionTemplate::SetCallHandler(FunctionCallback callback,
1239
                                      v8::Handle<Value> data) {
1240
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1241
  ENTER_V8(isolate);
1242
  i::HandleScope scope(isolate);
1243
  i::Handle<i::Struct> struct_obj =
1244
      isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1245
  i::Handle<i::CallHandlerInfo> obj =
1246
      i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1247
  SET_FIELD_WRAPPED(obj, set_callback, callback);
1248
  if (data.IsEmpty()) {
1249
    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1250
  }
1251
  obj->set_data(*Utils::OpenHandle(*data));
1252
  Utils::OpenHandle(this)->set_call_code(*obj);
1253
}
1254

    
1255

    
1256
static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
1257
    i::Handle<i::AccessorInfo> obj,
1258
    v8::Handle<String> name,
1259
    v8::AccessControl settings,
1260
    v8::PropertyAttribute attributes,
1261
    v8::Handle<AccessorSignature> signature) {
1262
  obj->set_name(*Utils::OpenHandle(*name));
1263
  if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1264
  if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1265
  if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true);
1266
  obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
1267
  if (!signature.IsEmpty()) {
1268
    obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1269
  }
1270
  return obj;
1271
}
1272

    
1273

    
1274
template<typename Getter, typename Setter>
1275
static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1276
      v8::Handle<String> name,
1277
      Getter getter,
1278
      Setter setter,
1279
      v8::Handle<Value> data,
1280
      v8::AccessControl settings,
1281
      v8::PropertyAttribute attributes,
1282
      v8::Handle<AccessorSignature> signature) {
1283
  i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1284
  i::Handle<i::ExecutableAccessorInfo> obj =
1285
      isolate->factory()->NewExecutableAccessorInfo();
1286
  SET_FIELD_WRAPPED(obj, set_getter, getter);
1287
  SET_FIELD_WRAPPED(obj, set_setter, setter);
1288
  if (data.IsEmpty()) {
1289
    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1290
  }
1291
  obj->set_data(*Utils::OpenHandle(*data));
1292
  return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1293
}
1294

    
1295

    
1296
static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1297
      v8::Handle<String> name,
1298
      v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
1299
      void* setter_ignored,
1300
      void* data_ignored,
1301
      v8::AccessControl settings,
1302
      v8::PropertyAttribute attributes,
1303
      v8::Handle<AccessorSignature> signature) {
1304
  i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1305
  if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
1306
  i::Handle<i::DeclaredAccessorInfo> obj =
1307
      isolate->factory()->NewDeclaredAccessorInfo();
1308
  obj->set_descriptor(*Utils::OpenHandle(*descriptor));
1309
  return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1310
}
1311

    
1312

    
1313
Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1314
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1315
  if (EmptyCheck("v8::FunctionTemplate::InstanceTemplate()", this))
1316
    return Local<ObjectTemplate>();
1317
  ENTER_V8(isolate);
1318
  i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this);
1319
  if (handle->instance_template()->IsUndefined()) {
1320
    Local<ObjectTemplate> templ =
1321
        ObjectTemplate::New(ToApiHandle<FunctionTemplate>(handle));
1322
    handle->set_instance_template(*Utils::OpenHandle(*templ));
1323
  }
1324
  i::Handle<i::ObjectTemplateInfo> result(
1325
      i::ObjectTemplateInfo::cast(handle->instance_template()));
1326
  return Utils::ToLocal(result);
1327
}
1328

    
1329

    
1330
void FunctionTemplate::SetLength(int length) {
1331
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1332
  ENTER_V8(isolate);
1333
  Utils::OpenHandle(this)->set_length(length);
1334
}
1335

    
1336

    
1337
void FunctionTemplate::SetClassName(Handle<String> name) {
1338
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1339
  ENTER_V8(isolate);
1340
  Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
1341
}
1342

    
1343

    
1344
void FunctionTemplate::SetHiddenPrototype(bool value) {
1345
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1346
  ENTER_V8(isolate);
1347
  Utils::OpenHandle(this)->set_hidden_prototype(value);
1348
}
1349

    
1350

    
1351
void FunctionTemplate::ReadOnlyPrototype() {
1352
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1353
  ENTER_V8(isolate);
1354
  Utils::OpenHandle(this)->set_read_only_prototype(true);
1355
}
1356

    
1357

    
1358
void FunctionTemplate::RemovePrototype() {
1359
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1360
  ENTER_V8(isolate);
1361
  Utils::OpenHandle(this)->set_remove_prototype(true);
1362
}
1363

    
1364

    
1365
// --- O b j e c t T e m p l a t e ---
1366

    
1367

    
1368
Local<ObjectTemplate> ObjectTemplate::New() {
1369
  return New(Local<FunctionTemplate>());
1370
}
1371

    
1372

    
1373
Local<ObjectTemplate> ObjectTemplate::New(
1374
      v8::Handle<FunctionTemplate> constructor) {
1375
  i::Isolate* isolate = i::Isolate::Current();
1376
  EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
1377
  LOG_API(isolate, "ObjectTemplate::New");
1378
  ENTER_V8(isolate);
1379
  i::Handle<i::Struct> struct_obj =
1380
      isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
1381
  i::Handle<i::ObjectTemplateInfo> obj =
1382
      i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1383
  InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1384
  if (!constructor.IsEmpty())
1385
    obj->set_constructor(*Utils::OpenHandle(*constructor));
1386
  obj->set_internal_field_count(i::Smi::FromInt(0));
1387
  return Utils::ToLocal(obj);
1388
}
1389

    
1390

    
1391
// Ensure that the object template has a constructor.  If no
1392
// constructor is available we create one.
1393
static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1394
    ObjectTemplate* object_template) {
1395
  i::Object* obj = Utils::OpenHandle(object_template)->constructor();
1396
  if (!obj ->IsUndefined()) {
1397
    i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
1398
    return i::Handle<i::FunctionTemplateInfo>(info, info->GetIsolate());
1399
  }
1400
  Local<FunctionTemplate> templ = FunctionTemplate::New();
1401
  i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1402
  constructor->set_instance_template(*Utils::OpenHandle(object_template));
1403
  Utils::OpenHandle(object_template)->set_constructor(*constructor);
1404
  return constructor;
1405
}
1406

    
1407

    
1408
static inline void AddPropertyToTemplate(
1409
    i::Handle<i::TemplateInfo> info,
1410
    i::Handle<i::AccessorInfo> obj) {
1411
  i::Handle<i::Object> list(info->property_accessors(), info->GetIsolate());
1412
  if (list->IsUndefined()) {
1413
    list = NeanderArray().value();
1414
    info->set_property_accessors(*list);
1415
  }
1416
  NeanderArray array(list);
1417
  array.add(obj);
1418
}
1419

    
1420

    
1421
static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1422
    Template* template_obj) {
1423
  return Utils::OpenHandle(template_obj);
1424
}
1425

    
1426

    
1427
// TODO(dcarney): remove this with ObjectTemplate::SetAccessor
1428
static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1429
    ObjectTemplate* object_template) {
1430
  EnsureConstructor(object_template);
1431
  return Utils::OpenHandle(object_template);
1432
}
1433

    
1434

    
1435
template<typename Setter, typename Getter, typename Data, typename Template>
1436
static bool TemplateSetAccessor(
1437
    Template* template_obj,
1438
    v8::Local<String> name,
1439
    Getter getter,
1440
    Setter setter,
1441
    Data data,
1442
    AccessControl settings,
1443
    PropertyAttribute attribute,
1444
    v8::Local<AccessorSignature> signature) {
1445
  i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
1446
  ENTER_V8(isolate);
1447
  i::HandleScope scope(isolate);
1448
  i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
1449
      name, getter, setter, data, settings, attribute, signature);
1450
  if (obj.is_null()) return false;
1451
  i::Handle<i::TemplateInfo> info = GetTemplateInfo(template_obj);
1452
  AddPropertyToTemplate(info, obj);
1453
  return true;
1454
}
1455

    
1456

    
1457
bool Template::SetDeclaredAccessor(
1458
    Local<String> name,
1459
    Local<DeclaredAccessorDescriptor> descriptor,
1460
    PropertyAttribute attribute,
1461
    Local<AccessorSignature> signature,
1462
    AccessControl settings) {
1463
  void* null = NULL;
1464
  return TemplateSetAccessor(
1465
      this, name, descriptor, null, null, settings, attribute, signature);
1466
}
1467

    
1468

    
1469
void Template::SetNativeDataProperty(v8::Local<String> name,
1470
                                     AccessorGetterCallback getter,
1471
                                     AccessorSetterCallback setter,
1472
                                     v8::Handle<Value> data,
1473
                                     PropertyAttribute attribute,
1474
                                     v8::Local<AccessorSignature> signature,
1475
                                     AccessControl settings) {
1476
  TemplateSetAccessor(
1477
      this, name, getter, setter, data, settings, attribute, signature);
1478
}
1479

    
1480

    
1481
void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1482
                                 AccessorGetterCallback getter,
1483
                                 AccessorSetterCallback setter,
1484
                                 v8::Handle<Value> data,
1485
                                 AccessControl settings,
1486
                                 PropertyAttribute attribute,
1487
                                 v8::Handle<AccessorSignature> signature) {
1488
  TemplateSetAccessor(
1489
      this, name, getter, setter, data, settings, attribute, signature);
1490
}
1491

    
1492

    
1493
void ObjectTemplate::SetNamedPropertyHandler(
1494
    NamedPropertyGetterCallback getter,
1495
    NamedPropertySetterCallback setter,
1496
    NamedPropertyQueryCallback query,
1497
    NamedPropertyDeleterCallback remover,
1498
    NamedPropertyEnumeratorCallback enumerator,
1499
    Handle<Value> data) {
1500
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1501
  ENTER_V8(isolate);
1502
  i::HandleScope scope(isolate);
1503
  EnsureConstructor(this);
1504
  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1505
      Utils::OpenHandle(this)->constructor());
1506
  i::Handle<i::FunctionTemplateInfo> cons(constructor);
1507
  i::Handle<i::Struct> struct_obj =
1508
      isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1509
  i::Handle<i::InterceptorInfo> obj =
1510
      i::Handle<i::InterceptorInfo>::cast(struct_obj);
1511

    
1512
  if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1513
  if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1514
  if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1515
  if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1516
  if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1517

    
1518
  if (data.IsEmpty()) {
1519
    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1520
  }
1521
  obj->set_data(*Utils::OpenHandle(*data));
1522
  cons->set_named_property_handler(*obj);
1523
}
1524

    
1525

    
1526
void ObjectTemplate::MarkAsUndetectable() {
1527
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1528
  ENTER_V8(isolate);
1529
  i::HandleScope scope(isolate);
1530
  EnsureConstructor(this);
1531
  i::FunctionTemplateInfo* constructor =
1532
      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1533
  i::Handle<i::FunctionTemplateInfo> cons(constructor);
1534
  cons->set_undetectable(true);
1535
}
1536

    
1537

    
1538
void ObjectTemplate::SetAccessCheckCallbacks(
1539
      NamedSecurityCallback named_callback,
1540
      IndexedSecurityCallback indexed_callback,
1541
      Handle<Value> data,
1542
      bool turned_on_by_default) {
1543
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1544
  ENTER_V8(isolate);
1545
  i::HandleScope scope(isolate);
1546
  EnsureConstructor(this);
1547

    
1548
  i::Handle<i::Struct> struct_info =
1549
      isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1550
  i::Handle<i::AccessCheckInfo> info =
1551
      i::Handle<i::AccessCheckInfo>::cast(struct_info);
1552

    
1553
  SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1554
  SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1555

    
1556
  if (data.IsEmpty()) {
1557
    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1558
  }
1559
  info->set_data(*Utils::OpenHandle(*data));
1560

    
1561
  i::FunctionTemplateInfo* constructor =
1562
      i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1563
  i::Handle<i::FunctionTemplateInfo> cons(constructor);
1564
  cons->set_access_check_info(*info);
1565
  cons->set_needs_access_check(turned_on_by_default);
1566
}
1567

    
1568

    
1569
void ObjectTemplate::SetIndexedPropertyHandler(
1570
      IndexedPropertyGetterCallback getter,
1571
      IndexedPropertySetterCallback setter,
1572
      IndexedPropertyQueryCallback query,
1573
      IndexedPropertyDeleterCallback remover,
1574
      IndexedPropertyEnumeratorCallback enumerator,
1575
      Handle<Value> data) {
1576
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1577
  ENTER_V8(isolate);
1578
  i::HandleScope scope(isolate);
1579
  EnsureConstructor(this);
1580
  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1581
      Utils::OpenHandle(this)->constructor());
1582
  i::Handle<i::FunctionTemplateInfo> cons(constructor);
1583
  i::Handle<i::Struct> struct_obj =
1584
      isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1585
  i::Handle<i::InterceptorInfo> obj =
1586
      i::Handle<i::InterceptorInfo>::cast(struct_obj);
1587

    
1588
  if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1589
  if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1590
  if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1591
  if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1592
  if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1593

    
1594
  if (data.IsEmpty()) {
1595
    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1596
  }
1597
  obj->set_data(*Utils::OpenHandle(*data));
1598
  cons->set_indexed_property_handler(*obj);
1599
}
1600

    
1601

    
1602
void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1603
                                              Handle<Value> data) {
1604
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1605
  ENTER_V8(isolate);
1606
  i::HandleScope scope(isolate);
1607
  EnsureConstructor(this);
1608
  i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1609
      Utils::OpenHandle(this)->constructor());
1610
  i::Handle<i::FunctionTemplateInfo> cons(constructor);
1611
  i::Handle<i::Struct> struct_obj =
1612
      isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1613
  i::Handle<i::CallHandlerInfo> obj =
1614
      i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1615
  SET_FIELD_WRAPPED(obj, set_callback, callback);
1616
  if (data.IsEmpty()) {
1617
    data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1618
  }
1619
  obj->set_data(*Utils::OpenHandle(*data));
1620
  cons->set_instance_call_handler(*obj);
1621
}
1622

    
1623

    
1624
int ObjectTemplate::InternalFieldCount() {
1625
  return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1626
}
1627

    
1628

    
1629
void ObjectTemplate::SetInternalFieldCount(int value) {
1630
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1631
  if (!ApiCheck(i::Smi::IsValid(value),
1632
                "v8::ObjectTemplate::SetInternalFieldCount()",
1633
                "Invalid internal field count")) {
1634
    return;
1635
  }
1636
  ENTER_V8(isolate);
1637
  if (value > 0) {
1638
    // The internal field count is set by the constructor function's
1639
    // construct code, so we ensure that there is a constructor
1640
    // function to do the setting.
1641
    EnsureConstructor(this);
1642
  }
1643
  Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1644
}
1645

    
1646

    
1647
// --- S c r i p t D a t a ---
1648

    
1649

    
1650
ScriptData* ScriptData::PreCompile(v8::Isolate* isolate,
1651
                                   const char* input,
1652
                                   int length) {
1653
  i::Utf8ToUtf16CharacterStream stream(
1654
      reinterpret_cast<const unsigned char*>(input), length);
1655
  return i::PreParserApi::PreParse(
1656
      reinterpret_cast<i::Isolate*>(isolate), &stream);
1657
}
1658

    
1659

    
1660
ScriptData* ScriptData::PreCompile(v8::Handle<String> source) {
1661
  i::Handle<i::String> str = Utils::OpenHandle(*source);
1662
  i::Isolate* isolate = str->GetIsolate();
1663
  if (str->IsExternalTwoByteString()) {
1664
    i::ExternalTwoByteStringUtf16CharacterStream stream(
1665
      i::Handle<i::ExternalTwoByteString>::cast(str), 0, str->length());
1666
    return i::PreParserApi::PreParse(isolate, &stream);
1667
  } else {
1668
    i::GenericStringUtf16CharacterStream stream(str, 0, str->length());
1669
    return i::PreParserApi::PreParse(isolate, &stream);
1670
  }
1671
}
1672

    
1673

    
1674
ScriptData* ScriptData::New(const char* data, int length) {
1675
  // Return an empty ScriptData if the length is obviously invalid.
1676
  if (length % sizeof(unsigned) != 0) {
1677
    return new i::ScriptDataImpl();
1678
  }
1679

    
1680
  // Copy the data to ensure it is properly aligned.
1681
  int deserialized_data_length = length / sizeof(unsigned);
1682
  // If aligned, don't create a copy of the data.
1683
  if (reinterpret_cast<intptr_t>(data) % sizeof(unsigned) == 0) {
1684
    return new i::ScriptDataImpl(data, length);
1685
  }
1686
  // Copy the data to align it.
1687
  unsigned* deserialized_data = i::NewArray<unsigned>(deserialized_data_length);
1688
  i::CopyBytes(reinterpret_cast<char*>(deserialized_data),
1689
               data, static_cast<size_t>(length));
1690

    
1691
  return new i::ScriptDataImpl(
1692
      i::Vector<unsigned>(deserialized_data, deserialized_data_length));
1693
}
1694

    
1695

    
1696
// --- S c r i p t ---
1697

    
1698

    
1699
Local<Script> Script::New(v8::Handle<String> source,
1700
                          v8::ScriptOrigin* origin,
1701
                          v8::ScriptData* pre_data,
1702
                          v8::Handle<String> script_data) {
1703
  i::Handle<i::String> str = Utils::OpenHandle(*source);
1704
  i::Isolate* isolate = str->GetIsolate();
1705
  ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>());
1706
  LOG_API(isolate, "Script::New");
1707
  ENTER_V8(isolate);
1708
  i::SharedFunctionInfo* raw_result = NULL;
1709
  { i::HandleScope scope(isolate);
1710
    i::Handle<i::Object> name_obj;
1711
    int line_offset = 0;
1712
    int column_offset = 0;
1713
    bool is_shared_cross_origin = false;
1714
    if (origin != NULL) {
1715
      if (!origin->ResourceName().IsEmpty()) {
1716
        name_obj = Utils::OpenHandle(*origin->ResourceName());
1717
      }
1718
      if (!origin->ResourceLineOffset().IsEmpty()) {
1719
        line_offset = static_cast<int>(origin->ResourceLineOffset()->Value());
1720
      }
1721
      if (!origin->ResourceColumnOffset().IsEmpty()) {
1722
        column_offset =
1723
            static_cast<int>(origin->ResourceColumnOffset()->Value());
1724
      }
1725
      if (!origin->ResourceIsSharedCrossOrigin().IsEmpty()) {
1726
        v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1727
        is_shared_cross_origin =
1728
            origin->ResourceIsSharedCrossOrigin() == v8::True(v8_isolate);
1729
      }
1730
    }
1731
    EXCEPTION_PREAMBLE(isolate);
1732
    i::ScriptDataImpl* pre_data_impl =
1733
        static_cast<i::ScriptDataImpl*>(pre_data);
1734
    // We assert that the pre-data is sane, even though we can actually
1735
    // handle it if it turns out not to be in release mode.
1736
    ASSERT(pre_data_impl == NULL || pre_data_impl->SanityCheck());
1737
    // If the pre-data isn't sane we simply ignore it
1738
    if (pre_data_impl != NULL && !pre_data_impl->SanityCheck()) {
1739
      pre_data_impl = NULL;
1740
    }
1741
    i::Handle<i::SharedFunctionInfo> result =
1742
      i::Compiler::Compile(str,
1743
                           name_obj,
1744
                           line_offset,
1745
                           column_offset,
1746
                           is_shared_cross_origin,
1747
                           isolate->global_context(),
1748
                           NULL,
1749
                           pre_data_impl,
1750
                           Utils::OpenHandle(*script_data, true),
1751
                           i::NOT_NATIVES_CODE);
1752
    has_pending_exception = result.is_null();
1753
    EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>());
1754
    raw_result = *result;
1755
  }
1756
  i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
1757
  return ToApiHandle<Script>(result);
1758
}
1759

    
1760

    
1761
Local<Script> Script::New(v8::Handle<String> source,
1762
                          v8::Handle<Value> file_name) {
1763
  ScriptOrigin origin(file_name);
1764
  return New(source, &origin);
1765
}
1766

    
1767

    
1768
Local<Script> Script::Compile(v8::Handle<String> source,
1769
                              v8::ScriptOrigin* origin,
1770
                              v8::ScriptData* pre_data,
1771
                              v8::Handle<String> script_data) {
1772
  i::Handle<i::String> str = Utils::OpenHandle(*source);
1773
  i::Isolate* isolate = str->GetIsolate();
1774
  ON_BAILOUT(isolate, "v8::Script::Compile()", return Local<Script>());
1775
  LOG_API(isolate, "Script::Compile");
1776
  ENTER_V8(isolate);
1777
  Local<Script> generic = New(source, origin, pre_data, script_data);
1778
  if (generic.IsEmpty())
1779
    return generic;
1780
  i::Handle<i::Object> obj = Utils::OpenHandle(*generic);
1781
  i::Handle<i::SharedFunctionInfo> function =
1782
      i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1783
  i::Handle<i::JSFunction> result =
1784
      isolate->factory()->NewFunctionFromSharedFunctionInfo(
1785
          function,
1786
          isolate->global_context());
1787
  return ToApiHandle<Script>(result);
1788
}
1789

    
1790

    
1791
Local<Script> Script::Compile(v8::Handle<String> source,
1792
                              v8::Handle<Value> file_name,
1793
                              v8::Handle<String> script_data) {
1794
  ScriptOrigin origin(file_name);
1795
  return Compile(source, &origin, 0, script_data);
1796
}
1797

    
1798

    
1799
Local<Value> Script::Run() {
1800
  // If execution is terminating, Compile(script)->Run() requires this check.
1801
  if (this == NULL) return Local<Value>();
1802
  i::Handle<i::HeapObject> obj =
1803
      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1804
  i::Isolate* isolate = obj->GetIsolate();
1805
  ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
1806
  LOG_API(isolate, "Script::Run");
1807
  ENTER_V8(isolate);
1808
  i::Logger::TimerEventScope timer_scope(
1809
      isolate, i::Logger::TimerEventScope::v8_execute);
1810
  i::Object* raw_result = NULL;
1811
  {
1812
    i::HandleScope scope(isolate);
1813
    i::Handle<i::JSFunction> fun;
1814
    if (obj->IsSharedFunctionInfo()) {
1815
      i::Handle<i::SharedFunctionInfo>
1816
          function_info(i::SharedFunctionInfo::cast(*obj), isolate);
1817
      fun = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1818
          function_info, isolate->global_context());
1819
    } else {
1820
      fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate);
1821
    }
1822
    EXCEPTION_PREAMBLE(isolate);
1823
    i::Handle<i::Object> receiver(
1824
        isolate->context()->global_proxy(), isolate);
1825
    i::Handle<i::Object> result = i::Execution::Call(
1826
        isolate, fun, receiver, 0, NULL, &has_pending_exception);
1827
    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
1828
    raw_result = *result;
1829
  }
1830
  i::Handle<i::Object> result(raw_result, isolate);
1831
  return Utils::ToLocal(result);
1832
}
1833

    
1834

    
1835
static i::Handle<i::SharedFunctionInfo> OpenScript(Script* script) {
1836
  i::Handle<i::Object> obj = Utils::OpenHandle(script);
1837
  i::Handle<i::SharedFunctionInfo> result;
1838
  if (obj->IsSharedFunctionInfo()) {
1839
    result =
1840
        i::Handle<i::SharedFunctionInfo>(i::SharedFunctionInfo::cast(*obj));
1841
  } else {
1842
    result =
1843
        i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared());
1844
  }
1845
  return result;
1846
}
1847

    
1848

    
1849
Local<Value> Script::Id() {
1850
  i::Handle<i::HeapObject> obj =
1851
      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1852
  i::Isolate* isolate = obj->GetIsolate();
1853
  ON_BAILOUT(isolate, "v8::Script::Id()", return Local<Value>());
1854
  LOG_API(isolate, "Script::Id");
1855
  i::Object* raw_id = NULL;
1856
  {
1857
    i::HandleScope scope(isolate);
1858
    i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1859
    i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1860
    i::Handle<i::Object> id(script->id(), isolate);
1861
    raw_id = *id;
1862
  }
1863
  i::Handle<i::Object> id(raw_id, isolate);
1864
  return Utils::ToLocal(id);
1865
}
1866

    
1867

    
1868
int Script::GetId() {
1869
  i::Handle<i::HeapObject> obj =
1870
      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1871
  i::Isolate* isolate = obj->GetIsolate();
1872
  ON_BAILOUT(isolate, "v8::Script::Id()", return -1);
1873
  LOG_API(isolate, "Script::Id");
1874
  {
1875
    i::HandleScope scope(isolate);
1876
    i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1877
    i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1878
    return script->id()->value();
1879
  }
1880
}
1881

    
1882

    
1883
int Script::GetLineNumber(int code_pos) {
1884
  i::Handle<i::HeapObject> obj =
1885
      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1886
  i::Isolate* isolate = obj->GetIsolate();
1887
  ON_BAILOUT(isolate, "v8::Script::GetLineNumber()", return -1);
1888
  LOG_API(isolate, "Script::GetLineNumber");
1889
  if (obj->IsScript()) {
1890
    i::Handle<i::Script> script = i::Handle<i::Script>(i::Script::cast(*obj));
1891
    return i::GetScriptLineNumber(script, code_pos);
1892
  } else {
1893
    return -1;
1894
  }
1895
}
1896

    
1897

    
1898
Handle<Value> Script::GetScriptName() {
1899
  i::Handle<i::HeapObject> obj =
1900
      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1901
  i::Isolate* isolate = obj->GetIsolate();
1902
  ON_BAILOUT(isolate, "v8::Script::GetName()", return Handle<String>());
1903
  LOG_API(isolate, "Script::GetName");
1904
  if (obj->IsScript()) {
1905
    i::Object* name = i::Script::cast(*obj)->name();
1906
    return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
1907
  } else {
1908
    return Handle<String>();
1909
  }
1910
}
1911

    
1912

    
1913
void Script::SetData(v8::Handle<String> data) {
1914
  i::Handle<i::HeapObject> obj =
1915
      i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1916
  i::Isolate* isolate = obj->GetIsolate();
1917
  ON_BAILOUT(isolate, "v8::Script::SetData()", return);
1918
  LOG_API(isolate, "Script::SetData");
1919
  {
1920
    i::HandleScope scope(isolate);
1921
    i::Handle<i::SharedFunctionInfo> function_info = OpenScript(this);
1922
    i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
1923
    i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1924
    script->set_data(*raw_data);
1925
  }
1926
}
1927

    
1928

    
1929
// --- E x c e p t i o n s ---
1930

    
1931

    
1932
v8::TryCatch::TryCatch()
1933
    : isolate_(i::Isolate::Current()),
1934
      next_(isolate_->try_catch_handler_address()),
1935
      is_verbose_(false),
1936
      can_continue_(true),
1937
      capture_message_(true),
1938
      rethrow_(false),
1939
      has_terminated_(false) {
1940
  Reset();
1941
  isolate_->RegisterTryCatchHandler(this);
1942
}
1943

    
1944

    
1945
v8::TryCatch::~TryCatch() {
1946
  ASSERT(isolate_ == i::Isolate::Current());
1947
  if (rethrow_) {
1948
    v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
1949
    v8::HandleScope scope(isolate);
1950
    v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
1951
    if (HasCaught() && capture_message_) {
1952
      // If an exception was caught and rethrow_ is indicated, the saved
1953
      // message, script, and location need to be restored to Isolate TLS
1954
      // for reuse.  capture_message_ needs to be disabled so that DoThrow()
1955
      // does not create a new message.
1956
      isolate_->thread_local_top()->rethrowing_message_ = true;
1957
      isolate_->RestorePendingMessageFromTryCatch(this);
1958
    }
1959
    isolate_->UnregisterTryCatchHandler(this);
1960
    reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
1961
    ASSERT(!isolate_->thread_local_top()->rethrowing_message_);
1962
  } else {
1963
    isolate_->UnregisterTryCatchHandler(this);
1964
  }
1965
}
1966

    
1967

    
1968
bool v8::TryCatch::HasCaught() const {
1969
  return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1970
}
1971

    
1972

    
1973
bool v8::TryCatch::CanContinue() const {
1974
  return can_continue_;
1975
}
1976

    
1977

    
1978
bool v8::TryCatch::HasTerminated() const {
1979
  return has_terminated_;
1980
}
1981

    
1982

    
1983
v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1984
  if (!HasCaught()) return v8::Local<v8::Value>();
1985
  rethrow_ = true;
1986
  return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
1987
}
1988

    
1989

    
1990
v8::Local<Value> v8::TryCatch::Exception() const {
1991
  ASSERT(isolate_ == i::Isolate::Current());
1992
  if (HasCaught()) {
1993
    // Check for out of memory exception.
1994
    i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1995
    return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
1996
  } else {
1997
    return v8::Local<Value>();
1998
  }
1999
}
2000

    
2001

    
2002
v8::Local<Value> v8::TryCatch::StackTrace() const {
2003
  ASSERT(isolate_ == i::Isolate::Current());
2004
  if (HasCaught()) {
2005
    i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
2006
    if (!raw_obj->IsJSObject()) return v8::Local<Value>();
2007
    i::HandleScope scope(isolate_);
2008
    i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
2009
    i::Handle<i::String> name = isolate_->factory()->stack_string();
2010
    if (!i::JSReceiver::HasProperty(obj, name)) return v8::Local<Value>();
2011
    i::Handle<i::Object> value = i::GetProperty(isolate_, obj, name);
2012
    if (value.is_null()) return v8::Local<Value>();
2013
    return v8::Utils::ToLocal(scope.CloseAndEscape(value));
2014
  } else {
2015
    return v8::Local<Value>();
2016
  }
2017
}
2018

    
2019

    
2020
v8::Local<v8::Message> v8::TryCatch::Message() const {
2021
  ASSERT(isolate_ == i::Isolate::Current());
2022
  i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
2023
  ASSERT(message->IsJSMessageObject() || message->IsTheHole());
2024
  if (HasCaught() && !message->IsTheHole()) {
2025
    return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
2026
  } else {
2027
    return v8::Local<v8::Message>();
2028
  }
2029
}
2030

    
2031

    
2032
void v8::TryCatch::Reset() {
2033
  ASSERT(isolate_ == i::Isolate::Current());
2034
  i::Object* the_hole = isolate_->heap()->the_hole_value();
2035
  exception_ = the_hole;
2036
  message_obj_ = the_hole;
2037
  message_script_ = the_hole;
2038
  message_start_pos_ = 0;
2039
  message_end_pos_ = 0;
2040
}
2041

    
2042

    
2043
void v8::TryCatch::SetVerbose(bool value) {
2044
  is_verbose_ = value;
2045
}
2046

    
2047

    
2048
void v8::TryCatch::SetCaptureMessage(bool value) {
2049
  capture_message_ = value;
2050
}
2051

    
2052

    
2053
// --- M e s s a g e ---
2054

    
2055

    
2056
Local<String> Message::Get() const {
2057
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2058
  ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
2059
  ENTER_V8(isolate);
2060
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2061
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2062
  i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj);
2063
  Local<String> result = Utils::ToLocal(raw_result);
2064
  return scope.Close(result);
2065
}
2066

    
2067

    
2068
v8::Handle<Value> Message::GetScriptResourceName() const {
2069
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2070
  ENTER_V8(isolate);
2071
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2072
  i::Handle<i::JSMessageObject> message =
2073
      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2074
  // Return this.script.name.
2075
  i::Handle<i::JSValue> script =
2076
      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2077
                                                       isolate));
2078
  i::Handle<i::Object> resource_name(i::Script::cast(script->value())->name(),
2079
                                     isolate);
2080
  return scope.Close(Utils::ToLocal(resource_name));
2081
}
2082

    
2083

    
2084
v8::Handle<Value> Message::GetScriptData() const {
2085
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2086
  ENTER_V8(isolate);
2087
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2088
  i::Handle<i::JSMessageObject> message =
2089
      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2090
  // Return this.script.data.
2091
  i::Handle<i::JSValue> script =
2092
      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2093
                                                       isolate));
2094
  i::Handle<i::Object> data(i::Script::cast(script->value())->data(), isolate);
2095
  return scope.Close(Utils::ToLocal(data));
2096
}
2097

    
2098

    
2099
v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
2100
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2101
  ENTER_V8(isolate);
2102
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2103
  i::Handle<i::JSMessageObject> message =
2104
      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2105
  i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
2106
  if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
2107
  i::Handle<i::JSArray> stackTrace =
2108
      i::Handle<i::JSArray>::cast(stackFramesObj);
2109
  return scope.Close(Utils::StackTraceToLocal(stackTrace));
2110
}
2111

    
2112

    
2113
static i::Handle<i::Object> CallV8HeapFunction(const char* name,
2114
                                               i::Handle<i::Object> recv,
2115
                                               int argc,
2116
                                               i::Handle<i::Object> argv[],
2117
                                               bool* has_pending_exception) {
2118
  i::Isolate* isolate = i::Isolate::Current();
2119
  i::Handle<i::String> fmt_str =
2120
      isolate->factory()->InternalizeUtf8String(name);
2121
  i::Object* object_fun =
2122
      isolate->js_builtins_object()->GetPropertyNoExceptionThrown(*fmt_str);
2123
  i::Handle<i::JSFunction> fun =
2124
      i::Handle<i::JSFunction>(i::JSFunction::cast(object_fun));
2125
  i::Handle<i::Object> value = i::Execution::Call(
2126
      isolate, fun, recv, argc, argv, has_pending_exception);
2127
  return value;
2128
}
2129

    
2130

    
2131
static i::Handle<i::Object> CallV8HeapFunction(const char* name,
2132
                                               i::Handle<i::Object> data,
2133
                                               bool* has_pending_exception) {
2134
  i::Handle<i::Object> argv[] = { data };
2135
  return CallV8HeapFunction(name,
2136
                            i::Isolate::Current()->js_builtins_object(),
2137
                            ARRAY_SIZE(argv),
2138
                            argv,
2139
                            has_pending_exception);
2140
}
2141

    
2142

    
2143
int Message::GetLineNumber() const {
2144
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2145
  ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
2146
  ENTER_V8(isolate);
2147
  i::HandleScope scope(isolate);
2148

    
2149
  EXCEPTION_PREAMBLE(isolate);
2150
  i::Handle<i::Object> result = CallV8HeapFunction("GetLineNumber",
2151
                                                   Utils::OpenHandle(this),
2152
                                                   &has_pending_exception);
2153
  EXCEPTION_BAILOUT_CHECK(isolate, 0);
2154
  return static_cast<int>(result->Number());
2155
}
2156

    
2157

    
2158
int Message::GetStartPosition() const {
2159
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2160
  ENTER_V8(isolate);
2161
  i::HandleScope scope(isolate);
2162
  i::Handle<i::JSMessageObject> message =
2163
      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2164
  return message->start_position();
2165
}
2166

    
2167

    
2168
int Message::GetEndPosition() const {
2169
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2170
  ENTER_V8(isolate);
2171
  i::HandleScope scope(isolate);
2172
  i::Handle<i::JSMessageObject> message =
2173
      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2174
  return message->end_position();
2175
}
2176

    
2177

    
2178
int Message::GetStartColumn() const {
2179
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2180
  ENTER_V8(isolate);
2181
  i::HandleScope scope(isolate);
2182
  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2183
  EXCEPTION_PREAMBLE(isolate);
2184
  i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
2185
      "GetPositionInLine",
2186
      data_obj,
2187
      &has_pending_exception);
2188
  EXCEPTION_BAILOUT_CHECK(isolate, 0);
2189
  return static_cast<int>(start_col_obj->Number());
2190
}
2191

    
2192

    
2193
int Message::GetEndColumn() const {
2194
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2195
  ENTER_V8(isolate);
2196
  i::HandleScope scope(isolate);
2197
  i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2198
  EXCEPTION_PREAMBLE(isolate);
2199
  i::Handle<i::Object> start_col_obj = CallV8HeapFunction(
2200
      "GetPositionInLine",
2201
      data_obj,
2202
      &has_pending_exception);
2203
  EXCEPTION_BAILOUT_CHECK(isolate, 0);
2204
  i::Handle<i::JSMessageObject> message =
2205
      i::Handle<i::JSMessageObject>::cast(data_obj);
2206
  int start = message->start_position();
2207
  int end = message->end_position();
2208
  return static_cast<int>(start_col_obj->Number()) + (end - start);
2209
}
2210

    
2211

    
2212
bool Message::IsSharedCrossOrigin() const {
2213
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2214
  ENTER_V8(isolate);
2215
  i::HandleScope scope(isolate);
2216
  i::Handle<i::JSMessageObject> message =
2217
      i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2218
  i::Handle<i::JSValue> script =
2219
      i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2220
                                                       isolate));
2221
  return i::Script::cast(script->value())->is_shared_cross_origin();
2222
}
2223

    
2224

    
2225
Local<String> Message::GetSourceLine() const {
2226
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2227
  ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
2228
  ENTER_V8(isolate);
2229
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2230
  EXCEPTION_PREAMBLE(isolate);
2231
  i::Handle<i::Object> result = CallV8HeapFunction("GetSourceLine",
2232
                                                   Utils::OpenHandle(this),
2233
                                                   &has_pending_exception);
2234
  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
2235
  if (result->IsString()) {
2236
    return scope.Close(Utils::ToLocal(i::Handle<i::String>::cast(result)));
2237
  } else {
2238
    return Local<String>();
2239
  }
2240
}
2241

    
2242

    
2243
void Message::PrintCurrentStackTrace(FILE* out) {
2244
  i::Isolate* isolate = i::Isolate::Current();
2245
  ENTER_V8(isolate);
2246
  isolate->PrintCurrentStackTrace(out);
2247
}
2248

    
2249

    
2250
// --- S t a c k T r a c e ---
2251

    
2252
Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
2253
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2254
  ENTER_V8(isolate);
2255
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2256
  i::Handle<i::JSArray> self = Utils::OpenHandle(this);
2257
  i::Object* raw_object = self->GetElementNoExceptionThrown(isolate, index);
2258
  i::Handle<i::JSObject> obj(i::JSObject::cast(raw_object));
2259
  return scope.Close(Utils::StackFrameToLocal(obj));
2260
}
2261

    
2262

    
2263
int StackTrace::GetFrameCount() const {
2264
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2265
  ENTER_V8(isolate);
2266
  return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
2267
}
2268

    
2269

    
2270
Local<Array> StackTrace::AsArray() {
2271
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2272
  ENTER_V8(isolate);
2273
  return Utils::ToLocal(Utils::OpenHandle(this));
2274
}
2275

    
2276

    
2277
Local<StackTrace> StackTrace::CurrentStackTrace(int frame_limit,
2278
    StackTraceOptions options) {
2279
  i::Isolate* isolate = i::Isolate::Current();
2280
  ENTER_V8(isolate);
2281
  i::Handle<i::JSArray> stackTrace =
2282
      isolate->CaptureCurrentStackTrace(frame_limit, options);
2283
  return Utils::StackTraceToLocal(stackTrace);
2284
}
2285

    
2286

    
2287
// --- S t a c k F r a m e ---
2288

    
2289
int StackFrame::GetLineNumber() const {
2290
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2291
  ENTER_V8(isolate);
2292
  i::HandleScope scope(isolate);
2293
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2294
  i::Handle<i::Object> line = GetProperty(self, "lineNumber");
2295
  if (!line->IsSmi()) {
2296
    return Message::kNoLineNumberInfo;
2297
  }
2298
  return i::Smi::cast(*line)->value();
2299
}
2300

    
2301

    
2302
int StackFrame::GetColumn() const {
2303
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2304
  ENTER_V8(isolate);
2305
  i::HandleScope scope(isolate);
2306
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2307
  i::Handle<i::Object> column = GetProperty(self, "column");
2308
  if (!column->IsSmi()) {
2309
    return Message::kNoColumnInfo;
2310
  }
2311
  return i::Smi::cast(*column)->value();
2312
}
2313

    
2314

    
2315
int StackFrame::GetScriptId() const {
2316
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2317
  ENTER_V8(isolate);
2318
  i::HandleScope scope(isolate);
2319
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2320
  i::Handle<i::Object> scriptId = GetProperty(self, "scriptId");
2321
  if (!scriptId->IsSmi()) {
2322
    return Message::kNoScriptIdInfo;
2323
  }
2324
  return i::Smi::cast(*scriptId)->value();
2325
}
2326

    
2327

    
2328
Local<String> StackFrame::GetScriptName() const {
2329
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2330
  ENTER_V8(isolate);
2331
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2332
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2333
  i::Handle<i::Object> name = GetProperty(self, "scriptName");
2334
  if (!name->IsString()) {
2335
    return Local<String>();
2336
  }
2337
  return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
2338
}
2339

    
2340

    
2341
Local<String> StackFrame::GetScriptNameOrSourceURL() const {
2342
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2343
  ENTER_V8(isolate);
2344
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2345
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2346
  i::Handle<i::Object> name = GetProperty(self, "scriptNameOrSourceURL");
2347
  if (!name->IsString()) {
2348
    return Local<String>();
2349
  }
2350
  return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
2351
}
2352

    
2353

    
2354
Local<String> StackFrame::GetFunctionName() const {
2355
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2356
  ENTER_V8(isolate);
2357
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
2358
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2359
  i::Handle<i::Object> name = GetProperty(self, "functionName");
2360
  if (!name->IsString()) {
2361
    return Local<String>();
2362
  }
2363
  return scope.Close(Local<String>::Cast(Utils::ToLocal(name)));
2364
}
2365

    
2366

    
2367
bool StackFrame::IsEval() const {
2368
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2369
  ENTER_V8(isolate);
2370
  i::HandleScope scope(isolate);
2371
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2372
  i::Handle<i::Object> is_eval = GetProperty(self, "isEval");
2373
  return is_eval->IsTrue();
2374
}
2375

    
2376

    
2377
bool StackFrame::IsConstructor() const {
2378
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2379
  ENTER_V8(isolate);
2380
  i::HandleScope scope(isolate);
2381
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
2382
  i::Handle<i::Object> is_constructor = GetProperty(self, "isConstructor");
2383
  return is_constructor->IsTrue();
2384
}
2385

    
2386

    
2387
// --- J S O N ---
2388

    
2389
Local<Value> JSON::Parse(Local<String> json_string) {
2390
  i::Isolate* isolate = i::Isolate::Current();
2391
  EnsureInitializedForIsolate(isolate, "v8::JSON::Parse");
2392
  ENTER_V8(isolate);
2393
  i::HandleScope scope(isolate);
2394
  i::Handle<i::String> source = i::Handle<i::String>(
2395
      FlattenGetString(Utils::OpenHandle(*json_string)));
2396
  EXCEPTION_PREAMBLE(isolate);
2397
  i::Handle<i::Object> result;
2398
  if (source->IsSeqOneByteString()) {
2399
    result = i::JsonParser<true>::Parse(source);
2400
  } else {
2401
    result = i::JsonParser<false>::Parse(source);
2402
  }
2403
  has_pending_exception = result.is_null();
2404
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
2405
  return Utils::ToLocal(
2406
      i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
2407
}
2408

    
2409

    
2410
// --- D a t a ---
2411

    
2412
bool Value::FullIsUndefined() const {
2413
  bool result = Utils::OpenHandle(this)->IsUndefined();
2414
  ASSERT_EQ(result, QuickIsUndefined());
2415
  return result;
2416
}
2417

    
2418

    
2419
bool Value::FullIsNull() const {
2420
  bool result = Utils::OpenHandle(this)->IsNull();
2421
  ASSERT_EQ(result, QuickIsNull());
2422
  return result;
2423
}
2424

    
2425

    
2426
bool Value::IsTrue() const {
2427
  return Utils::OpenHandle(this)->IsTrue();
2428
}
2429

    
2430

    
2431
bool Value::IsFalse() const {
2432
  return Utils::OpenHandle(this)->IsFalse();
2433
}
2434

    
2435

    
2436
bool Value::IsFunction() const {
2437
  return Utils::OpenHandle(this)->IsJSFunction();
2438
}
2439

    
2440

    
2441
bool Value::FullIsString() const {
2442
  bool result = Utils::OpenHandle(this)->IsString();
2443
  ASSERT_EQ(result, QuickIsString());
2444
  return result;
2445
}
2446

    
2447

    
2448
bool Value::IsSymbol() const {
2449
  return Utils::OpenHandle(this)->IsSymbol();
2450
}
2451

    
2452

    
2453
bool Value::IsArray() const {
2454
  return Utils::OpenHandle(this)->IsJSArray();
2455
}
2456

    
2457

    
2458
bool Value::IsArrayBuffer() const {
2459
  return Utils::OpenHandle(this)->IsJSArrayBuffer();
2460
}
2461

    
2462

    
2463
bool Value::IsArrayBufferView() const {
2464
  return Utils::OpenHandle(this)->IsJSArrayBufferView();
2465
}
2466

    
2467

    
2468
bool Value::IsTypedArray() const {
2469
  return Utils::OpenHandle(this)->IsJSTypedArray();
2470
}
2471

    
2472

    
2473
#define TYPED_ARRAY_LIST(F) \
2474
F(Uint8Array, kExternalUnsignedByteArray) \
2475
F(Int8Array, kExternalByteArray) \
2476
F(Uint16Array, kExternalUnsignedShortArray) \
2477
F(Int16Array, kExternalShortArray) \
2478
F(Uint32Array, kExternalUnsignedIntArray) \
2479
F(Int32Array, kExternalIntArray) \
2480
F(Float32Array, kExternalFloatArray) \
2481
F(Float64Array, kExternalDoubleArray) \
2482
F(Uint8ClampedArray, kExternalPixelArray)
2483

    
2484

    
2485
#define VALUE_IS_TYPED_ARRAY(TypedArray, type_const)                          \
2486
  bool Value::Is##TypedArray() const {                                        \
2487
    i::Handle<i::Object> obj = Utils::OpenHandle(this);                       \
2488
    if (!obj->IsJSTypedArray()) return false;                                 \
2489
    return i::JSTypedArray::cast(*obj)->type() == type_const;                 \
2490
  }
2491

    
2492
TYPED_ARRAY_LIST(VALUE_IS_TYPED_ARRAY)
2493

    
2494
#undef VALUE_IS_TYPED_ARRAY
2495

    
2496

    
2497
bool Value::IsDataView() const {
2498
  return Utils::OpenHandle(this)->IsJSDataView();
2499
}
2500

    
2501

    
2502
bool Value::IsObject() const {
2503
  return Utils::OpenHandle(this)->IsJSObject();
2504
}
2505

    
2506

    
2507
bool Value::IsNumber() const {
2508
  return Utils::OpenHandle(this)->IsNumber();
2509
}
2510

    
2511

    
2512
bool Value::IsBoolean() const {
2513
  return Utils::OpenHandle(this)->IsBoolean();
2514
}
2515

    
2516

    
2517
bool Value::IsExternal() const {
2518
  return Utils::OpenHandle(this)->IsExternal();
2519
}
2520

    
2521

    
2522
bool Value::IsInt32() const {
2523
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2524
  if (obj->IsSmi()) return true;
2525
  if (obj->IsNumber()) {
2526
    double value = obj->Number();
2527
    static const i::DoubleRepresentation minus_zero(-0.0);
2528
    i::DoubleRepresentation rep(value);
2529
    if (rep.bits == minus_zero.bits) {
2530
      return false;
2531
    }
2532
    return i::FastI2D(i::FastD2I(value)) == value;
2533
  }
2534
  return false;
2535
}
2536

    
2537

    
2538
bool Value::IsUint32() const {
2539
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2540
  if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
2541
  if (obj->IsNumber()) {
2542
    double value = obj->Number();
2543
    static const i::DoubleRepresentation minus_zero(-0.0);
2544
    i::DoubleRepresentation rep(value);
2545
    if (rep.bits == minus_zero.bits) {
2546
      return false;
2547
    }
2548
    return i::FastUI2D(i::FastD2UI(value)) == value;
2549
  }
2550
  return false;
2551
}
2552

    
2553

    
2554
bool Value::IsDate() const {
2555
  i::Isolate* isolate = i::Isolate::Current();
2556
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2557
  return obj->HasSpecificClassOf(isolate->heap()->Date_string());
2558
}
2559

    
2560

    
2561
bool Value::IsStringObject() const {
2562
  i::Isolate* isolate = i::Isolate::Current();
2563
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2564
  return obj->HasSpecificClassOf(isolate->heap()->String_string());
2565
}
2566

    
2567

    
2568
bool Value::IsSymbolObject() const {
2569
  // TODO(svenpanne): these and other test functions should be written such
2570
  // that they do not use Isolate::Current().
2571
  i::Isolate* isolate = i::Isolate::Current();
2572
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2573
  return obj->HasSpecificClassOf(isolate->heap()->Symbol_string());
2574
}
2575

    
2576

    
2577
bool Value::IsNumberObject() const {
2578
  i::Isolate* isolate = i::Isolate::Current();
2579
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2580
  return obj->HasSpecificClassOf(isolate->heap()->Number_string());
2581
}
2582

    
2583

    
2584
static i::Object* LookupBuiltin(i::Isolate* isolate,
2585
                                const char* builtin_name) {
2586
  i::Handle<i::String> string =
2587
      isolate->factory()->InternalizeUtf8String(builtin_name);
2588
  i::Handle<i::JSBuiltinsObject> builtins = isolate->js_builtins_object();
2589
  return builtins->GetPropertyNoExceptionThrown(*string);
2590
}
2591

    
2592

    
2593
static bool CheckConstructor(i::Isolate* isolate,
2594
                             i::Handle<i::JSObject> obj,
2595
                             const char* class_name) {
2596
  i::Object* constr = obj->map()->constructor();
2597
  if (!constr->IsJSFunction()) return false;
2598
  i::JSFunction* func = i::JSFunction::cast(constr);
2599
  return func->shared()->native() &&
2600
         constr == LookupBuiltin(isolate, class_name);
2601
}
2602

    
2603

    
2604
bool Value::IsNativeError() const {
2605
  i::Isolate* isolate = i::Isolate::Current();
2606
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2607
  if (obj->IsJSObject()) {
2608
    i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
2609
    return CheckConstructor(isolate, js_obj, "$Error") ||
2610
        CheckConstructor(isolate, js_obj, "$EvalError") ||
2611
        CheckConstructor(isolate, js_obj, "$RangeError") ||
2612
        CheckConstructor(isolate, js_obj, "$ReferenceError") ||
2613
        CheckConstructor(isolate, js_obj, "$SyntaxError") ||
2614
        CheckConstructor(isolate, js_obj, "$TypeError") ||
2615
        CheckConstructor(isolate, js_obj, "$URIError");
2616
  } else {
2617
    return false;
2618
  }
2619
}
2620

    
2621

    
2622
bool Value::IsBooleanObject() const {
2623
  i::Isolate* isolate = i::Isolate::Current();
2624
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2625
  return obj->HasSpecificClassOf(isolate->heap()->Boolean_string());
2626
}
2627

    
2628

    
2629
bool Value::IsRegExp() const {
2630
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2631
  return obj->IsJSRegExp();
2632
}
2633

    
2634

    
2635
Local<String> Value::ToString() const {
2636
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2637
  i::Handle<i::Object> str;
2638
  if (obj->IsString()) {
2639
    str = obj;
2640
  } else {
2641
    i::Isolate* isolate = i::Isolate::Current();
2642
    LOG_API(isolate, "ToString");
2643
    ENTER_V8(isolate);
2644
    EXCEPTION_PREAMBLE(isolate);
2645
    str = i::Execution::ToString(isolate, obj, &has_pending_exception);
2646
    EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2647
  }
2648
  return ToApiHandle<String>(str);
2649
}
2650

    
2651

    
2652
Local<String> Value::ToDetailString() const {
2653
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2654
  i::Handle<i::Object> str;
2655
  if (obj->IsString()) {
2656
    str = obj;
2657
  } else {
2658
    i::Isolate* isolate = i::Isolate::Current();
2659
    LOG_API(isolate, "ToDetailString");
2660
    ENTER_V8(isolate);
2661
    EXCEPTION_PREAMBLE(isolate);
2662
    str = i::Execution::ToDetailString(isolate, obj, &has_pending_exception);
2663
    EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2664
  }
2665
  return ToApiHandle<String>(str);
2666
}
2667

    
2668

    
2669
Local<v8::Object> Value::ToObject() const {
2670
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2671
  i::Handle<i::Object> val;
2672
  if (obj->IsJSObject()) {
2673
    val = obj;
2674
  } else {
2675
    i::Isolate* isolate = i::Isolate::Current();
2676
    LOG_API(isolate, "ToObject");
2677
    ENTER_V8(isolate);
2678
    EXCEPTION_PREAMBLE(isolate);
2679
    val = i::Execution::ToObject(isolate, obj, &has_pending_exception);
2680
    EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
2681
  }
2682
  return ToApiHandle<Object>(val);
2683
}
2684

    
2685

    
2686
Local<Boolean> Value::ToBoolean() const {
2687
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2688
  if (obj->IsBoolean()) {
2689
    return ToApiHandle<Boolean>(obj);
2690
  } else {
2691
    i::Isolate* isolate = i::Isolate::Current();
2692
    LOG_API(isolate, "ToBoolean");
2693
    ENTER_V8(isolate);
2694
    i::Handle<i::Object> val =
2695
        isolate->factory()->ToBoolean(obj->BooleanValue());
2696
    return ToApiHandle<Boolean>(val);
2697
  }
2698
}
2699

    
2700

    
2701
Local<Number> Value::ToNumber() const {
2702
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2703
  i::Handle<i::Object> num;
2704
  if (obj->IsNumber()) {
2705
    num = obj;
2706
  } else {
2707
    i::Isolate* isolate = i::Isolate::Current();
2708
    LOG_API(isolate, "ToNumber");
2709
    ENTER_V8(isolate);
2710
    EXCEPTION_PREAMBLE(isolate);
2711
    num = i::Execution::ToNumber(isolate, obj, &has_pending_exception);
2712
    EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
2713
  }
2714
  return ToApiHandle<Number>(num);
2715
}
2716

    
2717

    
2718
Local<Integer> Value::ToInteger() const {
2719
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2720
  i::Handle<i::Object> num;
2721
  if (obj->IsSmi()) {
2722
    num = obj;
2723
  } else {
2724
    i::Isolate* isolate = i::Isolate::Current();
2725
    LOG_API(isolate, "ToInteger");
2726
    ENTER_V8(isolate);
2727
    EXCEPTION_PREAMBLE(isolate);
2728
    num = i::Execution::ToInteger(isolate, obj, &has_pending_exception);
2729
    EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
2730
  }
2731
  return ToApiHandle<Integer>(num);
2732
}
2733

    
2734

    
2735
void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
2736
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
2737
  ApiCheck(isolate != NULL && isolate->IsInitialized() && !isolate->IsDead(),
2738
           "v8::internal::Internals::CheckInitialized()",
2739
           "Isolate is not initialized or V8 has died");
2740
}
2741

    
2742

    
2743
void External::CheckCast(v8::Value* that) {
2744
  ApiCheck(Utils::OpenHandle(that)->IsExternal(),
2745
           "v8::External::Cast()",
2746
           "Could not convert to external");
2747
}
2748

    
2749

    
2750
void v8::Object::CheckCast(Value* that) {
2751
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2752
  ApiCheck(obj->IsJSObject(),
2753
           "v8::Object::Cast()",
2754
           "Could not convert to object");
2755
}
2756

    
2757

    
2758
void v8::Function::CheckCast(Value* that) {
2759
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2760
  ApiCheck(obj->IsJSFunction(),
2761
           "v8::Function::Cast()",
2762
           "Could not convert to function");
2763
}
2764

    
2765

    
2766
void v8::String::CheckCast(v8::Value* that) {
2767
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2768
  ApiCheck(obj->IsString(),
2769
           "v8::String::Cast()",
2770
           "Could not convert to string");
2771
}
2772

    
2773

    
2774
void v8::Symbol::CheckCast(v8::Value* that) {
2775
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2776
  ApiCheck(obj->IsSymbol(),
2777
           "v8::Symbol::Cast()",
2778
           "Could not convert to symbol");
2779
}
2780

    
2781

    
2782
void v8::Number::CheckCast(v8::Value* that) {
2783
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2784
  ApiCheck(obj->IsNumber(),
2785
           "v8::Number::Cast()",
2786
           "Could not convert to number");
2787
}
2788

    
2789

    
2790
void v8::Integer::CheckCast(v8::Value* that) {
2791
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2792
  ApiCheck(obj->IsNumber(),
2793
           "v8::Integer::Cast()",
2794
           "Could not convert to number");
2795
}
2796

    
2797

    
2798
void v8::Array::CheckCast(Value* that) {
2799
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2800
  ApiCheck(obj->IsJSArray(),
2801
           "v8::Array::Cast()",
2802
           "Could not convert to array");
2803
}
2804

    
2805

    
2806
void v8::ArrayBuffer::CheckCast(Value* that) {
2807
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2808
  ApiCheck(obj->IsJSArrayBuffer(),
2809
           "v8::ArrayBuffer::Cast()",
2810
           "Could not convert to ArrayBuffer");
2811
}
2812

    
2813

    
2814
void v8::ArrayBufferView::CheckCast(Value* that) {
2815
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2816
  ApiCheck(obj->IsJSArrayBufferView(),
2817
           "v8::ArrayBufferView::Cast()",
2818
           "Could not convert to ArrayBufferView");
2819
}
2820

    
2821

    
2822
void v8::TypedArray::CheckCast(Value* that) {
2823
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2824
  ApiCheck(obj->IsJSTypedArray(),
2825
           "v8::TypedArray::Cast()",
2826
           "Could not convert to TypedArray");
2827
}
2828

    
2829

    
2830
#define CHECK_TYPED_ARRAY_CAST(ApiClass, typeConst)                         \
2831
  void v8::ApiClass::CheckCast(Value* that) {                               \
2832
    i::Handle<i::Object> obj = Utils::OpenHandle(that);                     \
2833
    ApiCheck(obj->IsJSTypedArray() &&                                       \
2834
             i::JSTypedArray::cast(*obj)->type() == typeConst,              \
2835
             "v8::" #ApiClass "::Cast()",                                   \
2836
             "Could not convert to " #ApiClass);                            \
2837
  }
2838

    
2839

    
2840
TYPED_ARRAY_LIST(CHECK_TYPED_ARRAY_CAST)
2841

    
2842
#undef CHECK_TYPED_ARRAY_CAST
2843

    
2844

    
2845
void v8::DataView::CheckCast(Value* that) {
2846
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2847
  ApiCheck(obj->IsJSDataView(),
2848
           "v8::DataView::Cast()",
2849
           "Could not convert to DataView");
2850
}
2851

    
2852

    
2853
void v8::Date::CheckCast(v8::Value* that) {
2854
  i::Isolate* isolate = i::Isolate::Current();
2855
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2856
  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Date_string()),
2857
           "v8::Date::Cast()",
2858
           "Could not convert to date");
2859
}
2860

    
2861

    
2862
void v8::StringObject::CheckCast(v8::Value* that) {
2863
  i::Isolate* isolate = i::Isolate::Current();
2864
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2865
  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->String_string()),
2866
           "v8::StringObject::Cast()",
2867
           "Could not convert to StringObject");
2868
}
2869

    
2870

    
2871
void v8::SymbolObject::CheckCast(v8::Value* that) {
2872
  i::Isolate* isolate = i::Isolate::Current();
2873
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2874
  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
2875
           "v8::SymbolObject::Cast()",
2876
           "Could not convert to SymbolObject");
2877
}
2878

    
2879

    
2880
void v8::NumberObject::CheckCast(v8::Value* that) {
2881
  i::Isolate* isolate = i::Isolate::Current();
2882
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2883
  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Number_string()),
2884
           "v8::NumberObject::Cast()",
2885
           "Could not convert to NumberObject");
2886
}
2887

    
2888

    
2889
void v8::BooleanObject::CheckCast(v8::Value* that) {
2890
  i::Isolate* isolate = i::Isolate::Current();
2891
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2892
  ApiCheck(obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
2893
           "v8::BooleanObject::Cast()",
2894
           "Could not convert to BooleanObject");
2895
}
2896

    
2897

    
2898
void v8::RegExp::CheckCast(v8::Value* that) {
2899
  i::Handle<i::Object> obj = Utils::OpenHandle(that);
2900
  ApiCheck(obj->IsJSRegExp(),
2901
           "v8::RegExp::Cast()",
2902
           "Could not convert to regular expression");
2903
}
2904

    
2905

    
2906
bool Value::BooleanValue() const {
2907
  return Utils::OpenHandle(this)->BooleanValue();
2908
}
2909

    
2910

    
2911
double Value::NumberValue() const {
2912
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2913
  i::Handle<i::Object> num;
2914
  if (obj->IsNumber()) {
2915
    num = obj;
2916
  } else {
2917
    i::Isolate* isolate = i::Isolate::Current();
2918
    LOG_API(isolate, "NumberValue");
2919
    ENTER_V8(isolate);
2920
    EXCEPTION_PREAMBLE(isolate);
2921
    num = i::Execution::ToNumber(isolate, obj, &has_pending_exception);
2922
    EXCEPTION_BAILOUT_CHECK(isolate, i::OS::nan_value());
2923
  }
2924
  return num->Number();
2925
}
2926

    
2927

    
2928
int64_t Value::IntegerValue() const {
2929
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2930
  i::Handle<i::Object> num;
2931
  if (obj->IsNumber()) {
2932
    num = obj;
2933
  } else {
2934
    i::Isolate* isolate = i::Isolate::Current();
2935
    LOG_API(isolate, "IntegerValue");
2936
    ENTER_V8(isolate);
2937
    EXCEPTION_PREAMBLE(isolate);
2938
    num = i::Execution::ToInteger(isolate, obj, &has_pending_exception);
2939
    EXCEPTION_BAILOUT_CHECK(isolate, 0);
2940
  }
2941
  if (num->IsSmi()) {
2942
    return i::Smi::cast(*num)->value();
2943
  } else {
2944
    return static_cast<int64_t>(num->Number());
2945
  }
2946
}
2947

    
2948

    
2949
Local<Int32> Value::ToInt32() const {
2950
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2951
  i::Handle<i::Object> num;
2952
  if (obj->IsSmi()) {
2953
    num = obj;
2954
  } else {
2955
    i::Isolate* isolate = i::Isolate::Current();
2956
    LOG_API(isolate, "ToInt32");
2957
    ENTER_V8(isolate);
2958
    EXCEPTION_PREAMBLE(isolate);
2959
    num = i::Execution::ToInt32(isolate, obj, &has_pending_exception);
2960
    EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
2961
  }
2962
  return ToApiHandle<Int32>(num);
2963
}
2964

    
2965

    
2966
Local<Uint32> Value::ToUint32() const {
2967
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2968
  i::Handle<i::Object> num;
2969
  if (obj->IsSmi()) {
2970
    num = obj;
2971
  } else {
2972
    i::Isolate* isolate = i::Isolate::Current();
2973
    LOG_API(isolate, "ToUInt32");
2974
    ENTER_V8(isolate);
2975
    EXCEPTION_PREAMBLE(isolate);
2976
    num = i::Execution::ToUint32(isolate, obj, &has_pending_exception);
2977
    EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2978
  }
2979
  return ToApiHandle<Uint32>(num);
2980
}
2981

    
2982

    
2983
Local<Uint32> Value::ToArrayIndex() const {
2984
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
2985
  if (obj->IsSmi()) {
2986
    if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2987
    return Local<Uint32>();
2988
  }
2989
  i::Isolate* isolate = i::Isolate::Current();
2990
  LOG_API(isolate, "ToArrayIndex");
2991
  ENTER_V8(isolate);
2992
  EXCEPTION_PREAMBLE(isolate);
2993
  i::Handle<i::Object> string_obj =
2994
      i::Execution::ToString(isolate, obj, &has_pending_exception);
2995
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2996
  i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2997
  uint32_t index;
2998
  if (str->AsArrayIndex(&index)) {
2999
    i::Handle<i::Object> value;
3000
    if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
3001
      value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
3002
    } else {
3003
      value = isolate->factory()->NewNumber(index);
3004
    }
3005
    return Utils::Uint32ToLocal(value);
3006
  }
3007
  return Local<Uint32>();
3008
}
3009

    
3010

    
3011
int32_t Value::Int32Value() const {
3012
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
3013
  if (obj->IsSmi()) {
3014
    return i::Smi::cast(*obj)->value();
3015
  } else {
3016
    i::Isolate* isolate = i::Isolate::Current();
3017
    LOG_API(isolate, "Int32Value (slow)");
3018
    ENTER_V8(isolate);
3019
    EXCEPTION_PREAMBLE(isolate);
3020
    i::Handle<i::Object> num =
3021
        i::Execution::ToInt32(isolate, obj, &has_pending_exception);
3022
    EXCEPTION_BAILOUT_CHECK(isolate, 0);
3023
    if (num->IsSmi()) {
3024
      return i::Smi::cast(*num)->value();
3025
    } else {
3026
      return static_cast<int32_t>(num->Number());
3027
    }
3028
  }
3029
}
3030

    
3031

    
3032
bool Value::Equals(Handle<Value> that) const {
3033
  i::Isolate* isolate = i::Isolate::Current();
3034
  if (EmptyCheck("v8::Value::Equals()", this) ||
3035
      EmptyCheck("v8::Value::Equals()", that)) {
3036
    return false;
3037
  }
3038
  LOG_API(isolate, "Equals");
3039
  ENTER_V8(isolate);
3040
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
3041
  i::Handle<i::Object> other = Utils::OpenHandle(*that);
3042
  // If both obj and other are JSObjects, we'd better compare by identity
3043
  // immediately when going into JS builtin.  The reason is Invoke
3044
  // would overwrite global object receiver with global proxy.
3045
  if (obj->IsJSObject() && other->IsJSObject()) {
3046
    return *obj == *other;
3047
  }
3048
  i::Handle<i::Object> args[] = { other };
3049
  EXCEPTION_PREAMBLE(isolate);
3050
  i::Handle<i::Object> result =
3051
      CallV8HeapFunction("EQUALS", obj, ARRAY_SIZE(args), args,
3052
                         &has_pending_exception);
3053
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3054
  return *result == i::Smi::FromInt(i::EQUAL);
3055
}
3056

    
3057

    
3058
bool Value::StrictEquals(Handle<Value> that) const {
3059
  i::Isolate* isolate = i::Isolate::Current();
3060
  if (EmptyCheck("v8::Value::StrictEquals()", this) ||
3061
      EmptyCheck("v8::Value::StrictEquals()", that)) {
3062
    return false;
3063
  }
3064
  LOG_API(isolate, "StrictEquals");
3065
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
3066
  i::Handle<i::Object> other = Utils::OpenHandle(*that);
3067
  // Must check HeapNumber first, since NaN !== NaN.
3068
  if (obj->IsHeapNumber()) {
3069
    if (!other->IsNumber()) return false;
3070
    double x = obj->Number();
3071
    double y = other->Number();
3072
    // Must check explicitly for NaN:s on Windows, but -0 works fine.
3073
    return x == y && !std::isnan(x) && !std::isnan(y);
3074
  } else if (*obj == *other) {  // Also covers Booleans.
3075
    return true;
3076
  } else if (obj->IsSmi()) {
3077
    return other->IsNumber() && obj->Number() == other->Number();
3078
  } else if (obj->IsString()) {
3079
    return other->IsString() &&
3080
      i::String::cast(*obj)->Equals(i::String::cast(*other));
3081
  } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
3082
    return other->IsUndefined() || other->IsUndetectableObject();
3083
  } else {
3084
    return false;
3085
  }
3086
}
3087

    
3088

    
3089
bool Value::SameValue(Handle<Value> that) const {
3090
  i::Isolate* isolate = i::Isolate::Current();
3091
  if (EmptyCheck("v8::Value::SameValue()", this) ||
3092
      EmptyCheck("v8::Value::SameValue()", that)) {
3093
    return false;
3094
  }
3095
  LOG_API(isolate, "SameValue");
3096
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
3097
  i::Handle<i::Object> other = Utils::OpenHandle(*that);
3098
  return obj->SameValue(*other);
3099
}
3100

    
3101

    
3102
uint32_t Value::Uint32Value() const {
3103
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
3104
  if (obj->IsSmi()) {
3105
    return i::Smi::cast(*obj)->value();
3106
  } else {
3107
    i::Isolate* isolate = i::Isolate::Current();
3108
    LOG_API(isolate, "Uint32Value");
3109
    ENTER_V8(isolate);
3110
    EXCEPTION_PREAMBLE(isolate);
3111
    i::Handle<i::Object> num =
3112
        i::Execution::ToUint32(isolate, obj, &has_pending_exception);
3113
    EXCEPTION_BAILOUT_CHECK(isolate, 0);
3114
    if (num->IsSmi()) {
3115
      return i::Smi::cast(*num)->value();
3116
    } else {
3117
      return static_cast<uint32_t>(num->Number());
3118
    }
3119
  }
3120
}
3121

    
3122

    
3123
bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value,
3124
                     v8::PropertyAttribute attribs) {
3125
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3126
  ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3127
  ENTER_V8(isolate);
3128
  i::HandleScope scope(isolate);
3129
  i::Handle<i::Object> self = Utils::OpenHandle(this);
3130
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3131
  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3132
  EXCEPTION_PREAMBLE(isolate);
3133
  i::Handle<i::Object> obj = i::SetProperty(
3134
      isolate,
3135
      self,
3136
      key_obj,
3137
      value_obj,
3138
      static_cast<PropertyAttributes>(attribs),
3139
      i::kNonStrictMode);
3140
  has_pending_exception = obj.is_null();
3141
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3142
  return true;
3143
}
3144

    
3145

    
3146
bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
3147
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3148
  ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3149
  ENTER_V8(isolate);
3150
  i::HandleScope scope(isolate);
3151
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3152
  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3153
  EXCEPTION_PREAMBLE(isolate);
3154
  i::Handle<i::Object> obj = i::JSObject::SetElement(
3155
      self,
3156
      index,
3157
      value_obj,
3158
      NONE,
3159
      i::kNonStrictMode);
3160
  has_pending_exception = obj.is_null();
3161
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3162
  return true;
3163
}
3164

    
3165

    
3166
bool v8::Object::ForceSet(v8::Handle<Value> key,
3167
                          v8::Handle<Value> value,
3168
                          v8::PropertyAttribute attribs) {
3169
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3170
  ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
3171
  ENTER_V8(isolate);
3172
  i::HandleScope scope(isolate);
3173
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3174
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3175
  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3176
  EXCEPTION_PREAMBLE(isolate);
3177
  i::Handle<i::Object> obj = i::ForceSetProperty(
3178
      self,
3179
      key_obj,
3180
      value_obj,
3181
      static_cast<PropertyAttributes>(attribs));
3182
  has_pending_exception = obj.is_null();
3183
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3184
  return true;
3185
}
3186

    
3187

    
3188
bool v8::Object::ForceDelete(v8::Handle<Value> key) {
3189
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3190
  ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
3191
  ENTER_V8(isolate);
3192
  i::HandleScope scope(isolate);
3193
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3194
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3195

    
3196
  // When deleting a property on the global object using ForceDelete
3197
  // deoptimize all functions as optimized code does not check for the hole
3198
  // value with DontDelete properties.  We have to deoptimize all contexts
3199
  // because of possible cross-context inlined functions.
3200
  if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
3201
    i::Deoptimizer::DeoptimizeAll(isolate);
3202
  }
3203

    
3204
  EXCEPTION_PREAMBLE(isolate);
3205
  i::Handle<i::Object> obj = i::ForceDeleteProperty(self, key_obj);
3206
  has_pending_exception = obj.is_null();
3207
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3208
  return obj->IsTrue();
3209
}
3210

    
3211

    
3212
Local<Value> v8::Object::Get(v8::Handle<Value> key) {
3213
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3214
  ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3215
  ENTER_V8(isolate);
3216
  i::Handle<i::Object> self = Utils::OpenHandle(this);
3217
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3218
  EXCEPTION_PREAMBLE(isolate);
3219
  i::Handle<i::Object> result = i::GetProperty(isolate, self, key_obj);
3220
  has_pending_exception = result.is_null();
3221
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3222
  return Utils::ToLocal(result);
3223
}
3224

    
3225

    
3226
Local<Value> v8::Object::Get(uint32_t index) {
3227
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3228
  ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3229
  ENTER_V8(isolate);
3230
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3231
  EXCEPTION_PREAMBLE(isolate);
3232
  i::Handle<i::Object> result = i::Object::GetElement(isolate, self, index);
3233
  has_pending_exception = result.is_null();
3234
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3235
  return Utils::ToLocal(result);
3236
}
3237

    
3238

    
3239
PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
3240
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3241
  ON_BAILOUT(isolate, "v8::Object::GetPropertyAttribute()",
3242
             return static_cast<PropertyAttribute>(NONE));
3243
  ENTER_V8(isolate);
3244
  i::HandleScope scope(isolate);
3245
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3246
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3247
  if (!key_obj->IsName()) {
3248
    EXCEPTION_PREAMBLE(isolate);
3249
    key_obj = i::Execution::ToString(isolate, key_obj, &has_pending_exception);
3250
    EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3251
  }
3252
  i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
3253
  PropertyAttributes result = self->GetPropertyAttribute(*key_name);
3254
  if (result == ABSENT) return static_cast<PropertyAttribute>(NONE);
3255
  return static_cast<PropertyAttribute>(result);
3256
}
3257

    
3258

    
3259
Local<Value> v8::Object::GetPrototype() {
3260
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3261
  ON_BAILOUT(isolate, "v8::Object::GetPrototype()",
3262
             return Local<v8::Value>());
3263
  ENTER_V8(isolate);
3264
  i::Handle<i::Object> self = Utils::OpenHandle(this);
3265
  i::Handle<i::Object> result(self->GetPrototype(isolate), isolate);
3266
  return Utils::ToLocal(result);
3267
}
3268

    
3269

    
3270
bool v8::Object::SetPrototype(Handle<Value> value) {
3271
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3272
  ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
3273
  ENTER_V8(isolate);
3274
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3275
  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3276
  // We do not allow exceptions thrown while setting the prototype
3277
  // to propagate outside.
3278
  TryCatch try_catch;
3279
  EXCEPTION_PREAMBLE(isolate);
3280
  i::Handle<i::Object> result = i::JSObject::SetPrototype(self, value_obj);
3281
  has_pending_exception = result.is_null();
3282
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3283
  return true;
3284
}
3285

    
3286

    
3287
Local<Object> v8::Object::FindInstanceInPrototypeChain(
3288
    v8::Handle<FunctionTemplate> tmpl) {
3289
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3290
  ON_BAILOUT(isolate,
3291
             "v8::Object::FindInstanceInPrototypeChain()",
3292
             return Local<v8::Object>());
3293
  ENTER_V8(isolate);
3294
  i::JSObject* object = *Utils::OpenHandle(this);
3295
  i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
3296
  while (!object->IsInstanceOf(tmpl_info)) {
3297
    i::Object* prototype = object->GetPrototype();
3298
    if (!prototype->IsJSObject()) return Local<Object>();
3299
    object = i::JSObject::cast(prototype);
3300
  }
3301
  return Utils::ToLocal(i::Handle<i::JSObject>(object));
3302
}
3303

    
3304

    
3305
Local<Array> v8::Object::GetPropertyNames() {
3306
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3307
  ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
3308
             return Local<v8::Array>());
3309
  ENTER_V8(isolate);
3310
  i::HandleScope scope(isolate);
3311
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3312
  bool threw = false;
3313
  i::Handle<i::FixedArray> value =
3314
      i::GetKeysInFixedArrayFor(self, i::INCLUDE_PROTOS, &threw);
3315
  if (threw) return Local<v8::Array>();
3316
  // Because we use caching to speed up enumeration it is important
3317
  // to never change the result of the basic enumeration function so
3318
  // we clone the result.
3319
  i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3320
  i::Handle<i::JSArray> result =
3321
      isolate->factory()->NewJSArrayWithElements(elms);
3322
  return Utils::ToLocal(scope.CloseAndEscape(result));
3323
}
3324

    
3325

    
3326
Local<Array> v8::Object::GetOwnPropertyNames() {
3327
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3328
  ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()",
3329
             return Local<v8::Array>());
3330
  ENTER_V8(isolate);
3331
  i::HandleScope scope(isolate);
3332
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3333
  bool threw = false;
3334
  i::Handle<i::FixedArray> value =
3335
      i::GetKeysInFixedArrayFor(self, i::LOCAL_ONLY, &threw);
3336
  if (threw) return Local<v8::Array>();
3337
  // Because we use caching to speed up enumeration it is important
3338
  // to never change the result of the basic enumeration function so
3339
  // we clone the result.
3340
  i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3341
  i::Handle<i::JSArray> result =
3342
      isolate->factory()->NewJSArrayWithElements(elms);
3343
  return Utils::ToLocal(scope.CloseAndEscape(result));
3344
}
3345

    
3346

    
3347
Local<String> v8::Object::ObjectProtoToString() {
3348
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3349
  ON_BAILOUT(isolate, "v8::Object::ObjectProtoToString()",
3350
             return Local<v8::String>());
3351
  ENTER_V8(isolate);
3352
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3353

    
3354
  i::Handle<i::Object> name(self->class_name(), isolate);
3355

    
3356
  // Native implementation of Object.prototype.toString (v8natives.js):
3357
  //   var c = %_ClassOf(this);
3358
  //   if (c === 'Arguments') c  = 'Object';
3359
  //   return "[object " + c + "]";
3360

    
3361
  if (!name->IsString()) {
3362
    return v8::String::New("[object ]");
3363

    
3364
  } else {
3365
    i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
3366
    if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) {
3367
      return v8::String::New("[object Object]");
3368

    
3369
    } else {
3370
      const char* prefix = "[object ";
3371
      Local<String> str = Utils::ToLocal(class_name);
3372
      const char* postfix = "]";
3373

    
3374
      int prefix_len = i::StrLength(prefix);
3375
      int str_len = str->Utf8Length();
3376
      int postfix_len = i::StrLength(postfix);
3377

    
3378
      int buf_len = prefix_len + str_len + postfix_len;
3379
      i::ScopedVector<char> buf(buf_len);
3380

    
3381
      // Write prefix.
3382
      char* ptr = buf.start();
3383
      i::OS::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize);
3384
      ptr += prefix_len;
3385

    
3386
      // Write real content.
3387
      str->WriteUtf8(ptr, str_len);
3388
      ptr += str_len;
3389

    
3390
      // Write postfix.
3391
      i::OS::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize);
3392

    
3393
      // Copy the buffer into a heap-allocated string and return it.
3394
      Local<String> result = v8::String::New(buf.start(), buf_len);
3395
      return result;
3396
    }
3397
  }
3398
}
3399

    
3400

    
3401
Local<Value> v8::Object::GetConstructor() {
3402
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3403
  ON_BAILOUT(isolate, "v8::Object::GetConstructor()",
3404
             return Local<v8::Function>());
3405
  ENTER_V8(isolate);
3406
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3407
  i::Handle<i::Object> constructor(self->GetConstructor(), isolate);
3408
  return Utils::ToLocal(constructor);
3409
}
3410

    
3411

    
3412
Local<String> v8::Object::GetConstructorName() {
3413
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3414
  ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
3415
             return Local<v8::String>());
3416
  ENTER_V8(isolate);
3417
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3418
  i::Handle<i::String> name(self->constructor_name());
3419
  return Utils::ToLocal(name);
3420
}
3421

    
3422

    
3423
bool v8::Object::Delete(v8::Handle<Value> key) {
3424
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3425
  ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
3426
  ENTER_V8(isolate);
3427
  i::HandleScope scope(isolate);
3428
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3429
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3430
  EXCEPTION_PREAMBLE(isolate);
3431
  i::Handle<i::Object> obj = i::DeleteProperty(self, key_obj);
3432
  has_pending_exception = obj.is_null();
3433
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3434
  return obj->IsTrue();
3435
}
3436

    
3437

    
3438
bool v8::Object::Has(v8::Handle<Value> key) {
3439
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3440
  ON_BAILOUT(isolate, "v8::Object::Has()", return false);
3441
  ENTER_V8(isolate);
3442
  i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
3443
  i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3444
  EXCEPTION_PREAMBLE(isolate);
3445
  i::Handle<i::Object> obj = i::HasProperty(self, key_obj);
3446
  has_pending_exception = obj.is_null();
3447
  EXCEPTION_BAILOUT_CHECK(isolate, false);
3448
  return obj->IsTrue();
3449
}
3450

    
3451

    
3452
bool v8::Object::Delete(uint32_t index) {
3453
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3454
  ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
3455
             return false);
3456
  ENTER_V8(isolate);
3457
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
3458
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3459
  return i::JSReceiver::DeleteElement(self, index)->IsTrue();
3460
}
3461

    
3462

    
3463
bool v8::Object::Has(uint32_t index) {
3464
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3465
  ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
3466
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3467
  return i::JSReceiver::HasElement(self, index);
3468
}
3469

    
3470

    
3471
template<typename Setter, typename Getter, typename Data>
3472
static inline bool ObjectSetAccessor(Object* obj,
3473
                                     Handle<String> name,
3474
                                     Setter getter,
3475
                                     Getter setter,
3476
                                     Data data,
3477
                                     AccessControl settings,
3478
                                     PropertyAttribute attributes) {
3479
  i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate();
3480
  ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
3481
  ENTER_V8(isolate);
3482
  i::HandleScope scope(isolate);
3483
  v8::Handle<AccessorSignature> signature;
3484
  i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
3485
      name, getter, setter, data, settings, attributes, signature);
3486
  if (info.is_null()) return false;
3487
  bool fast = Utils::OpenHandle(obj)->HasFastProperties();
3488
  i::Handle<i::Object> result =
3489
      i::JSObject::SetAccessor(Utils::OpenHandle(obj), info);
3490
  if (result.is_null() || result->IsUndefined()) return false;
3491
  if (fast) i::JSObject::TransformToFastProperties(Utils::OpenHandle(obj), 0);
3492
  return true;
3493
}
3494

    
3495

    
3496
bool Object::SetAccessor(Handle<String> name,
3497
                         AccessorGetterCallback getter,
3498
                         AccessorSetterCallback setter,
3499
                         v8::Handle<Value> data,
3500
                         AccessControl settings,
3501
                         PropertyAttribute attributes) {
3502
  return ObjectSetAccessor(
3503
      this, name, getter, setter, data, settings, attributes);
3504
}
3505

    
3506

    
3507
bool Object::SetDeclaredAccessor(Local<String> name,
3508
                                 Local<DeclaredAccessorDescriptor> descriptor,
3509
                                 PropertyAttribute attributes,
3510
                                 AccessControl settings) {
3511
  void* null = NULL;
3512
  return ObjectSetAccessor(
3513
      this, name, descriptor, null, null, settings, attributes);
3514
}
3515

    
3516

    
3517
bool v8::Object::HasOwnProperty(Handle<String> key) {
3518
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3519
  ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
3520
             return false);
3521
  return i::JSReceiver::HasLocalProperty(
3522
      Utils::OpenHandle(this), Utils::OpenHandle(*key));
3523
}
3524

    
3525

    
3526
bool v8::Object::HasRealNamedProperty(Handle<String> key) {
3527
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3528
  ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
3529
             return false);
3530
  return i::JSObject::HasRealNamedProperty(Utils::OpenHandle(this),
3531
                                           Utils::OpenHandle(*key));
3532
}
3533

    
3534

    
3535
bool v8::Object::HasRealIndexedProperty(uint32_t index) {
3536
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3537
  ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
3538
             return false);
3539
  return i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
3540
}
3541

    
3542

    
3543
bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
3544
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3545
  ON_BAILOUT(isolate,
3546
             "v8::Object::HasRealNamedCallbackProperty()",
3547
             return false);
3548
  ENTER_V8(isolate);
3549
  return i::JSObject::HasRealNamedCallbackProperty(Utils::OpenHandle(this),
3550
                                                   Utils::OpenHandle(*key));
3551
}
3552

    
3553

    
3554
bool v8::Object::HasNamedLookupInterceptor() {
3555
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3556
  ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
3557
             return false);
3558
  return Utils::OpenHandle(this)->HasNamedInterceptor();
3559
}
3560

    
3561

    
3562
bool v8::Object::HasIndexedLookupInterceptor() {
3563
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3564
  ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
3565
             return false);
3566
  return Utils::OpenHandle(this)->HasIndexedInterceptor();
3567
}
3568

    
3569

    
3570
static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
3571
                                        i::Handle<i::JSObject> receiver,
3572
                                        i::Handle<i::String> name,
3573
                                        i::LookupResult* lookup) {
3574
  if (!lookup->IsProperty()) {
3575
    // No real property was found.
3576
    return Local<Value>();
3577
  }
3578

    
3579
  // If the property being looked up is a callback, it can throw
3580
  // an exception.
3581
  EXCEPTION_PREAMBLE(isolate);
3582
  PropertyAttributes ignored;
3583
  i::Handle<i::Object> result =
3584
      i::Object::GetProperty(receiver, receiver, lookup, name,
3585
                             &ignored);
3586
  has_pending_exception = result.is_null();
3587
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3588

    
3589
  return Utils::ToLocal(result);
3590
}
3591

    
3592

    
3593
Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
3594
      Handle<String> key) {
3595
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3596
  ON_BAILOUT(isolate,
3597
             "v8::Object::GetRealNamedPropertyInPrototypeChain()",
3598
             return Local<Value>());
3599
  ENTER_V8(isolate);
3600
  i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3601
  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3602
  i::LookupResult lookup(isolate);
3603
  self_obj->LookupRealNamedPropertyInPrototypes(*key_obj, &lookup);
3604
  return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3605
}
3606

    
3607

    
3608
Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
3609
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3610
  ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
3611
             return Local<Value>());
3612
  ENTER_V8(isolate);
3613
  i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3614
  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3615
  i::LookupResult lookup(isolate);
3616
  self_obj->LookupRealNamedProperty(*key_obj, &lookup);
3617
  return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3618
}
3619

    
3620

    
3621
// Turns on access checks by copying the map and setting the check flag.
3622
// Because the object gets a new map, existing inline cache caching
3623
// the old map of this object will fail.
3624
void v8::Object::TurnOnAccessCheck() {
3625
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3626
  ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
3627
  ENTER_V8(isolate);
3628
  i::HandleScope scope(isolate);
3629
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3630

    
3631
  // When turning on access checks for a global object deoptimize all functions
3632
  // as optimized code does not always handle access checks.
3633
  i::Deoptimizer::DeoptimizeGlobalObject(*obj);
3634

    
3635
  i::Handle<i::Map> new_map =
3636
      isolate->factory()->CopyMap(i::Handle<i::Map>(obj->map()));
3637
  new_map->set_is_access_check_needed(true);
3638
  obj->set_map(*new_map);
3639
}
3640

    
3641

    
3642
bool v8::Object::IsDirty() {
3643
  return Utils::OpenHandle(this)->IsDirty();
3644
}
3645

    
3646

    
3647
Local<v8::Object> v8::Object::Clone() {
3648
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3649
  ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
3650
  ENTER_V8(isolate);
3651
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3652
  EXCEPTION_PREAMBLE(isolate);
3653
  i::Handle<i::JSObject> result = i::JSObject::Copy(self);
3654
  has_pending_exception = result.is_null();
3655
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
3656
  return Utils::ToLocal(result);
3657
}
3658

    
3659

    
3660
static i::Context* GetCreationContext(i::JSObject* object) {
3661
  i::Object* constructor = object->map()->constructor();
3662
  i::JSFunction* function;
3663
  if (!constructor->IsJSFunction()) {
3664
    // Functions have null as a constructor,
3665
    // but any JSFunction knows its context immediately.
3666
    ASSERT(object->IsJSFunction());
3667
    function = i::JSFunction::cast(object);
3668
  } else {
3669
    function = i::JSFunction::cast(constructor);
3670
  }
3671
  return function->context()->native_context();
3672
}
3673

    
3674

    
3675
Local<v8::Context> v8::Object::CreationContext() {
3676
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3677
  ON_BAILOUT(isolate,
3678
             "v8::Object::CreationContext()", return Local<v8::Context>());
3679
  ENTER_V8(isolate);
3680
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3681
  i::Context* context = GetCreationContext(*self);
3682
  return Utils::ToLocal(i::Handle<i::Context>(context));
3683
}
3684

    
3685

    
3686
int v8::Object::GetIdentityHash() {
3687
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3688
  ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
3689
  ENTER_V8(isolate);
3690
  i::HandleScope scope(isolate);
3691
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3692
  return i::JSObject::GetIdentityHash(self);
3693
}
3694

    
3695

    
3696
bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
3697
                                v8::Handle<v8::Value> value) {
3698
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3699
  ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
3700
  if (value.IsEmpty()) return DeleteHiddenValue(key);
3701
  ENTER_V8(isolate);
3702
  i::HandleScope scope(isolate);
3703
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3704
  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3705
  i::Handle<i::String> key_string =
3706
      isolate->factory()->InternalizeString(key_obj);
3707
  i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3708
  i::Handle<i::Object> result =
3709
      i::JSObject::SetHiddenProperty(self, key_string, value_obj);
3710
  return *result == *self;
3711
}
3712

    
3713

    
3714
v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
3715
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3716
  ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
3717
             return Local<v8::Value>());
3718
  ENTER_V8(isolate);
3719
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3720
  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3721
  i::Handle<i::String> key_string =
3722
      isolate->factory()->InternalizeString(key_obj);
3723
  i::Handle<i::Object> result(self->GetHiddenProperty(*key_string), isolate);
3724
  if (result->IsTheHole()) return v8::Local<v8::Value>();
3725
  return Utils::ToLocal(result);
3726
}
3727

    
3728

    
3729
bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
3730
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3731
  ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
3732
  ENTER_V8(isolate);
3733
  i::HandleScope scope(isolate);
3734
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3735
  i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3736
  i::Handle<i::String> key_string =
3737
      isolate->factory()->InternalizeString(key_obj);
3738
  i::JSObject::DeleteHiddenProperty(self, key_string);
3739
  return true;
3740
}
3741

    
3742

    
3743
namespace {
3744

    
3745
static i::ElementsKind GetElementsKindFromExternalArrayType(
3746
    ExternalArrayType array_type) {
3747
  switch (array_type) {
3748
    case kExternalByteArray:
3749
      return i::EXTERNAL_BYTE_ELEMENTS;
3750
      break;
3751
    case kExternalUnsignedByteArray:
3752
      return i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS;
3753
      break;
3754
    case kExternalShortArray:
3755
      return i::EXTERNAL_SHORT_ELEMENTS;
3756
      break;
3757
    case kExternalUnsignedShortArray:
3758
      return i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS;
3759
      break;
3760
    case kExternalIntArray:
3761
      return i::EXTERNAL_INT_ELEMENTS;
3762
      break;
3763
    case kExternalUnsignedIntArray:
3764
      return i::EXTERNAL_UNSIGNED_INT_ELEMENTS;
3765
      break;
3766
    case kExternalFloatArray:
3767
      return i::EXTERNAL_FLOAT_ELEMENTS;
3768
      break;
3769
    case kExternalDoubleArray:
3770
      return i::EXTERNAL_DOUBLE_ELEMENTS;
3771
      break;
3772
    case kExternalPixelArray:
3773
      return i::EXTERNAL_PIXEL_ELEMENTS;
3774
      break;
3775
  }
3776
  UNREACHABLE();
3777
  return i::DICTIONARY_ELEMENTS;
3778
}
3779

    
3780

    
3781
void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
3782
                                  void* data,
3783
                                  ExternalArrayType array_type,
3784
                                  int length) {
3785
  i::Isolate* isolate = object->GetIsolate();
3786
  i::Handle<i::ExternalArray> array =
3787
      isolate->factory()->NewExternalArray(length, array_type, data);
3788

    
3789
  i::Handle<i::Map> external_array_map =
3790
      isolate->factory()->GetElementsTransitionMap(
3791
          object,
3792
          GetElementsKindFromExternalArrayType(array_type));
3793

    
3794
  object->set_map(*external_array_map);
3795
  object->set_elements(*array);
3796
}
3797

    
3798
}  // namespace
3799

    
3800

    
3801
void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
3802
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3803
  ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
3804
  ENTER_V8(isolate);
3805
  i::HandleScope scope(isolate);
3806
  if (!ApiCheck(length >= 0 && length <= i::ExternalPixelArray::kMaxLength,
3807
                "v8::Object::SetIndexedPropertiesToPixelData()",
3808
                "length exceeds max acceptable value")) {
3809
    return;
3810
  }
3811
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3812
  if (!ApiCheck(!self->IsJSArray(),
3813
                "v8::Object::SetIndexedPropertiesToPixelData()",
3814
                "JSArray is not supported")) {
3815
    return;
3816
  }
3817
  PrepareExternalArrayElements(self, data, kExternalPixelArray, length);
3818
}
3819

    
3820

    
3821
bool v8::Object::HasIndexedPropertiesInPixelData() {
3822
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3823
  ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
3824
             return false);
3825
  return self->HasExternalPixelElements();
3826
}
3827

    
3828

    
3829
uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
3830
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3831
  ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
3832
             return NULL);
3833
  if (self->HasExternalPixelElements()) {
3834
    return i::ExternalPixelArray::cast(self->elements())->
3835
        external_pixel_pointer();
3836
  } else {
3837
    return NULL;
3838
  }
3839
}
3840

    
3841

    
3842
int v8::Object::GetIndexedPropertiesPixelDataLength() {
3843
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3844
  ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
3845
             return -1);
3846
  if (self->HasExternalPixelElements()) {
3847
    return i::ExternalPixelArray::cast(self->elements())->length();
3848
  } else {
3849
    return -1;
3850
  }
3851
}
3852

    
3853

    
3854
void v8::Object::SetIndexedPropertiesToExternalArrayData(
3855
    void* data,
3856
    ExternalArrayType array_type,
3857
    int length) {
3858
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3859
  ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
3860
  ENTER_V8(isolate);
3861
  i::HandleScope scope(isolate);
3862
  if (!ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
3863
                "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3864
                "length exceeds max acceptable value")) {
3865
    return;
3866
  }
3867
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3868
  if (!ApiCheck(!self->IsJSArray(),
3869
                "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3870
                "JSArray is not supported")) {
3871
    return;
3872
  }
3873
  PrepareExternalArrayElements(self, data, array_type, length);
3874
}
3875

    
3876

    
3877
bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
3878
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3879
  ON_BAILOUT(self->GetIsolate(),
3880
             "v8::HasIndexedPropertiesInExternalArrayData()",
3881
             return false);
3882
  return self->HasExternalArrayElements();
3883
}
3884

    
3885

    
3886
void* v8::Object::GetIndexedPropertiesExternalArrayData() {
3887
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3888
  ON_BAILOUT(self->GetIsolate(),
3889
             "v8::GetIndexedPropertiesExternalArrayData()",
3890
             return NULL);
3891
  if (self->HasExternalArrayElements()) {
3892
    return i::ExternalArray::cast(self->elements())->external_pointer();
3893
  } else {
3894
    return NULL;
3895
  }
3896
}
3897

    
3898

    
3899
ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
3900
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3901
  ON_BAILOUT(self->GetIsolate(),
3902
             "v8::GetIndexedPropertiesExternalArrayDataType()",
3903
             return static_cast<ExternalArrayType>(-1));
3904
  switch (self->elements()->map()->instance_type()) {
3905
    case i::EXTERNAL_BYTE_ARRAY_TYPE:
3906
      return kExternalByteArray;
3907
    case i::EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
3908
      return kExternalUnsignedByteArray;
3909
    case i::EXTERNAL_SHORT_ARRAY_TYPE:
3910
      return kExternalShortArray;
3911
    case i::EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
3912
      return kExternalUnsignedShortArray;
3913
    case i::EXTERNAL_INT_ARRAY_TYPE:
3914
      return kExternalIntArray;
3915
    case i::EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
3916
      return kExternalUnsignedIntArray;
3917
    case i::EXTERNAL_FLOAT_ARRAY_TYPE:
3918
      return kExternalFloatArray;
3919
    case i::EXTERNAL_DOUBLE_ARRAY_TYPE:
3920
      return kExternalDoubleArray;
3921
    case i::EXTERNAL_PIXEL_ARRAY_TYPE:
3922
      return kExternalPixelArray;
3923
    default:
3924
      return static_cast<ExternalArrayType>(-1);
3925
  }
3926
}
3927

    
3928

    
3929
int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
3930
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3931
  ON_BAILOUT(self->GetIsolate(),
3932
             "v8::GetIndexedPropertiesExternalArrayDataLength()",
3933
             return 0);
3934
  if (self->HasExternalArrayElements()) {
3935
    return i::ExternalArray::cast(self->elements())->length();
3936
  } else {
3937
    return -1;
3938
  }
3939
}
3940

    
3941

    
3942
bool v8::Object::IsCallable() {
3943
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3944
  ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
3945
  ENTER_V8(isolate);
3946
  i::HandleScope scope(isolate);
3947
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3948
  if (obj->IsJSFunction()) return true;
3949
  return i::Execution::GetFunctionDelegate(isolate, obj)->IsJSFunction();
3950
}
3951

    
3952

    
3953
Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
3954
                                        int argc,
3955
                                        v8::Handle<v8::Value> argv[]) {
3956
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3957
  ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
3958
             return Local<v8::Value>());
3959
  LOG_API(isolate, "Object::CallAsFunction");
3960
  ENTER_V8(isolate);
3961
  i::Logger::TimerEventScope timer_scope(
3962
      isolate, i::Logger::TimerEventScope::v8_execute);
3963
  i::HandleScope scope(isolate);
3964
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3965
  i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3966
  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3967
  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3968
  i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
3969
  if (obj->IsJSFunction()) {
3970
    fun = i::Handle<i::JSFunction>::cast(obj);
3971
  } else {
3972
    EXCEPTION_PREAMBLE(isolate);
3973
    i::Handle<i::Object> delegate = i::Execution::TryGetFunctionDelegate(
3974
        isolate, obj, &has_pending_exception);
3975
    EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3976
    fun = i::Handle<i::JSFunction>::cast(delegate);
3977
    recv_obj = obj;
3978
  }
3979
  EXCEPTION_PREAMBLE(isolate);
3980
  i::Handle<i::Object> returned = i::Execution::Call(
3981
      isolate, fun, recv_obj, argc, args, &has_pending_exception, true);
3982
  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
3983
  return Utils::ToLocal(scope.CloseAndEscape(returned));
3984
}
3985

    
3986

    
3987
Local<v8::Value> Object::CallAsConstructor(int argc,
3988
                                           v8::Handle<v8::Value> argv[]) {
3989
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3990
  ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
3991
             return Local<v8::Object>());
3992
  LOG_API(isolate, "Object::CallAsConstructor");
3993
  ENTER_V8(isolate);
3994
  i::Logger::TimerEventScope timer_scope(
3995
      isolate, i::Logger::TimerEventScope::v8_execute);
3996
  i::HandleScope scope(isolate);
3997
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3998
  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3999
  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4000
  if (obj->IsJSFunction()) {
4001
    i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
4002
    EXCEPTION_PREAMBLE(isolate);
4003
    i::Handle<i::Object> returned =
4004
        i::Execution::New(fun, argc, args, &has_pending_exception);
4005
    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4006
    return Utils::ToLocal(scope.CloseAndEscape(
4007
        i::Handle<i::JSObject>::cast(returned)));
4008
  }
4009
  EXCEPTION_PREAMBLE(isolate);
4010
  i::Handle<i::Object> delegate = i::Execution::TryGetConstructorDelegate(
4011
      isolate, obj, &has_pending_exception);
4012
  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
4013
  if (!delegate->IsUndefined()) {
4014
    i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
4015
    EXCEPTION_PREAMBLE(isolate);
4016
    i::Handle<i::Object> returned = i::Execution::Call(
4017
        isolate, fun, obj, argc, args, &has_pending_exception);
4018
    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4019
    ASSERT(!delegate->IsUndefined());
4020
    return Utils::ToLocal(scope.CloseAndEscape(returned));
4021
  }
4022
  return Local<v8::Object>();
4023
}
4024

    
4025

    
4026
Local<Function> Function::New(Isolate* v8_isolate,
4027
                              FunctionCallback callback,
4028
                              Local<Value> data,
4029
                              int length) {
4030
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
4031
  LOG_API(isolate, "Function::New");
4032
  ENTER_V8(isolate);
4033
  return FunctionTemplateNew(
4034
      isolate, callback, data, Local<Signature>(), length, true)->
4035
          GetFunction();
4036
}
4037

    
4038

    
4039
Local<v8::Object> Function::NewInstance() const {
4040
  return NewInstance(0, NULL);
4041
}
4042

    
4043

    
4044
Local<v8::Object> Function::NewInstance(int argc,
4045
                                        v8::Handle<v8::Value> argv[]) const {
4046
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4047
  ON_BAILOUT(isolate, "v8::Function::NewInstance()",
4048
             return Local<v8::Object>());
4049
  LOG_API(isolate, "Function::NewInstance");
4050
  ENTER_V8(isolate);
4051
  i::Logger::TimerEventScope timer_scope(
4052
      isolate, i::Logger::TimerEventScope::v8_execute);
4053
  HandleScope scope(reinterpret_cast<Isolate*>(isolate));
4054
  i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
4055
  STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4056
  i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4057
  EXCEPTION_PREAMBLE(isolate);
4058
  i::Handle<i::Object> returned =
4059
      i::Execution::New(function, argc, args, &has_pending_exception);
4060
  EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4061
  return scope.Close(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
4062
}
4063

    
4064

    
4065
Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
4066
                                v8::Handle<v8::Value> argv[]) {
4067
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4068
  ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
4069
  LOG_API(isolate, "Function::Call");
4070
  ENTER_V8(isolate);
4071
  i::Logger::TimerEventScope timer_scope(
4072
      isolate, i::Logger::TimerEventScope::v8_execute);
4073
  i::Object* raw_result = NULL;
4074
  {
4075
    i::HandleScope scope(isolate);
4076
    i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
4077
    i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
4078
    STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4079
    i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4080
    EXCEPTION_PREAMBLE(isolate);
4081
    i::Handle<i::Object> returned = i::Execution::Call(
4082
        isolate, fun, recv_obj, argc, args, &has_pending_exception, true);
4083
    EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
4084
    raw_result = *returned;
4085
  }
4086
  i::Handle<i::Object> result(raw_result, isolate);
4087
  return Utils::ToLocal(result);
4088
}
4089

    
4090

    
4091
void Function::SetName(v8::Handle<v8::String> name) {
4092
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4093
  ENTER_V8(isolate);
4094
  USE(isolate);
4095
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4096
  func->shared()->set_name(*Utils::OpenHandle(*name));
4097
}
4098

    
4099

    
4100
Handle<Value> Function::GetName() const {
4101
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4102
  return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(),
4103
                                             func->GetIsolate()));
4104
}
4105

    
4106

    
4107
Handle<Value> Function::GetInferredName() const {
4108
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4109
  return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(),
4110
                                             func->GetIsolate()));
4111
}
4112

    
4113

    
4114
Handle<Value> Function::GetDisplayName() const {
4115
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4116
  ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
4117
             return ToApiHandle<Primitive>(
4118
                isolate->factory()->undefined_value()));
4119
  ENTER_V8(isolate);
4120
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4121
  i::Handle<i::String> property_name =
4122
      isolate->factory()->InternalizeOneByteString(
4123
          STATIC_ASCII_VECTOR("displayName"));
4124
  i::LookupResult lookup(isolate);
4125
  func->LookupRealNamedProperty(*property_name, &lookup);
4126
  if (lookup.IsFound()) {
4127
    i::Object* value = lookup.GetLazyValue();
4128
    if (value && value->IsString()) {
4129
      i::String* name = i::String::cast(value);
4130
      if (name->length() > 0) return Utils::ToLocal(i::Handle<i::String>(name));
4131
    }
4132
  }
4133
  return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
4134
}
4135

    
4136

    
4137
ScriptOrigin Function::GetScriptOrigin() const {
4138
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4139
  if (func->shared()->script()->IsScript()) {
4140
    i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4141
    i::Handle<i::Object> scriptName = GetScriptNameOrSourceURL(script);
4142
    v8::ScriptOrigin origin(
4143
      Utils::ToLocal(scriptName),
4144
      v8::Integer::New(script->line_offset()->value()),
4145
      v8::Integer::New(script->column_offset()->value()));
4146
    return origin;
4147
  }
4148
  return v8::ScriptOrigin(Handle<Value>());
4149
}
4150

    
4151

    
4152
const int Function::kLineOffsetNotFound = -1;
4153

    
4154

    
4155
int Function::GetScriptLineNumber() const {
4156
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4157
  if (func->shared()->script()->IsScript()) {
4158
    i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4159
    return i::GetScriptLineNumber(script, func->shared()->start_position());
4160
  }
4161
  return kLineOffsetNotFound;
4162
}
4163

    
4164

    
4165
int Function::GetScriptColumnNumber() const {
4166
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4167
  if (func->shared()->script()->IsScript()) {
4168
    i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4169
    return i::GetScriptColumnNumber(script, func->shared()->start_position());
4170
  }
4171
  return kLineOffsetNotFound;
4172
}
4173

    
4174

    
4175
bool Function::IsBuiltin() const {
4176
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4177
  return func->IsBuiltin();
4178
}
4179

    
4180

    
4181
Handle<Value> Function::GetScriptId() const {
4182
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4183
  i::Isolate* isolate = func->GetIsolate();
4184
  if (!func->shared()->script()->IsScript()) {
4185
    return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
4186
  }
4187
  i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4188
  return Utils::ToLocal(i::Handle<i::Object>(script->id(), isolate));
4189
}
4190

    
4191

    
4192
int Function::ScriptId() const {
4193
  i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4194
  if (!func->shared()->script()->IsScript()) return v8::Script::kNoScriptId;
4195
  i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4196
  return script->id()->value();
4197
}
4198

    
4199

    
4200
int String::Length() const {
4201
  i::Handle<i::String> str = Utils::OpenHandle(this);
4202
  return str->length();
4203
}
4204

    
4205

    
4206
bool String::IsOneByte() const {
4207
  i::Handle<i::String> str = Utils::OpenHandle(this);
4208
  return str->HasOnlyOneByteChars();
4209
}
4210

    
4211

    
4212
// Helpers for ContainsOnlyOneByteHelper
4213
template<size_t size> struct OneByteMask;
4214
template<> struct OneByteMask<4> {
4215
  static const uint32_t value = 0xFF00FF00;
4216
};
4217
template<> struct OneByteMask<8> {
4218
  static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00);
4219
};
4220
static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
4221
static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
4222
static inline bool Unaligned(const uint16_t* chars) {
4223
  return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
4224
}
4225

    
4226

    
4227
static inline const uint16_t* Align(const uint16_t* chars) {
4228
  return reinterpret_cast<uint16_t*>(
4229
    reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
4230
}
4231

    
4232
class ContainsOnlyOneByteHelper {
4233
 public:
4234
  ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
4235
  bool Check(i::String* string) {
4236
    i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
4237
    if (cons_string == NULL) return is_one_byte_;
4238
    return CheckCons(cons_string);
4239
  }
4240
  void VisitOneByteString(const uint8_t* chars, int length) {
4241
    // Nothing to do.
4242
  }
4243
  void VisitTwoByteString(const uint16_t* chars, int length) {
4244
    // Accumulated bits.
4245
    uintptr_t acc = 0;
4246
    // Align to uintptr_t.
4247
    const uint16_t* end = chars + length;
4248
    while (Unaligned(chars) && chars != end) {
4249
        acc |= *chars++;
4250
    }
4251
    // Read word aligned in blocks,
4252
    // checking the return value at the end of each block.
4253
    const uint16_t* aligned_end = Align(end);
4254
    const int increment = sizeof(uintptr_t)/sizeof(uint16_t);
4255
    const int inner_loops = 16;
4256
    while (chars + inner_loops*increment < aligned_end) {
4257
      for (int i = 0; i < inner_loops; i++) {
4258
        acc |= *reinterpret_cast<const uintptr_t*>(chars);
4259
        chars += increment;
4260
      }
4261
      // Check for early return.
4262
      if ((acc & kOneByteMask) != 0) {
4263
        is_one_byte_ = false;
4264
        return;
4265
      }
4266
    }
4267
    // Read the rest.
4268
    while (chars != end) {
4269
      acc |= *chars++;
4270
    }
4271
    // Check result.
4272
    if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
4273
  }
4274

    
4275
 private:
4276
  bool CheckCons(i::ConsString* cons_string) {
4277
    while (true) {
4278
      // Check left side if flat.
4279
      i::String* left = cons_string->first();
4280
      i::ConsString* left_as_cons =
4281
          i::String::VisitFlat(this, left, 0);
4282
      if (!is_one_byte_) return false;
4283
      // Check right side if flat.
4284
      i::String* right = cons_string->second();
4285
      i::ConsString* right_as_cons =
4286
          i::String::VisitFlat(this, right, 0);
4287
      if (!is_one_byte_) return false;
4288
      // Standard recurse/iterate trick.
4289
      if (left_as_cons != NULL && right_as_cons != NULL) {
4290
        if (left->length() < right->length()) {
4291
          CheckCons(left_as_cons);
4292
          cons_string = right_as_cons;
4293
        } else {
4294
          CheckCons(right_as_cons);
4295
          cons_string = left_as_cons;
4296
        }
4297
        // Check fast return.
4298
        if (!is_one_byte_) return false;
4299
        continue;
4300
      }
4301
      // Descend left in place.
4302
      if (left_as_cons != NULL) {
4303
        cons_string = left_as_cons;
4304
        continue;
4305
      }
4306
      // Descend right in place.
4307
      if (right_as_cons != NULL) {
4308
        cons_string = right_as_cons;
4309
        continue;
4310
      }
4311
      // Terminate.
4312
      break;
4313
    }
4314
    return is_one_byte_;
4315
  }
4316
  bool is_one_byte_;
4317
  DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper);
4318
};
4319

    
4320

    
4321
bool String::ContainsOnlyOneByte() const {
4322
  i::Handle<i::String> str = Utils::OpenHandle(this);
4323
  if (str->HasOnlyOneByteChars()) return true;
4324
  ContainsOnlyOneByteHelper helper;
4325
  return helper.Check(*str);
4326
}
4327

    
4328

    
4329
class Utf8LengthHelper : public i::AllStatic {
4330
 public:
4331
  enum State {
4332
    kEndsWithLeadingSurrogate = 1 << 0,
4333
    kStartsWithTrailingSurrogate = 1 << 1,
4334
    kLeftmostEdgeIsCalculated = 1 << 2,
4335
    kRightmostEdgeIsCalculated = 1 << 3,
4336
    kLeftmostEdgeIsSurrogate = 1 << 4,
4337
    kRightmostEdgeIsSurrogate = 1 << 5
4338
  };
4339

    
4340
  static const uint8_t kInitialState = 0;
4341

    
4342
  static inline bool EndsWithSurrogate(uint8_t state) {
4343
    return state & kEndsWithLeadingSurrogate;
4344
  }
4345

    
4346
  static inline bool StartsWithSurrogate(uint8_t state) {
4347
    return state & kStartsWithTrailingSurrogate;
4348
  }
4349

    
4350
  class Visitor {
4351
   public:
4352
    inline explicit Visitor()
4353
      : utf8_length_(0),
4354
        state_(kInitialState) {}
4355

    
4356
    void VisitOneByteString(const uint8_t* chars, int length) {
4357
      int utf8_length = 0;
4358
      // Add in length 1 for each non-ASCII character.
4359
      for (int i = 0; i < length; i++) {
4360
        utf8_length += *chars++ >> 7;
4361
      }
4362
      // Add in length 1 for each character.
4363
      utf8_length_ = utf8_length + length;
4364
      state_ = kInitialState;
4365
    }
4366

    
4367
    void VisitTwoByteString(const uint16_t* chars, int length) {
4368
      int utf8_length = 0;
4369
      int last_character = unibrow::Utf16::kNoPreviousCharacter;
4370
      for (int i = 0; i < length; i++) {
4371
        uint16_t c = chars[i];
4372
        utf8_length += unibrow::Utf8::Length(c, last_character);
4373
        last_character = c;
4374
      }
4375
      utf8_length_ = utf8_length;
4376
      uint8_t state = 0;
4377
      if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
4378
        state |= kStartsWithTrailingSurrogate;
4379
      }
4380
      if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) {
4381
        state |= kEndsWithLeadingSurrogate;
4382
      }
4383
      state_ = state;
4384
    }
4385

    
4386
    static i::ConsString* VisitFlat(i::String* string,
4387
                                    int* length,
4388
                                    uint8_t* state) {
4389
      Visitor visitor;
4390
      i::ConsString* cons_string = i::String::VisitFlat(&visitor, string);
4391
      *length = visitor.utf8_length_;
4392
      *state = visitor.state_;
4393
      return cons_string;
4394
    }
4395

    
4396
   private:
4397
    int utf8_length_;
4398
    uint8_t state_;
4399
    DISALLOW_COPY_AND_ASSIGN(Visitor);
4400
  };
4401

    
4402
  static inline void MergeLeafLeft(int* length,
4403
                                   uint8_t* state,
4404
                                   uint8_t leaf_state) {
4405
    bool edge_surrogate = StartsWithSurrogate(leaf_state);
4406
    if (!(*state & kLeftmostEdgeIsCalculated)) {
4407
      ASSERT(!(*state & kLeftmostEdgeIsSurrogate));
4408
      *state |= kLeftmostEdgeIsCalculated
4409
          | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0);
4410
    } else if (EndsWithSurrogate(*state) && edge_surrogate) {
4411
      *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4412
    }
4413
    if (EndsWithSurrogate(leaf_state)) {
4414
      *state |= kEndsWithLeadingSurrogate;
4415
    } else {
4416
      *state &= ~kEndsWithLeadingSurrogate;
4417
    }
4418
  }
4419

    
4420
  static inline void MergeLeafRight(int* length,
4421
                                    uint8_t* state,
4422
                                    uint8_t leaf_state) {
4423
    bool edge_surrogate = EndsWithSurrogate(leaf_state);
4424
    if (!(*state & kRightmostEdgeIsCalculated)) {
4425
      ASSERT(!(*state & kRightmostEdgeIsSurrogate));
4426
      *state |= (kRightmostEdgeIsCalculated
4427
          | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
4428
    } else if (edge_surrogate && StartsWithSurrogate(*state)) {
4429
      *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4430
    }
4431
    if (StartsWithSurrogate(leaf_state)) {
4432
      *state |= kStartsWithTrailingSurrogate;
4433
    } else {
4434
      *state &= ~kStartsWithTrailingSurrogate;
4435
    }
4436
  }
4437

    
4438
  static inline void MergeTerminal(int* length,
4439
                                   uint8_t state,
4440
                                   uint8_t* state_out) {
4441
    ASSERT((state & kLeftmostEdgeIsCalculated) &&
4442
           (state & kRightmostEdgeIsCalculated));
4443
    if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) {
4444
      *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4445
    }
4446
    *state_out = kInitialState |
4447
        (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) |
4448
        (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0);
4449
  }
4450

    
4451
  static int Calculate(i::ConsString* current, uint8_t* state_out) {
4452
    using namespace internal;
4453
    int total_length = 0;
4454
    uint8_t state = kInitialState;
4455
    while (true) {
4456
      i::String* left = current->first();
4457
      i::String* right = current->second();
4458
      uint8_t right_leaf_state;
4459
      uint8_t left_leaf_state;
4460
      int leaf_length;
4461
      ConsString* left_as_cons =
4462
          Visitor::VisitFlat(left, &leaf_length, &left_leaf_state);
4463
      if (left_as_cons == NULL) {
4464
        total_length += leaf_length;
4465
        MergeLeafLeft(&total_length, &state, left_leaf_state);
4466
      }
4467
      ConsString* right_as_cons =
4468
          Visitor::VisitFlat(right, &leaf_length, &right_leaf_state);
4469
      if (right_as_cons == NULL) {
4470
        total_length += leaf_length;
4471
        MergeLeafRight(&total_length, &state, right_leaf_state);
4472
        if (left_as_cons != NULL) {
4473
          // 1 Leaf node. Descend in place.
4474
          current = left_as_cons;
4475
          continue;
4476
        } else {
4477
          // Terminal node.
4478
          MergeTerminal(&total_length, state, state_out);
4479
          return total_length;
4480
        }
4481
      } else if (left_as_cons == NULL) {
4482
        // 1 Leaf node. Descend in place.
4483
        current = right_as_cons;
4484
        continue;
4485
      }
4486
      // Both strings are ConsStrings.
4487
      // Recurse on smallest.
4488
      if (left->length() < right->length()) {
4489
        total_length += Calculate(left_as_cons, &left_leaf_state);
4490
        MergeLeafLeft(&total_length, &state, left_leaf_state);
4491
        current = right_as_cons;
4492
      } else {
4493
        total_length += Calculate(right_as_cons, &right_leaf_state);
4494
        MergeLeafRight(&total_length, &state, right_leaf_state);
4495
        current = left_as_cons;
4496
      }
4497
    }
4498
    UNREACHABLE();
4499
    return 0;
4500
  }
4501

    
4502
  static inline int Calculate(i::ConsString* current) {
4503
    uint8_t state = kInitialState;
4504
    return Calculate(current, &state);
4505
  }
4506

    
4507
 private:
4508
  DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper);
4509
};
4510

    
4511

    
4512
static int Utf8Length(i::String* str, i::Isolate* isolate) {
4513
  int length = str->length();
4514
  if (length == 0) return 0;
4515
  uint8_t state;
4516
  i::ConsString* cons_string =
4517
      Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state);
4518
  if (cons_string == NULL) return length;
4519
  return Utf8LengthHelper::Calculate(cons_string);
4520
}
4521

    
4522

    
4523
int String::Utf8Length() const {
4524
  i::Handle<i::String> str = Utils::OpenHandle(this);
4525
  i::Isolate* isolate = str->GetIsolate();
4526
  return v8::Utf8Length(*str, isolate);
4527
}
4528

    
4529

    
4530
class Utf8WriterVisitor {
4531
 public:
4532
  Utf8WriterVisitor(
4533
      char* buffer, int capacity, bool skip_capacity_check)
4534
    : early_termination_(false),
4535
      last_character_(unibrow::Utf16::kNoPreviousCharacter),
4536
      buffer_(buffer),
4537
      start_(buffer),
4538
      capacity_(capacity),
4539
      skip_capacity_check_(capacity == -1 || skip_capacity_check),
4540
      utf16_chars_read_(0) {
4541
  }
4542

    
4543
  static int WriteEndCharacter(uint16_t character,
4544
                               int last_character,
4545
                               int remaining,
4546
                               char* const buffer) {
4547
    using namespace unibrow;
4548
    ASSERT(remaining > 0);
4549
    // We can't use a local buffer here because Encode needs to modify
4550
    // previous characters in the stream.  We know, however, that
4551
    // exactly one character will be advanced.
4552
    if (Utf16::IsTrailSurrogate(character) &&
4553
        Utf16::IsLeadSurrogate(last_character)) {
4554
      int written = Utf8::Encode(buffer, character, last_character);
4555
      ASSERT(written == 1);
4556
      return written;
4557
    }
4558
    // Use a scratch buffer to check the required characters.
4559
    char temp_buffer[Utf8::kMaxEncodedSize];
4560
    // Can't encode using last_character as gcc has array bounds issues.
4561
    int written = Utf8::Encode(temp_buffer,
4562
                               character,
4563
                               Utf16::kNoPreviousCharacter);
4564
    // Won't fit.
4565
    if (written > remaining) return 0;
4566
    // Copy over the character from temp_buffer.
4567
    for (int j = 0; j < written; j++) {
4568
      buffer[j] = temp_buffer[j];
4569
    }
4570
    return written;
4571
  }
4572

    
4573
  template<typename Char>
4574
  void Visit(const Char* chars, const int length) {
4575
    using namespace unibrow;
4576
    ASSERT(!early_termination_);
4577
    if (length == 0) return;
4578
    // Copy state to stack.
4579
    char* buffer = buffer_;
4580
    int last_character =
4581
        sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
4582
    int i = 0;
4583
    // Do a fast loop where there is no exit capacity check.
4584
    while (true) {
4585
      int fast_length;
4586
      if (skip_capacity_check_) {
4587
        fast_length = length;
4588
      } else {
4589
        int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4590
        // Need enough space to write everything but one character.
4591
        STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
4592
        int max_size_per_char =  sizeof(Char) == 1 ? 2 : 3;
4593
        int writable_length =
4594
            (remaining_capacity - max_size_per_char)/max_size_per_char;
4595
        // Need to drop into slow loop.
4596
        if (writable_length <= 0) break;
4597
        fast_length = i + writable_length;
4598
        if (fast_length > length) fast_length = length;
4599
      }
4600
      // Write the characters to the stream.
4601
      if (sizeof(Char) == 1) {
4602
        for (; i < fast_length; i++) {
4603
          buffer +=
4604
              Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
4605
          ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
4606
        }
4607
      } else {
4608
        for (; i < fast_length; i++) {
4609
          uint16_t character = *chars++;
4610
          buffer += Utf8::Encode(buffer, character, last_character);
4611
          last_character = character;
4612
          ASSERT(capacity_ == -1 || (buffer - start_) <= capacity_);
4613
        }
4614
      }
4615
      // Array is fully written. Exit.
4616
      if (fast_length == length) {
4617
        // Write state back out to object.
4618
        last_character_ = last_character;
4619
        buffer_ = buffer;
4620
        utf16_chars_read_ += length;
4621
        return;
4622
      }
4623
    }
4624
    ASSERT(!skip_capacity_check_);
4625
    // Slow loop. Must check capacity on each iteration.
4626
    int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4627
    ASSERT(remaining_capacity >= 0);
4628
    for (; i < length && remaining_capacity > 0; i++) {
4629
      uint16_t character = *chars++;
4630
      int written = WriteEndCharacter(character,
4631
                                      last_character,
4632
                                      remaining_capacity,
4633
                                      buffer);
4634
      if (written == 0) {
4635
        early_termination_ = true;
4636
        break;
4637
      }
4638
      buffer += written;
4639
      remaining_capacity -= written;
4640
      last_character = character;
4641
    }
4642
    // Write state back out to object.
4643
    last_character_ = last_character;
4644
    buffer_ = buffer;
4645
    utf16_chars_read_ += i;
4646
  }
4647

    
4648
  inline bool IsDone() {
4649
    return early_termination_;
4650
  }
4651

    
4652
  inline void VisitOneByteString(const uint8_t* chars, int length) {
4653
    Visit(chars, length);
4654
  }
4655

    
4656
  inline void VisitTwoByteString(const uint16_t* chars, int length) {
4657
    Visit(chars, length);
4658
  }
4659

    
4660
  int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
4661
    // Write out number of utf16 characters written to the stream.
4662
    if (utf16_chars_read_out != NULL) {
4663
      *utf16_chars_read_out = utf16_chars_read_;
4664
    }
4665
    // Only null terminate if all of the string was written and there's space.
4666
    if (write_null &&
4667
        !early_termination_ &&
4668
        (capacity_ == -1 || (buffer_ - start_) < capacity_)) {
4669
      *buffer_++ = '\0';
4670
    }
4671
    return static_cast<int>(buffer_ - start_);
4672
  }
4673

    
4674
 private:
4675
  bool early_termination_;
4676
  int last_character_;
4677
  char* buffer_;
4678
  char* const start_;
4679
  int capacity_;
4680
  bool const skip_capacity_check_;
4681
  int utf16_chars_read_;
4682
  DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor);
4683
};
4684

    
4685

    
4686
static bool RecursivelySerializeToUtf8(i::String* current,
4687
                                      Utf8WriterVisitor* writer,
4688
                                      int recursion_budget) {
4689
  while (!writer->IsDone()) {
4690
    i::ConsString* cons_string = i::String::VisitFlat(writer, current);
4691
    if (cons_string == NULL) return true;  // Leaf node.
4692
    if (recursion_budget <= 0) return false;
4693
    // Must write the left branch first.
4694
    i::String* first = cons_string->first();
4695
    bool success = RecursivelySerializeToUtf8(first,
4696
                                              writer,
4697
                                              recursion_budget - 1);
4698
    if (!success) return false;
4699
    // Inline tail recurse for right branch.
4700
    current = cons_string->second();
4701
  }
4702
  return true;
4703
}
4704

    
4705

    
4706
int String::WriteUtf8(char* buffer,
4707
                      int capacity,
4708
                      int* nchars_ref,
4709
                      int options) const {
4710
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4711
  LOG_API(isolate, "String::WriteUtf8");
4712
  ENTER_V8(isolate);
4713
  i::Handle<i::String> str = Utils::OpenHandle(this);
4714
  if (options & HINT_MANY_WRITES_EXPECTED) {
4715
    FlattenString(str);  // Flatten the string for efficiency.
4716
  }
4717
  const int string_length = str->length();
4718
  bool write_null = !(options & NO_NULL_TERMINATION);
4719
  // First check if we can just write the string without checking capacity.
4720
  if (capacity == -1 || capacity / 3 >= string_length) {
4721
    Utf8WriterVisitor writer(buffer, capacity, true);
4722
    const int kMaxRecursion = 100;
4723
    bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion);
4724
    if (success) return writer.CompleteWrite(write_null, nchars_ref);
4725
  } else if (capacity >= string_length) {
4726
    // First check that the buffer is large enough.
4727
    int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate());
4728
    if (utf8_bytes <= capacity) {
4729
      // ASCII fast path.
4730
      if (utf8_bytes == string_length) {
4731
        WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options);
4732
        if (nchars_ref != NULL) *nchars_ref = string_length;
4733
        if (write_null && (utf8_bytes+1 <= capacity)) {
4734
          return string_length + 1;
4735
        }
4736
        return string_length;
4737
      }
4738
      if (write_null && (utf8_bytes+1 > capacity)) {
4739
        options |= NO_NULL_TERMINATION;
4740
      }
4741
      // Recurse once without a capacity limit.
4742
      // This will get into the first branch above.
4743
      // TODO(dcarney) Check max left rec. in Utf8Length and fall through.
4744
      return WriteUtf8(buffer, -1, nchars_ref, options);
4745
    }
4746
  }
4747
  // Recursive slow path can potentially be unreasonable slow. Flatten.
4748
  str = FlattenGetString(str);
4749
  Utf8WriterVisitor writer(buffer, capacity, false);
4750
  i::String::VisitFlat(&writer, *str);
4751
  return writer.CompleteWrite(write_null, nchars_ref);
4752
}
4753

    
4754

    
4755
template<typename CharType>
4756
static inline int WriteHelper(const String* string,
4757
                              CharType* buffer,
4758
                              int start,
4759
                              int length,
4760
                              int options) {
4761
  i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate();
4762
  LOG_API(isolate, "String::Write");
4763
  ENTER_V8(isolate);
4764
  ASSERT(start >= 0 && length >= -1);
4765
  i::Handle<i::String> str = Utils::OpenHandle(string);
4766
  isolate->string_tracker()->RecordWrite(str);
4767
  if (options & String::HINT_MANY_WRITES_EXPECTED) {
4768
    // Flatten the string for efficiency.  This applies whether we are
4769
    // using StringCharacterStream or Get(i) to access the characters.
4770
    FlattenString(str);
4771
  }
4772
  int end = start + length;
4773
  if ((length == -1) || (length > str->length() - start) )
4774
    end = str->length();
4775
  if (end < 0) return 0;
4776
  i::String::WriteToFlat(*str, buffer, start, end);
4777
  if (!(options & String::NO_NULL_TERMINATION) &&
4778
      (length == -1 || end - start < length)) {
4779
    buffer[end - start] = '\0';
4780
  }
4781
  return end - start;
4782
}
4783

    
4784

    
4785
int String::WriteOneByte(uint8_t* buffer,
4786
                         int start,
4787
                         int length,
4788
                         int options) const {
4789
  return WriteHelper(this, buffer, start, length, options);
4790
}
4791

    
4792

    
4793
int String::Write(uint16_t* buffer,
4794
                  int start,
4795
                  int length,
4796
                  int options) const {
4797
  return WriteHelper(this, buffer, start, length, options);
4798
}
4799

    
4800

    
4801
bool v8::String::IsExternal() const {
4802
  i::Handle<i::String> str = Utils::OpenHandle(this);
4803
  EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()");
4804
  return i::StringShape(*str).IsExternalTwoByte();
4805
}
4806

    
4807

    
4808
bool v8::String::IsExternalAscii() const {
4809
  i::Handle<i::String> str = Utils::OpenHandle(this);
4810
  return i::StringShape(*str).IsExternalAscii();
4811
}
4812

    
4813

    
4814
void v8::String::VerifyExternalStringResource(
4815
    v8::String::ExternalStringResource* value) const {
4816
  i::Handle<i::String> str = Utils::OpenHandle(this);
4817
  const v8::String::ExternalStringResource* expected;
4818
  if (i::StringShape(*str).IsExternalTwoByte()) {
4819
    const void* resource =
4820
        i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4821
    expected = reinterpret_cast<const ExternalStringResource*>(resource);
4822
  } else {
4823
    expected = NULL;
4824
  }
4825
  CHECK_EQ(expected, value);
4826
}
4827

    
4828
void v8::String::VerifyExternalStringResourceBase(
4829
    v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
4830
  i::Handle<i::String> str = Utils::OpenHandle(this);
4831
  const v8::String::ExternalStringResourceBase* expected;
4832
  Encoding expectedEncoding;
4833
  if (i::StringShape(*str).IsExternalAscii()) {
4834
    const void* resource =
4835
        i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4836
    expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4837
    expectedEncoding = ASCII_ENCODING;
4838
  } else if (i::StringShape(*str).IsExternalTwoByte()) {
4839
    const void* resource =
4840
        i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4841
    expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4842
    expectedEncoding = TWO_BYTE_ENCODING;
4843
  } else {
4844
    expected = NULL;
4845
    expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING
4846
                                                    : TWO_BYTE_ENCODING;
4847
  }
4848
  CHECK_EQ(expected, value);
4849
  CHECK_EQ(expectedEncoding, encoding);
4850
}
4851

    
4852
const v8::String::ExternalAsciiStringResource*
4853
      v8::String::GetExternalAsciiStringResource() const {
4854
  i::Handle<i::String> str = Utils::OpenHandle(this);
4855
  if (i::StringShape(*str).IsExternalAscii()) {
4856
    const void* resource =
4857
        i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4858
    return reinterpret_cast<const ExternalAsciiStringResource*>(resource);
4859
  } else {
4860
    return NULL;
4861
  }
4862
}
4863

    
4864

    
4865
Local<Value> Symbol::Name() const {
4866
  i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
4867
  i::Handle<i::Object> name(sym->name(), sym->GetIsolate());
4868
  return Utils::ToLocal(name);
4869
}
4870

    
4871

    
4872
double Number::Value() const {
4873
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
4874
  return obj->Number();
4875
}
4876

    
4877

    
4878
bool Boolean::Value() const {
4879
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
4880
  return obj->IsTrue();
4881
}
4882

    
4883

    
4884
int64_t Integer::Value() const {
4885
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
4886
  if (obj->IsSmi()) {
4887
    return i::Smi::cast(*obj)->value();
4888
  } else {
4889
    return static_cast<int64_t>(obj->Number());
4890
  }
4891
}
4892

    
4893

    
4894
int32_t Int32::Value() const {
4895
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
4896
  if (obj->IsSmi()) {
4897
    return i::Smi::cast(*obj)->value();
4898
  } else {
4899
    return static_cast<int32_t>(obj->Number());
4900
  }
4901
}
4902

    
4903

    
4904
uint32_t Uint32::Value() const {
4905
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
4906
  if (obj->IsSmi()) {
4907
    return i::Smi::cast(*obj)->value();
4908
  } else {
4909
    return static_cast<uint32_t>(obj->Number());
4910
  }
4911
}
4912

    
4913

    
4914
int v8::Object::InternalFieldCount() {
4915
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4916
  return obj->GetInternalFieldCount();
4917
}
4918

    
4919

    
4920
static bool InternalFieldOK(i::Handle<i::JSObject> obj,
4921
                            int index,
4922
                            const char* location) {
4923
  return ApiCheck(index < obj->GetInternalFieldCount(),
4924
                  location,
4925
                  "Internal field out of bounds");
4926
}
4927

    
4928

    
4929
Local<Value> v8::Object::SlowGetInternalField(int index) {
4930
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4931
  const char* location = "v8::Object::GetInternalField()";
4932
  if (!InternalFieldOK(obj, index, location)) return Local<Value>();
4933
  i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
4934
  return Utils::ToLocal(value);
4935
}
4936

    
4937

    
4938
void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
4939
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4940
  const char* location = "v8::Object::SetInternalField()";
4941
  if (!InternalFieldOK(obj, index, location)) return;
4942
  i::Handle<i::Object> val = Utils::OpenHandle(*value);
4943
  obj->SetInternalField(index, *val);
4944
  ASSERT_EQ(value, GetInternalField(index));
4945
}
4946

    
4947

    
4948
void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
4949
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4950
  const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
4951
  if (!InternalFieldOK(obj, index, location)) return NULL;
4952
  return DecodeSmiToAligned(obj->GetInternalField(index), location);
4953
}
4954

    
4955

    
4956
void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
4957
  i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4958
  const char* location = "v8::Object::SetAlignedPointerInInternalField()";
4959
  if (!InternalFieldOK(obj, index, location)) return;
4960
  obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
4961
  ASSERT_EQ(value, GetAlignedPointerFromInternalField(index));
4962
}
4963

    
4964

    
4965
static void* ExternalValue(i::Object* obj) {
4966
  // Obscure semantics for undefined, but somehow checked in our unit tests...
4967
  if (obj->IsUndefined()) return NULL;
4968
  i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
4969
  return i::Foreign::cast(foreign)->foreign_address();
4970
}
4971

    
4972

    
4973
// --- E n v i r o n m e n t ---
4974

    
4975

    
4976
bool v8::V8::Initialize() {
4977
  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
4978
  if (isolate != NULL && isolate->IsInitialized()) {
4979
    return true;
4980
  }
4981
  return InitializeHelper(isolate);
4982
}
4983

    
4984

    
4985
void v8::V8::SetEntropySource(EntropySource entropy_source) {
4986
  i::RandomNumberGenerator::SetEntropySource(entropy_source);
4987
}
4988

    
4989

    
4990
void v8::V8::SetReturnAddressLocationResolver(
4991
      ReturnAddressLocationResolver return_address_resolver) {
4992
  i::V8::SetReturnAddressLocationResolver(return_address_resolver);
4993
}
4994

    
4995

    
4996
bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate,
4997
                                  FunctionEntryHook entry_hook) {
4998
  ASSERT(ext_isolate != NULL);
4999
  ASSERT(entry_hook != NULL);
5000

    
5001
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(ext_isolate);
5002

    
5003
  // The entry hook can only be set before the Isolate is initialized, as
5004
  // otherwise the Isolate's code stubs generated at initialization won't
5005
  // contain entry hooks.
5006
  if (isolate->IsInitialized())
5007
    return false;
5008

    
5009
  // Setting an entry hook is a one-way operation, once set, it cannot be
5010
  // changed or unset.
5011
  if (isolate->function_entry_hook() != NULL)
5012
    return false;
5013

    
5014
  isolate->set_function_entry_hook(entry_hook);
5015
  return true;
5016
}
5017

    
5018

    
5019
void v8::V8::SetJitCodeEventHandler(
5020
    JitCodeEventOptions options, JitCodeEventHandler event_handler) {
5021
  i::Isolate* isolate = i::Isolate::Current();
5022
  // Ensure that logging is initialized for our isolate.
5023
  isolate->InitializeLoggingAndCounters();
5024
  isolate->logger()->SetCodeEventHandler(options, event_handler);
5025
}
5026

    
5027
void v8::V8::SetArrayBufferAllocator(
5028
    ArrayBuffer::Allocator* allocator) {
5029
  if (!ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
5030
                "v8::V8::SetArrayBufferAllocator",
5031
                "ArrayBufferAllocator might only be set once"))
5032
    return;
5033
  i::V8::SetArrayBufferAllocator(allocator);
5034
}
5035

    
5036

    
5037
bool v8::V8::Dispose() {
5038
  i::Isolate* isolate = i::Isolate::Current();
5039
  if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
5040
                "v8::V8::Dispose()",
5041
                "Use v8::Isolate::Dispose() for a non-default isolate.")) {
5042
    return false;
5043
  }
5044
  i::V8::TearDown();
5045
  return true;
5046
}
5047

    
5048

    
5049
HeapStatistics::HeapStatistics(): total_heap_size_(0),
5050
                                  total_heap_size_executable_(0),
5051
                                  total_physical_size_(0),
5052
                                  used_heap_size_(0),
5053
                                  heap_size_limit_(0) { }
5054

    
5055

    
5056
void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
5057
  i::Isolate* isolate = i::Isolate::Current();
5058
  isolate->heap()->VisitExternalResources(visitor);
5059
}
5060

    
5061

    
5062
class VisitorAdapter : public i::ObjectVisitor {
5063
 public:
5064
  explicit VisitorAdapter(PersistentHandleVisitor* visitor)
5065
      : visitor_(visitor) {}
5066
  virtual void VisitPointers(i::Object** start, i::Object** end) {
5067
    UNREACHABLE();
5068
  }
5069
  virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
5070
    Value* value = ToApi<Value>(i::Handle<i::Object>(p));
5071
    visitor_->VisitPersistentHandle(
5072
        reinterpret_cast<Persistent<Value>*>(&value), class_id);
5073
  }
5074
 private:
5075
  PersistentHandleVisitor* visitor_;
5076
};
5077

    
5078

    
5079
void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
5080
  i::Isolate* isolate = i::Isolate::Current();
5081
  i::DisallowHeapAllocation no_allocation;
5082

    
5083
  VisitorAdapter visitor_adapter(visitor);
5084
  isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
5085
}
5086

    
5087

    
5088
void v8::V8::VisitHandlesForPartialDependence(
5089
    Isolate* exported_isolate, PersistentHandleVisitor* visitor) {
5090
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
5091
  ASSERT(isolate == i::Isolate::Current());
5092
  i::DisallowHeapAllocation no_allocation;
5093

    
5094
  VisitorAdapter visitor_adapter(visitor);
5095
  isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
5096
      &visitor_adapter);
5097
}
5098

    
5099

    
5100
bool v8::V8::IdleNotification(int hint) {
5101
  // Returning true tells the caller that it need not
5102
  // continue to call IdleNotification.
5103
  i::Isolate* isolate = i::Isolate::Current();
5104
  if (isolate == NULL || !isolate->IsInitialized()) return true;
5105
  if (!i::FLAG_use_idle_notification) return true;
5106
  return isolate->heap()->IdleNotification(hint);
5107
}
5108

    
5109

    
5110
void v8::V8::LowMemoryNotification() {
5111
  i::Isolate* isolate = i::Isolate::Current();
5112
  if (isolate == NULL || !isolate->IsInitialized()) return;
5113
  isolate->heap()->CollectAllAvailableGarbage("low memory notification");
5114
}
5115

    
5116

    
5117
int v8::V8::ContextDisposedNotification() {
5118
  i::Isolate* isolate = i::Isolate::Current();
5119
  if (!isolate->IsInitialized()) return 0;
5120
  return isolate->heap()->NotifyContextDisposed();
5121
}
5122

    
5123

    
5124
bool v8::V8::InitializeICU() {
5125
  return i::InitializeICU();
5126
}
5127

    
5128

    
5129
const char* v8::V8::GetVersion() {
5130
  return i::Version::GetVersion();
5131
}
5132

    
5133

    
5134
static i::Handle<i::Context> CreateEnvironment(
5135
    i::Isolate* isolate,
5136
    v8::ExtensionConfiguration* extensions,
5137
    v8::Handle<ObjectTemplate> global_template,
5138
    v8::Handle<Value> global_object) {
5139
  i::Handle<i::Context> env;
5140

    
5141
  // Enter V8 via an ENTER_V8 scope.
5142
  {
5143
    ENTER_V8(isolate);
5144
    v8::Handle<ObjectTemplate> proxy_template = global_template;
5145
    i::Handle<i::FunctionTemplateInfo> proxy_constructor;
5146
    i::Handle<i::FunctionTemplateInfo> global_constructor;
5147

    
5148
    if (!global_template.IsEmpty()) {
5149
      // Make sure that the global_template has a constructor.
5150
      global_constructor = EnsureConstructor(*global_template);
5151

    
5152
      // Create a fresh template for the global proxy object.
5153
      proxy_template = ObjectTemplate::New();
5154
      proxy_constructor = EnsureConstructor(*proxy_template);
5155

    
5156
      // Set the global template to be the prototype template of
5157
      // global proxy template.
5158
      proxy_constructor->set_prototype_template(
5159
          *Utils::OpenHandle(*global_template));
5160

    
5161
      // Migrate security handlers from global_template to
5162
      // proxy_template.  Temporarily removing access check
5163
      // information from the global template.
5164
      if (!global_constructor->access_check_info()->IsUndefined()) {
5165
        proxy_constructor->set_access_check_info(
5166
            global_constructor->access_check_info());
5167
        proxy_constructor->set_needs_access_check(
5168
            global_constructor->needs_access_check());
5169
        global_constructor->set_needs_access_check(false);
5170
        global_constructor->set_access_check_info(
5171
            isolate->heap()->undefined_value());
5172
      }
5173
    }
5174

    
5175
    // Create the environment.
5176
    env = isolate->bootstrapper()->CreateEnvironment(
5177
        Utils::OpenHandle(*global_object, true),
5178
        proxy_template,
5179
        extensions);
5180

    
5181
    // Restore the access check info on the global template.
5182
    if (!global_template.IsEmpty()) {
5183
      ASSERT(!global_constructor.is_null());
5184
      ASSERT(!proxy_constructor.is_null());
5185
      global_constructor->set_access_check_info(
5186
          proxy_constructor->access_check_info());
5187
      global_constructor->set_needs_access_check(
5188
          proxy_constructor->needs_access_check());
5189
    }
5190
    isolate->runtime_profiler()->Reset();
5191
  }
5192
  // Leave V8.
5193

    
5194
  return env;
5195
}
5196

    
5197
Local<Context> v8::Context::New(
5198
    v8::Isolate* external_isolate,
5199
    v8::ExtensionConfiguration* extensions,
5200
    v8::Handle<ObjectTemplate> global_template,
5201
    v8::Handle<Value> global_object) {
5202
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
5203
  EnsureInitializedForIsolate(isolate, "v8::Context::New()");
5204
  LOG_API(isolate, "Context::New");
5205
  ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>());
5206
  i::HandleScope scope(isolate);
5207
  i::Handle<i::Context> env =
5208
      CreateEnvironment(isolate, extensions, global_template, global_object);
5209
  if (env.is_null()) return Local<Context>();
5210
  return Utils::ToLocal(scope.CloseAndEscape(env));
5211
}
5212

    
5213

    
5214
void v8::Context::SetSecurityToken(Handle<Value> token) {
5215
  i::Isolate* isolate = i::Isolate::Current();
5216
  ENTER_V8(isolate);
5217
  i::Handle<i::Context> env = Utils::OpenHandle(this);
5218
  i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
5219
  env->set_security_token(*token_handle);
5220
}
5221

    
5222

    
5223
void v8::Context::UseDefaultSecurityToken() {
5224
  i::Isolate* isolate = i::Isolate::Current();
5225
  ENTER_V8(isolate);
5226
  i::Handle<i::Context> env = Utils::OpenHandle(this);
5227
  env->set_security_token(env->global_object());
5228
}
5229

    
5230

    
5231
Handle<Value> v8::Context::GetSecurityToken() {
5232
  i::Isolate* isolate = i::Isolate::Current();
5233
  i::Handle<i::Context> env = Utils::OpenHandle(this);
5234
  i::Object* security_token = env->security_token();
5235
  i::Handle<i::Object> token_handle(security_token, isolate);
5236
  return Utils::ToLocal(token_handle);
5237
}
5238

    
5239

    
5240
bool Context::HasOutOfMemoryException() {
5241
  i::Handle<i::Context> env = Utils::OpenHandle(this);
5242
  return env->has_out_of_memory();
5243
}
5244

    
5245

    
5246
bool Context::InContext() {
5247
  return i::Isolate::Current()->context() != NULL;
5248
}
5249

    
5250

    
5251
v8::Isolate* Context::GetIsolate() {
5252
  i::Handle<i::Context> env = Utils::OpenHandle(this);
5253
  return reinterpret_cast<Isolate*>(env->GetIsolate());
5254
}
5255

    
5256

    
5257
v8::Local<v8::Context> Context::GetEntered() {
5258
  i::Isolate* isolate = i::Isolate::Current();
5259
  if (!EnsureInitializedForIsolate(isolate, "v8::Context::GetEntered()")) {
5260
    return Local<Context>();
5261
  }
5262
  return reinterpret_cast<Isolate*>(isolate)->GetEnteredContext();
5263
}
5264

    
5265

    
5266
v8::Local<v8::Context> Context::GetCurrent() {
5267
  i::Isolate* isolate = i::Isolate::Current();
5268
  return reinterpret_cast<Isolate*>(isolate)->GetCurrentContext();
5269
}
5270

    
5271

    
5272
v8::Local<v8::Context> Context::GetCalling() {
5273
  i::Isolate* isolate = i::Isolate::Current();
5274
  return reinterpret_cast<Isolate*>(isolate)->GetCallingContext();
5275
}
5276

    
5277

    
5278
v8::Local<v8::Object> Context::Global() {
5279
  i::Handle<i::Context> context = Utils::OpenHandle(this);
5280
  i::Isolate* isolate = context->GetIsolate();
5281
  i::Handle<i::Object> global(context->global_proxy(), isolate);
5282
  return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
5283
}
5284

    
5285

    
5286
void Context::DetachGlobal() {
5287
  i::Handle<i::Context> context = Utils::OpenHandle(this);
5288
  i::Isolate* isolate = context->GetIsolate();
5289
  ENTER_V8(isolate);
5290
  isolate->bootstrapper()->DetachGlobal(context);
5291
}
5292

    
5293

    
5294
void Context::ReattachGlobal(Handle<Object> global_object) {
5295
  i::Handle<i::Context> context = Utils::OpenHandle(this);
5296
  i::Isolate* isolate = context->GetIsolate();
5297
  ENTER_V8(isolate);
5298
  i::Handle<i::JSGlobalProxy> global_proxy =
5299
      i::Handle<i::JSGlobalProxy>::cast(Utils::OpenHandle(*global_object));
5300
  isolate->bootstrapper()->ReattachGlobal(context, global_proxy);
5301
}
5302

    
5303

    
5304
void Context::AllowCodeGenerationFromStrings(bool allow) {
5305
  i::Handle<i::Context> context = Utils::OpenHandle(this);
5306
  i::Isolate* isolate = context->GetIsolate();
5307
  ENTER_V8(isolate);
5308
  context->set_allow_code_gen_from_strings(
5309
      allow ? isolate->heap()->true_value() : isolate->heap()->false_value());
5310
}
5311

    
5312

    
5313
bool Context::IsCodeGenerationFromStringsAllowed() {
5314
  i::Handle<i::Context> context = Utils::OpenHandle(this);
5315
  return !context->allow_code_gen_from_strings()->IsFalse();
5316
}
5317

    
5318

    
5319
void Context::SetErrorMessageForCodeGenerationFromStrings(
5320
    Handle<String> error) {
5321
  i::Handle<i::Context> context = Utils::OpenHandle(this);
5322
  i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
5323
  context->set_error_message_for_code_gen_from_strings(*error_handle);
5324
}
5325

    
5326

    
5327
Local<v8::Object> ObjectTemplate::NewInstance() {
5328
  i::Isolate* isolate = i::Isolate::Current();
5329
  ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
5330
             return Local<v8::Object>());
5331
  LOG_API(isolate, "ObjectTemplate::NewInstance");
5332
  ENTER_V8(isolate);
5333
  EXCEPTION_PREAMBLE(isolate);
5334
  i::Handle<i::Object> obj =
5335
      i::Execution::InstantiateObject(Utils::OpenHandle(this),
5336
                                      &has_pending_exception);
5337
  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
5338
  return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
5339
}
5340

    
5341

    
5342
Local<v8::Function> FunctionTemplate::GetFunction() {
5343
  i::Isolate* isolate = i::Isolate::Current();
5344
  ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
5345
             return Local<v8::Function>());
5346
  LOG_API(isolate, "FunctionTemplate::GetFunction");
5347
  ENTER_V8(isolate);
5348
  EXCEPTION_PREAMBLE(isolate);
5349
  i::Handle<i::Object> obj =
5350
      i::Execution::InstantiateFunction(Utils::OpenHandle(this),
5351
                                        &has_pending_exception);
5352
  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
5353
  return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
5354
}
5355

    
5356

    
5357
bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
5358
  ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()",
5359
             return false);
5360
  i::Object* obj = *Utils::OpenHandle(*value);
5361
  return obj->IsInstanceOf(*Utils::OpenHandle(this));
5362
}
5363

    
5364

    
5365
Local<External> v8::External::New(void* value) {
5366
  STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
5367
  i::Isolate* isolate = i::Isolate::Current();
5368
  EnsureInitializedForIsolate(isolate, "v8::External::New()");
5369
  LOG_API(isolate, "External::New");
5370
  ENTER_V8(isolate);
5371
  i::Handle<i::JSObject> external = isolate->factory()->NewExternal(value);
5372
  return Utils::ExternalToLocal(external);
5373
}
5374

    
5375

    
5376
void* External::Value() const {
5377
  return ExternalValue(*Utils::OpenHandle(this));
5378
}
5379

    
5380

    
5381
Local<String> v8::String::Empty() {
5382
  i::Isolate* isolate = i::Isolate::Current();
5383
  if (!EnsureInitializedForIsolate(isolate, "v8::String::Empty()")) {
5384
    return v8::Local<String>();
5385
  }
5386
  LOG_API(isolate, "String::Empty()");
5387
  return Utils::ToLocal(isolate->factory()->empty_string());
5388
}
5389

    
5390

    
5391
// anonymous namespace for string creation helper functions
5392
namespace {
5393

    
5394
inline int StringLength(const char* string) {
5395
  return i::StrLength(string);
5396
}
5397

    
5398

    
5399
inline int StringLength(const uint8_t* string) {
5400
  return i::StrLength(reinterpret_cast<const char*>(string));
5401
}
5402

    
5403

    
5404
inline int StringLength(const uint16_t* string) {
5405
  int length = 0;
5406
  while (string[length] != '\0')
5407
    length++;
5408
  return length;
5409
}
5410

    
5411

    
5412
inline i::Handle<i::String> NewString(i::Factory* factory,
5413
                                      String::NewStringType type,
5414
                                      i::Vector<const char> string) {
5415
  if (type ==String::kInternalizedString) {
5416
    return factory->InternalizeUtf8String(string);
5417
  }
5418
  return factory->NewStringFromUtf8(string);
5419
}
5420

    
5421

    
5422
inline i::Handle<i::String> NewString(i::Factory* factory,
5423
                                      String::NewStringType type,
5424
                                      i::Vector<const uint8_t> string) {
5425
  if (type == String::kInternalizedString) {
5426
    return factory->InternalizeOneByteString(string);
5427
  }
5428
  return factory->NewStringFromOneByte(string);
5429
}
5430

    
5431

    
5432
inline i::Handle<i::String> NewString(i::Factory* factory,
5433
                                      String::NewStringType type,
5434
                                      i::Vector<const uint16_t> string) {
5435
  if (type == String::kInternalizedString) {
5436
    return factory->InternalizeTwoByteString(string);
5437
  }
5438
  return factory->NewStringFromTwoByte(string);
5439
}
5440

    
5441

    
5442
template<typename Char>
5443
inline Local<String> NewString(Isolate* v8_isolate,
5444
                               const char* location,
5445
                               const char* env,
5446
                               const Char* data,
5447
                               String::NewStringType type,
5448
                               int length) {
5449
  i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
5450
  EnsureInitializedForIsolate(isolate, location);
5451
  LOG_API(isolate, env);
5452
  if (length == 0 && type != String::kUndetectableString) {
5453
    return String::Empty();
5454
  }
5455
  ENTER_V8(isolate);
5456
  if (length == -1) length = StringLength(data);
5457
  i::Handle<i::String> result = NewString(
5458
      isolate->factory(), type, i::Vector<const Char>(data, length));
5459
  if (type == String::kUndetectableString) {
5460
    result->MarkAsUndetectable();
5461
  }
5462
  return Utils::ToLocal(result);
5463
}
5464

    
5465
}  // anonymous namespace
5466

    
5467

    
5468
Local<String> String::NewFromUtf8(Isolate* isolate,
5469
                                  const char* data,
5470
                                  NewStringType type,
5471
                                  int length) {
5472
  return NewString(isolate,
5473
                   "v8::String::NewFromUtf8()",
5474
                   "String::NewFromUtf8",
5475
                   data,
5476
                   type,
5477
                   length);
5478
}
5479

    
5480

    
5481
Local<String> String::NewFromOneByte(Isolate* isolate,
5482
                                     const uint8_t* data,
5483
                                     NewStringType type,
5484
                                     int length) {
5485
  return NewString(isolate,
5486
                   "v8::String::NewFromOneByte()",
5487
                   "String::NewFromOneByte",
5488
                   data,
5489
                   type,
5490
                   length);
5491
}
5492

    
5493

    
5494
Local<String> String::NewFromTwoByte(Isolate* isolate,
5495
                                     const uint16_t* data,
5496
                                     NewStringType type,
5497
                                     int length) {
5498
  return NewString(isolate,
5499
                   "v8::String::NewFromTwoByte()",
5500
                   "String::NewFromTwoByte",
5501
                   data,
5502
                   type,
5503
                   length);
5504
}
5505

    
5506

    
5507
Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
5508
  i::Handle<i::String> left_string = Utils::OpenHandle(*left);
5509
  i::Isolate* isolate = left_string->GetIsolate();
5510
  EnsureInitializedForIsolate(isolate, "v8::String::New()");
5511
  LOG_API(isolate, "String::New(char)");
5512
  ENTER_V8(isolate);
5513
  i::Handle<i::String> right_string = Utils::OpenHandle(*right);
5514
  i::Handle<i::String> result = isolate->factory()->NewConsString(left_string,
5515
                                                                  right_string);
5516
  return Utils::ToLocal(result);
5517
}
5518

    
5519

    
5520
i::Handle<i::String> NewExternalStringHandle(i::Isolate* isolate,
5521
      v8::String::ExternalStringResource* resource) {
5522
  i::Handle<i::String> result =
5523
      isolate->factory()->NewExternalStringFromTwoByte(resource);
5524
  return result;
5525
}
5526

    
5527

    
5528
i::Handle<i::String> NewExternalAsciiStringHandle(i::Isolate* isolate,
5529
      v8::String::ExternalAsciiStringResource* resource) {
5530
  i::Handle<i::String> result =
5531
      isolate->factory()->NewExternalStringFromAscii(resource);
5532
  return result;
5533
}
5534

    
5535

    
5536
bool RedirectToExternalString(i::Isolate* isolate,
5537
                              i::Handle<i::String> parent,
5538
                              i::Handle<i::String> external) {
5539
  if (parent->IsConsString()) {
5540
    i::Handle<i::ConsString> cons = i::Handle<i::ConsString>::cast(parent);
5541
    cons->set_first(*external);
5542
    cons->set_second(isolate->heap()->empty_string());
5543
  } else {
5544
    ASSERT(parent->IsSlicedString());
5545
    i::Handle<i::SlicedString> slice = i::Handle<i::SlicedString>::cast(parent);
5546
    slice->set_parent(*external);
5547
    slice->set_offset(0);
5548
  }
5549
  return true;
5550
}
5551

    
5552

    
5553
Local<String> v8::String::NewExternal(
5554
      v8::String::ExternalStringResource* resource) {
5555
  i::Isolate* isolate = i::Isolate::Current();
5556
  EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
5557
  LOG_API(isolate, "String::NewExternal");
5558
  ENTER_V8(isolate);
5559
  CHECK(resource && resource->data());
5560
  i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
5561
  isolate->heap()->external_string_table()->AddString(*result);
5562
  return Utils::ToLocal(result);
5563
}
5564

    
5565

    
5566
bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
5567
  i::Handle<i::String> obj = Utils::OpenHandle(this);
5568
  i::Isolate* isolate = obj->GetIsolate();
5569
  if (i::StringShape(*obj).IsExternalTwoByte()) {
5570
    return false;  // Already an external string.
5571
  }
5572
  ENTER_V8(isolate);
5573
  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5574
    return false;
5575
  }
5576
  if (isolate->heap()->IsInGCPostProcessing()) {
5577
    return false;
5578
  }
5579
  CHECK(resource && resource->data());
5580

    
5581
  bool result;
5582
  i::Handle<i::String> external;
5583
  if (isolate->heap()->old_pointer_space()->Contains(*obj)) {
5584
    // We do not allow external strings in the old pointer space.  Instead of
5585
    // converting the string in-place, we keep the cons/sliced string and
5586
    // point it to a newly-allocated external string.
5587
    external = NewExternalStringHandle(isolate, resource);
5588
    result = RedirectToExternalString(isolate, obj, external);
5589
  } else {
5590
    result = obj->MakeExternal(resource);
5591
    external = obj;
5592
  }
5593

    
5594
  ASSERT(external->IsExternalString());
5595
  if (result && !external->IsInternalizedString()) {
5596
    isolate->heap()->external_string_table()->AddString(*external);
5597
  }
5598
  return result;
5599
}
5600

    
5601

    
5602
Local<String> v8::String::NewExternal(
5603
      v8::String::ExternalAsciiStringResource* resource) {
5604
  i::Isolate* isolate = i::Isolate::Current();
5605
  EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()");
5606
  LOG_API(isolate, "String::NewExternal");
5607
  ENTER_V8(isolate);
5608
  CHECK(resource && resource->data());
5609
  i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
5610
  isolate->heap()->external_string_table()->AddString(*result);
5611
  return Utils::ToLocal(result);
5612
}
5613

    
5614

    
5615
bool v8::String::MakeExternal(
5616
    v8::String::ExternalAsciiStringResource* resource) {
5617
  i::Handle<i::String> obj = Utils::OpenHandle(this);
5618
  i::Isolate* isolate = obj->GetIsolate();
5619
  if (i::StringShape(*obj).IsExternalTwoByte()) {
5620
    return false;  // Already an external string.
5621
  }
5622
  ENTER_V8(isolate);
5623
  if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5624
    return false;
5625
  }
5626
  if (isolate->heap()->IsInGCPostProcessing()) {
5627
    return false;
5628
  }
5629
  CHECK(resource && resource->data());
5630

    
5631
  bool result;
5632
  i::Handle<i::String> external;
5633
  if (isolate->heap()->old_pointer_space()->Contains(*obj)) {
5634
    // We do not allow external strings in the old pointer space.  Instead of
5635
    // converting the string in-place, we keep the cons/sliced string and
5636
    // point it to a newly-allocated external string.
5637
    external = NewExternalAsciiStringHandle(isolate, resource);
5638
    result = RedirectToExternalString(isolate, obj, external);
5639
  } else {
5640
    result = obj->MakeExternal(resource);
5641
    external = obj;
5642
  }
5643

    
5644
  ASSERT(external->IsExternalString());
5645
  if (result && !external->IsInternalizedString()) {
5646
    isolate->heap()->external_string_table()->AddString(*external);
5647
  }
5648
  return result;
5649
}
5650

    
5651

    
5652
bool v8::String::CanMakeExternal() {
5653
  if (!internal::FLAG_clever_optimizations) return false;
5654
  i::Handle<i::String> obj = Utils::OpenHandle(this);
5655
  i::Isolate* isolate = obj->GetIsolate();
5656

    
5657
  // TODO(yangguo): Externalizing sliced/cons strings allocates.
5658
  // This rule can be removed when all code that can
5659
  // trigger an access check is handlified and therefore GC safe.
5660
  if (isolate->heap()->old_pointer_space()->Contains(*obj)) return false;
5661

    
5662
  if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
5663
  int size = obj->Size();  // Byte size of the original string.
5664
  if (size < i::ExternalString::kShortSize) return false;
5665
  i::StringShape shape(*obj);
5666
  return !shape.IsExternal();
5667
}
5668

    
5669

    
5670
Local<v8::Object> v8::Object::New() {
5671
  i::Isolate* isolate = i::Isolate::Current();
5672
  EnsureInitializedForIsolate(isolate, "v8::Object::New()");
5673
  LOG_API(isolate, "Object::New");
5674
  ENTER_V8(isolate);
5675
  i::Handle<i::JSObject> obj =
5676
      isolate->factory()->NewJSObject(isolate->object_function());
5677
  return Utils::ToLocal(obj);
5678
}
5679

    
5680

    
5681
Local<v8::Value> v8::NumberObject::New(double value) {
5682
  i::Isolate* isolate = i::Isolate::Current();
5683
  EnsureInitializedForIsolate(isolate, "v8::NumberObject::New()");
5684
  LOG_API(isolate, "NumberObject::New");
5685
  ENTER_V8(isolate);
5686
  i::Handle<i::Object> number = isolate->factory()->NewNumber(value);
5687
  i::Handle<i::Object> obj = isolate->factory()->ToObject(number);
5688
  return Utils::ToLocal(obj);
5689
}
5690

    
5691

    
5692
double v8::NumberObject::ValueOf() const {
5693
  i::Isolate* isolate = i::Isolate::Current();
5694
  LOG_API(isolate, "NumberObject::NumberValue");
5695
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
5696
  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5697
  return jsvalue->value()->Number();
5698
}
5699

    
5700

    
5701
Local<v8::Value> v8::BooleanObject::New(bool value) {
5702
  i::Isolate* isolate = i::Isolate::Current();
5703
  EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
5704
  LOG_API(isolate, "BooleanObject::New");
5705
  ENTER_V8(isolate);
5706
  i::Handle<i::Object> boolean(value
5707
                               ? isolate->heap()->true_value()
5708
                               : isolate->heap()->false_value(),
5709
                               isolate);
5710
  i::Handle<i::Object> obj = isolate->factory()->ToObject(boolean);
5711
  return Utils::ToLocal(obj);
5712
}
5713

    
5714

    
5715
bool v8::BooleanObject::ValueOf() const {
5716
  i::Isolate* isolate = i::Isolate::Current();
5717
  LOG_API(isolate, "BooleanObject::BooleanValue");
5718
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
5719
  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5720
  return jsvalue->value()->IsTrue();
5721
}
5722

    
5723

    
5724
Local<v8::Value> v8::StringObject::New(Handle<String> value) {
5725
  i::Isolate* isolate = i::Isolate::Current();
5726
  EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
5727
  LOG_API(isolate, "StringObject::New");
5728
  ENTER_V8(isolate);
5729
  i::Handle<i::Object> obj =
5730
      isolate->factory()->ToObject(Utils::OpenHandle(*value));
5731
  return Utils::ToLocal(obj);
5732
}
5733

    
5734

    
5735
Local<v8::String> v8::StringObject::ValueOf() const {
5736
  i::Isolate* isolate = i::Isolate::Current();
5737
  LOG_API(isolate, "StringObject::StringValue");
5738
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
5739
  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5740
  return Utils::ToLocal(
5741
      i::Handle<i::String>(i::String::cast(jsvalue->value())));
5742
}
5743

    
5744

    
5745
Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) {
5746
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5747
  EnsureInitializedForIsolate(i_isolate, "v8::SymbolObject::New()");
5748
  LOG_API(i_isolate, "SymbolObject::New");
5749
  ENTER_V8(i_isolate);
5750
  i::Handle<i::Object> obj =
5751
      i_isolate->factory()->ToObject(Utils::OpenHandle(*value));
5752
  return Utils::ToLocal(obj);
5753
}
5754

    
5755

    
5756
Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
5757
  i::Isolate* isolate = i::Isolate::Current();
5758
  LOG_API(isolate, "SymbolObject::SymbolValue");
5759
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
5760
  i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5761
  return Utils::ToLocal(
5762
      i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
5763
}
5764

    
5765

    
5766
Local<v8::Value> v8::Date::New(double time) {
5767
  i::Isolate* isolate = i::Isolate::Current();
5768
  EnsureInitializedForIsolate(isolate, "v8::Date::New()");
5769
  LOG_API(isolate, "Date::New");
5770
  if (std::isnan(time)) {
5771
    // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
5772
    time = i::OS::nan_value();
5773
  }
5774
  ENTER_V8(isolate);
5775
  EXCEPTION_PREAMBLE(isolate);
5776
  i::Handle<i::Object> obj =
5777
      i::Execution::NewDate(isolate, time, &has_pending_exception);
5778
  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Value>());
5779
  return Utils::ToLocal(obj);
5780
}
5781

    
5782

    
5783
double v8::Date::ValueOf() const {
5784
  i::Isolate* isolate = i::Isolate::Current();
5785
  LOG_API(isolate, "Date::NumberValue");
5786
  i::Handle<i::Object> obj = Utils::OpenHandle(this);
5787
  i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
5788
  return jsdate->value()->Number();
5789
}
5790

    
5791

    
5792
void v8::Date::DateTimeConfigurationChangeNotification() {
5793
  i::Isolate* isolate = i::Isolate::Current();
5794
  ON_BAILOUT(isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
5795
             return);
5796
  LOG_API(isolate, "Date::DateTimeConfigurationChangeNotification");
5797
  ENTER_V8(isolate);
5798

    
5799
  isolate->date_cache()->ResetDateCache();
5800

    
5801
  i::HandleScope scope(isolate);
5802
  // Get the function ResetDateCache (defined in date.js).
5803
  i::Handle<i::String> func_name_str =
5804
      isolate->factory()->InternalizeOneByteString(
5805
          STATIC_ASCII_VECTOR("ResetDateCache"));
5806
  i::MaybeObject* result =
5807
      isolate->js_builtins_object()->GetProperty(*func_name_str);
5808
  i::Object* object_func;
5809
  if (!result->ToObject(&object_func)) {
5810
    return;
5811
  }
5812

    
5813
  if (object_func->IsJSFunction()) {
5814
    i::Handle<i::JSFunction> func =
5815
        i::Handle<i::JSFunction>(i::JSFunction::cast(object_func));
5816

    
5817
    // Call ResetDateCache(0 but expect no exceptions:
5818
    bool caught_exception = false;
5819
    i::Execution::TryCall(func,
5820
                          isolate->js_builtins_object(),
5821
                          0,
5822
                          NULL,
5823
                          &caught_exception);
5824
  }
5825
}
5826

    
5827

    
5828
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
5829
  i::Isolate* isolate = i::Isolate::Current();
5830
  uint8_t flags_buf[3];
5831
  int num_flags = 0;
5832
  if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
5833
  if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
5834
  if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
5835
  ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
5836
  return isolate->factory()->InternalizeOneByteString(
5837
      i::Vector<const uint8_t>(flags_buf, num_flags));
5838
}
5839

    
5840

    
5841
Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
5842
                                  Flags flags) {
5843
  i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
5844
  EnsureInitializedForIsolate(isolate, "v8::RegExp::New()");
5845
  LOG_API(isolate, "RegExp::New");
5846
  ENTER_V8(isolate);
5847
  EXCEPTION_PREAMBLE(isolate);
5848
  i::Handle<i::JSRegExp> obj = i::Execution::NewJSRegExp(
5849
      Utils::OpenHandle(*pattern),
5850
      RegExpFlagsToString(flags),
5851
      &has_pending_exception);
5852
  EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
5853
  return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
5854
}
5855

    
5856

    
5857
Local<v8::String> v8::RegExp::GetSource() const {
5858
  i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5859
  return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
5860
}
5861

    
5862

    
5863
// Assert that the static flags cast in GetFlags is valid.
5864
#define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag)        \
5865
  STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) ==     \
5866
                static_cast<int>(i::JSRegExp::internal_flag))
5867
REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
5868
REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
5869
REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
5870
REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
5871
#undef REGEXP_FLAG_ASSERT_EQ
5872

    
5873
v8::RegExp::Flags v8::RegExp::GetFlags() const {
5874
  i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5875
  return static_cast<RegExp::Flags>(obj->GetFlags().value());
5876
}
5877

    
5878

    
5879
Local<v8::Array> v8::Array::New(int length) {
5880
  i::Isolate* isolate = i::Isolate::Current();
5881
  EnsureInitializedForIsolate(isolate, "v8::Array::New()");
5882
  LOG_API(isolate, "Array::New");
5883
  ENTER_V8(isolate);
5884
  int real_length = length > 0 ? length : 0;
5885
  i::Handle<i::JSArray> obj = isolate->factory()->NewJSArray(real_length);
5886
  i::Handle<i::Object> length_obj =
5887
      isolate->factory()->NewNumberFromInt(real_length);
5888
  obj->set_length(*length_obj);
5889
  return Utils::ToLocal(obj);
5890
}
5891

    
5892

    
5893
uint32_t v8::Array::Length() const {
5894
  i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
5895
  i::Object* length = obj->length();
5896
  if (length->IsSmi()) {
5897
    return i::Smi::cast(length)->value();
5898
  } else {
5899
    return static_cast<uint32_t>(length->Number());
5900
  }
5901
}
5902

    
5903

    
5904
Local<Object> Array::CloneElementAt(uint32_t index) {
5905
  i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
5906
  ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
5907
  i::Handle<i::JSObject> self = Utils::OpenHandle(this);
5908
  if (!self->HasFastObjectElements()) {
5909
    return Local<Object>();
5910
  }
5911
  i::FixedArray* elms = i::FixedArray::cast(self->elements());
5912
  i::Object* paragon = elms->get(index);
5913
  if (!paragon->IsJSObject()) {
5914
    return Local<Object>();
5915
  }
5916
  i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
5917
  EXCEPTION_PREAMBLE(isolate);
5918
  ENTER_V8(isolate);
5919
  i::Handle<i::JSObject> result = i::JSObject::Copy(paragon_handle);
5920
  has_pending_exception = result.is_null();
5921
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
5922
  return Utils::ToLocal(result);
5923
}
5924

    
5925

    
5926
bool v8::ArrayBuffer::IsExternal() const {
5927
  return Utils::OpenHandle(this)->is_external();
5928
}
5929

    
5930

    
5931
v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
5932
  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5933
  ApiCheck(!obj->is_external(),
5934
            "v8::ArrayBuffer::Externalize",
5935
            "ArrayBuffer already externalized");
5936
  obj->set_is_external(true);
5937
  size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
5938
  Contents contents;
5939
  contents.data_ = obj->backing_store();
5940
  contents.byte_length_ = byte_length;
5941
  return contents;
5942
}
5943

    
5944

    
5945
void v8::ArrayBuffer::Neuter() {
5946
  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5947
  i::Isolate* isolate = obj->GetIsolate();
5948
  ApiCheck(obj->is_external(),
5949
           "v8::ArrayBuffer::Neuter",
5950
           "Only externalized ArrayBuffers can be neutered");
5951
  LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
5952
  ENTER_V8(isolate);
5953

    
5954
  for (i::Handle<i::Object> view_obj(obj->weak_first_view(), isolate);
5955
       !view_obj->IsUndefined();) {
5956
    i::Handle<i::JSArrayBufferView> view(i::JSArrayBufferView::cast(*view_obj));
5957
    if (view->IsJSTypedArray()) {
5958
      i::JSTypedArray::cast(*view)->Neuter();
5959
    } else if (view->IsJSDataView()) {
5960
      i::JSDataView::cast(*view)->Neuter();
5961
    } else {
5962
      UNREACHABLE();
5963
    }
5964
    view_obj = i::handle(view->weak_next(), isolate);
5965
  }
5966
  obj->Neuter();
5967
}
5968

    
5969

    
5970
size_t v8::ArrayBuffer::ByteLength() const {
5971
  i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5972
  return static_cast<size_t>(obj->byte_length()->Number());
5973
}
5974

    
5975

    
5976
Local<ArrayBuffer> v8::ArrayBuffer::New(size_t byte_length) {
5977
  i::Isolate* isolate = i::Isolate::Current();
5978
  EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(size_t)");
5979
  LOG_API(isolate, "v8::ArrayBuffer::New(size_t)");
5980
  ENTER_V8(isolate);
5981
  i::Handle<i::JSArrayBuffer> obj =
5982
      isolate->factory()->NewJSArrayBuffer();
5983
  i::Runtime::SetupArrayBufferAllocatingData(isolate, obj, byte_length);
5984
  return Utils::ToLocal(obj);
5985
}
5986

    
5987

    
5988
Local<ArrayBuffer> v8::ArrayBuffer::New(void* data, size_t byte_length) {
5989
  i::Isolate* isolate = i::Isolate::Current();
5990
  EnsureInitializedForIsolate(isolate, "v8::ArrayBuffer::New(void*, size_t)");
5991
  LOG_API(isolate, "v8::ArrayBuffer::New(void*, size_t)");
5992
  ENTER_V8(isolate);
5993
  i::Handle<i::JSArrayBuffer> obj =
5994
      isolate->factory()->NewJSArrayBuffer();
5995
  i::Runtime::SetupArrayBuffer(isolate, obj, true, data, byte_length);
5996
  return Utils::ToLocal(obj);
5997
}
5998

    
5999

    
6000
Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
6001
  i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6002
  ASSERT(obj->buffer()->IsJSArrayBuffer());
6003
  i::Handle<i::JSArrayBuffer> buffer(i::JSArrayBuffer::cast(obj->buffer()));
6004
  return Utils::ToLocal(buffer);
6005
}
6006

    
6007

    
6008
size_t v8::ArrayBufferView::ByteOffset() {
6009
  i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6010
  return static_cast<size_t>(obj->byte_offset()->Number());
6011
}
6012

    
6013

    
6014
size_t v8::ArrayBufferView::ByteLength() {
6015
  i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6016
  return static_cast<size_t>(obj->byte_length()->Number());
6017
}
6018

    
6019

    
6020
size_t v8::TypedArray::Length() {
6021
  i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
6022
  return static_cast<size_t>(obj->length()->Number());
6023
}
6024

    
6025

    
6026
static inline void SetupArrayBufferView(
6027
    i::Isolate* isolate,
6028
    i::Handle<i::JSArrayBufferView> obj,
6029
    i::Handle<i::JSArrayBuffer> buffer,
6030
    size_t byte_offset,
6031
    size_t byte_length) {
6032
  ASSERT(byte_offset + byte_length <=
6033
      static_cast<size_t>(buffer->byte_length()->Number()));
6034

    
6035
  obj->set_buffer(*buffer);
6036

    
6037
  obj->set_weak_next(buffer->weak_first_view());
6038
  buffer->set_weak_first_view(*obj);
6039

    
6040
  i::Handle<i::Object> byte_offset_object =
6041
    isolate->factory()->NewNumberFromSize(byte_offset);
6042
  obj->set_byte_offset(*byte_offset_object);
6043

    
6044
  i::Handle<i::Object> byte_length_object =
6045
    isolate->factory()->NewNumberFromSize(byte_length);
6046
  obj->set_byte_length(*byte_length_object);
6047
}
6048

    
6049
template<typename ElementType,
6050
         ExternalArrayType array_type,
6051
         i::ElementsKind elements_kind>
6052
i::Handle<i::JSTypedArray> NewTypedArray(
6053
    i::Isolate* isolate,
6054
    Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
6055
  i::Handle<i::JSTypedArray> obj =
6056
      isolate->factory()->NewJSTypedArray(array_type);
6057
  i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6058

    
6059
  ASSERT(byte_offset % sizeof(ElementType) == 0);
6060

    
6061
  SetupArrayBufferView(
6062
      isolate, obj, buffer, byte_offset, length * sizeof(ElementType));
6063

    
6064
  i::Handle<i::Object> length_object =
6065
    isolate->factory()->NewNumberFromSize(length);
6066
  obj->set_length(*length_object);
6067

    
6068
  i::Handle<i::ExternalArray> elements =
6069
      isolate->factory()->NewExternalArray(
6070
          static_cast<int>(length), array_type,
6071
          static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
6072
  obj->set_elements(*elements);
6073
  return obj;
6074
}
6075

    
6076

    
6077
#define TYPED_ARRAY_NEW(TypedArray, element_type, array_type, elements_kind) \
6078
  Local<TypedArray> TypedArray::New(Handle<ArrayBuffer> array_buffer,        \
6079
                                    size_t byte_offset, size_t length) {     \
6080
    i::Isolate* isolate = i::Isolate::Current();                             \
6081
    EnsureInitializedForIsolate(isolate,                                     \
6082
        "v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)");    \
6083
    LOG_API(isolate,                                                         \
6084
        "v8::" #TypedArray "::New(Handle<ArrayBuffer>, size_t, size_t)");    \
6085
    ENTER_V8(isolate);                                                       \
6086
    i::Handle<i::JSTypedArray> obj =                                         \
6087
        NewTypedArray<element_type, array_type, elements_kind>(              \
6088
            isolate, array_buffer, byte_offset, length);                     \
6089
    return Utils::ToLocal##TypedArray(obj);                                  \
6090
  }
6091

    
6092

    
6093
TYPED_ARRAY_NEW(Uint8Array, uint8_t, kExternalUnsignedByteArray,
6094
                i::EXTERNAL_UNSIGNED_BYTE_ELEMENTS)
6095
TYPED_ARRAY_NEW(Uint8ClampedArray, uint8_t, kExternalPixelArray,
6096
                i::EXTERNAL_PIXEL_ELEMENTS)
6097
TYPED_ARRAY_NEW(Int8Array, int8_t, kExternalByteArray,
6098
                i::EXTERNAL_BYTE_ELEMENTS)
6099
TYPED_ARRAY_NEW(Uint16Array, uint16_t, kExternalUnsignedShortArray,
6100
                i::EXTERNAL_UNSIGNED_SHORT_ELEMENTS)
6101
TYPED_ARRAY_NEW(Int16Array, int16_t, kExternalShortArray,
6102
                i::EXTERNAL_SHORT_ELEMENTS)
6103
TYPED_ARRAY_NEW(Uint32Array, uint32_t, kExternalUnsignedIntArray,
6104
                i::EXTERNAL_UNSIGNED_INT_ELEMENTS)
6105
TYPED_ARRAY_NEW(Int32Array, int32_t, kExternalIntArray,
6106
                i::EXTERNAL_INT_ELEMENTS)
6107
TYPED_ARRAY_NEW(Float32Array, float, kExternalFloatArray,
6108
                i::EXTERNAL_FLOAT_ELEMENTS)
6109
TYPED_ARRAY_NEW(Float64Array, double, kExternalDoubleArray,
6110
                i::EXTERNAL_DOUBLE_ELEMENTS)
6111

    
6112
#undef TYPED_ARRAY_NEW
6113

    
6114
Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
6115
                              size_t byte_offset, size_t byte_length) {
6116
  i::Isolate* isolate = i::Isolate::Current();
6117
  EnsureInitializedForIsolate(
6118
      isolate, "v8::DataView::New(void*, size_t, size_t)");
6119
  LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
6120
  ENTER_V8(isolate);
6121
  i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
6122
  i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6123
  SetupArrayBufferView(
6124
      isolate, obj, buffer, byte_offset, byte_length);
6125
  return Utils::ToLocal(obj);
6126
}
6127

    
6128

    
6129
Local<Symbol> v8::Symbol::New(Isolate* isolate) {
6130
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6131
  EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
6132
  LOG_API(i_isolate, "Symbol::New()");
6133
  ENTER_V8(i_isolate);
6134
  i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
6135
  return Utils::ToLocal(result);
6136
}
6137

    
6138

    
6139
Local<Symbol> v8::Symbol::New(Isolate* isolate, const char* data, int length) {
6140
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6141
  EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
6142
  LOG_API(i_isolate, "Symbol::New(char)");
6143
  ENTER_V8(i_isolate);
6144
  if (length == -1) length = i::StrLength(data);
6145
  i::Handle<i::String> name = i_isolate->factory()->NewStringFromUtf8(
6146
      i::Vector<const char>(data, length));
6147
  i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
6148
  result->set_name(*name);
6149
  return Utils::ToLocal(result);
6150
}
6151

    
6152

    
6153
Local<Number> v8::Number::New(double value) {
6154
  i::Isolate* isolate = i::Isolate::Current();
6155
  EnsureInitializedForIsolate(isolate, "v8::Number::New()");
6156
  return Number::New(reinterpret_cast<Isolate*>(isolate), value);
6157
}
6158

    
6159

    
6160
Local<Number> v8::Number::New(Isolate* isolate, double value) {
6161
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6162
  ASSERT(internal_isolate->IsInitialized());
6163
  if (std::isnan(value)) {
6164
    // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
6165
    value = i::OS::nan_value();
6166
  }
6167
  ENTER_V8(internal_isolate);
6168
  i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6169
  return Utils::NumberToLocal(result);
6170
}
6171

    
6172

    
6173
Local<Integer> v8::Integer::New(int32_t value) {
6174
  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6175
  EnsureInitializedForIsolate(isolate, "v8::Integer::New()");
6176
  return v8::Integer::New(value, reinterpret_cast<Isolate*>(isolate));
6177
}
6178

    
6179

    
6180
Local<Integer> Integer::NewFromUnsigned(uint32_t value) {
6181
  i::Isolate* isolate = i::Isolate::Current();
6182
  EnsureInitializedForIsolate(isolate, "v8::Integer::NewFromUnsigned()");
6183
  return Integer::NewFromUnsigned(value, reinterpret_cast<Isolate*>(isolate));
6184
}
6185

    
6186

    
6187
Local<Integer> v8::Integer::New(int32_t value, Isolate* isolate) {
6188
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6189
  ASSERT(internal_isolate->IsInitialized());
6190
  if (i::Smi::IsValid(value)) {
6191
    return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
6192
                                                      internal_isolate));
6193
  }
6194
  ENTER_V8(internal_isolate);
6195
  i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6196
  return Utils::IntegerToLocal(result);
6197
}
6198

    
6199

    
6200
Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) {
6201
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6202
  ASSERT(internal_isolate->IsInitialized());
6203
  bool fits_into_int32_t = (value & (1 << 31)) == 0;
6204
  if (fits_into_int32_t) {
6205
    return Integer::New(static_cast<int32_t>(value), isolate);
6206
  }
6207
  ENTER_V8(internal_isolate);
6208
  i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6209
  return Utils::IntegerToLocal(result);
6210
}
6211

    
6212

    
6213
#ifdef DEBUG
6214
v8::AssertNoGCScope::AssertNoGCScope(v8::Isolate* isolate) {
6215
  disallow_heap_allocation_ = new i::DisallowHeapAllocation();
6216
}
6217

    
6218

    
6219
v8::AssertNoGCScope::~AssertNoGCScope() {
6220
  delete static_cast<i::DisallowHeapAllocation*>(disallow_heap_allocation_);
6221
}
6222
#endif
6223

    
6224

    
6225
void V8::IgnoreOutOfMemoryException() {
6226
  EnterIsolateIfNeeded()->set_ignore_out_of_memory(true);
6227
}
6228

    
6229

    
6230
bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
6231
  i::Isolate* isolate = i::Isolate::Current();
6232
  EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()");
6233
  ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
6234
  ENTER_V8(isolate);
6235
  i::HandleScope scope(isolate);
6236
  NeanderArray listeners(isolate->factory()->message_listeners());
6237
  NeanderObject obj(2);
6238
  obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
6239
  obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
6240
                            : *Utils::OpenHandle(*data));
6241
  listeners.add(obj.value());
6242
  return true;
6243
}
6244

    
6245

    
6246
void V8::RemoveMessageListeners(MessageCallback that) {
6247
  i::Isolate* isolate = i::Isolate::Current();
6248
  EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()");
6249
  ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
6250
  ENTER_V8(isolate);
6251
  i::HandleScope scope(isolate);
6252
  NeanderArray listeners(isolate->factory()->message_listeners());
6253
  for (int i = 0; i < listeners.length(); i++) {
6254
    if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
6255

    
6256
    NeanderObject listener(i::JSObject::cast(listeners.get(i)));
6257
    i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0)));
6258
    if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) {
6259
      listeners.set(i, isolate->heap()->undefined_value());
6260
    }
6261
  }
6262
}
6263

    
6264

    
6265
void V8::SetCaptureStackTraceForUncaughtExceptions(
6266
      bool capture,
6267
      int frame_limit,
6268
      StackTrace::StackTraceOptions options) {
6269
  i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
6270
      capture,
6271
      frame_limit,
6272
      options);
6273
}
6274

    
6275

    
6276
void V8::SetCounterFunction(CounterLookupCallback callback) {
6277
  i::Isolate* isolate = EnterIsolateIfNeeded();
6278
  isolate->stats_table()->SetCounterFunction(callback);
6279
}
6280

    
6281

    
6282
void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) {
6283
  i::Isolate* isolate = EnterIsolateIfNeeded();
6284
  isolate->stats_table()->SetCreateHistogramFunction(callback);
6285
  isolate->InitializeLoggingAndCounters();
6286
  isolate->counters()->ResetHistograms();
6287
}
6288

    
6289

    
6290
void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) {
6291
  i::Isolate* isolate = EnterIsolateIfNeeded();
6292
  isolate->stats_table()->
6293
      SetAddHistogramSampleFunction(callback);
6294
}
6295

    
6296
void V8::SetFailedAccessCheckCallbackFunction(
6297
      FailedAccessCheckCallback callback) {
6298
  i::Isolate* isolate = i::Isolate::Current();
6299
  isolate->SetFailedAccessCheckCallback(callback);
6300
}
6301

    
6302

    
6303
intptr_t Isolate::AdjustAmountOfExternalAllocatedMemory(
6304
    intptr_t change_in_bytes) {
6305
  i::Heap* heap = reinterpret_cast<i::Isolate*>(this)->heap();
6306
  return heap->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
6307
}
6308

    
6309

    
6310
intptr_t V8::AdjustAmountOfExternalAllocatedMemory(intptr_t change_in_bytes) {
6311
  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6312
  if (isolate == NULL || !isolate->IsInitialized()) {
6313
    return 0;
6314
  }
6315
  Isolate* isolate_ext = reinterpret_cast<Isolate*>(isolate);
6316
  return isolate_ext->AdjustAmountOfExternalAllocatedMemory(change_in_bytes);
6317
}
6318

    
6319

    
6320
HeapProfiler* Isolate::GetHeapProfiler() {
6321
  i::HeapProfiler* heap_profiler =
6322
      reinterpret_cast<i::Isolate*>(this)->heap_profiler();
6323
  return reinterpret_cast<HeapProfiler*>(heap_profiler);
6324
}
6325

    
6326

    
6327
CpuProfiler* Isolate::GetCpuProfiler() {
6328
  i::CpuProfiler* cpu_profiler =
6329
      reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
6330
  return reinterpret_cast<CpuProfiler*>(cpu_profiler);
6331
}
6332

    
6333

    
6334
bool Isolate::InContext() {
6335
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6336
  return isolate->context() != NULL;
6337
}
6338

    
6339

    
6340
v8::Local<v8::Context> Isolate::GetCurrentContext() {
6341
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6342
  i::Context* context = isolate->context();
6343
  if (context == NULL) return Local<Context>();
6344
  i::Context* native_context = context->global_object()->native_context();
6345
  if (native_context == NULL) return Local<Context>();
6346
  return Utils::ToLocal(i::Handle<i::Context>(native_context));
6347
}
6348

    
6349

    
6350
v8::Local<v8::Context> Isolate::GetCallingContext() {
6351
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6352
  i::Handle<i::Object> calling = isolate->GetCallingNativeContext();
6353
  if (calling.is_null()) return Local<Context>();
6354
  return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
6355
}
6356

    
6357

    
6358
v8::Local<v8::Context> Isolate::GetEnteredContext() {
6359
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6360
  i::Handle<i::Object> last =
6361
      isolate->handle_scope_implementer()->LastEnteredContext();
6362
  if (last.is_null()) return Local<Context>();
6363
  return Utils::ToLocal(i::Handle<i::Context>::cast(last));
6364
}
6365

    
6366

    
6367
v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
6368
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6369
  ENTER_V8(isolate);
6370
  // If we're passed an empty handle, we throw an undefined exception
6371
  // to deal more gracefully with out of memory situations.
6372
  if (value.IsEmpty()) {
6373
    isolate->ScheduleThrow(isolate->heap()->undefined_value());
6374
  } else {
6375
    isolate->ScheduleThrow(*Utils::OpenHandle(*value));
6376
  }
6377
  return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6378
}
6379

    
6380

    
6381
void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
6382
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6383
  internal_isolate->global_handles()->SetObjectGroupId(
6384
      v8::internal::Handle<v8::internal::Object>(object).location(),
6385
      id);
6386
}
6387

    
6388

    
6389
void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
6390
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6391
  internal_isolate->global_handles()->SetReferenceFromGroup(
6392
      id,
6393
      v8::internal::Handle<v8::internal::Object>(object).location());
6394
}
6395

    
6396

    
6397
void Isolate::SetReference(internal::Object** parent,
6398
                           internal::Object** child) {
6399
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6400
  i::Object** parent_location =
6401
      v8::internal::Handle<v8::internal::Object>(parent).location();
6402
  internal_isolate->global_handles()->SetReference(
6403
      reinterpret_cast<i::HeapObject**>(parent_location),
6404
      v8::internal::Handle<v8::internal::Object>(child).location());
6405
}
6406

    
6407

    
6408
void Isolate::AddGCPrologueCallback(GCPrologueCallback callback,
6409
                                    GCType gc_type) {
6410
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6411
  isolate->heap()->AddGCPrologueCallback(callback, gc_type);
6412
}
6413

    
6414

    
6415
void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6416
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6417
  isolate->heap()->RemoveGCPrologueCallback(callback);
6418
}
6419

    
6420

    
6421
void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback,
6422
                                    GCType gc_type) {
6423
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6424
  isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
6425
}
6426

    
6427

    
6428
void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6429
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6430
  isolate->heap()->RemoveGCEpilogueCallback(callback);
6431
}
6432

    
6433

    
6434
void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
6435
  i::Isolate* isolate = i::Isolate::Current();
6436
  isolate->heap()->AddGCPrologueCallback(
6437
      reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback),
6438
      gc_type,
6439
      false);
6440
}
6441

    
6442

    
6443
void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6444
  i::Isolate* isolate = i::Isolate::Current();
6445
  isolate->heap()->RemoveGCPrologueCallback(
6446
      reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback));
6447
}
6448

    
6449

    
6450
void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
6451
  i::Isolate* isolate = i::Isolate::Current();
6452
  isolate->heap()->AddGCEpilogueCallback(
6453
      reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback),
6454
      gc_type,
6455
      false);
6456
}
6457

    
6458

    
6459
void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6460
  i::Isolate* isolate = i::Isolate::Current();
6461
  isolate->heap()->RemoveGCEpilogueCallback(
6462
      reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback));
6463
}
6464

    
6465

    
6466
void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
6467
                                     ObjectSpace space,
6468
                                     AllocationAction action) {
6469
  i::Isolate* isolate = i::Isolate::Current();
6470
  isolate->memory_allocator()->AddMemoryAllocationCallback(
6471
      callback, space, action);
6472
}
6473

    
6474

    
6475
void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
6476
  i::Isolate* isolate = i::Isolate::Current();
6477
  isolate->memory_allocator()->RemoveMemoryAllocationCallback(
6478
      callback);
6479
}
6480

    
6481

    
6482
void V8::AddCallCompletedCallback(CallCompletedCallback callback) {
6483
  if (callback == NULL) return;
6484
  i::V8::AddCallCompletedCallback(callback);
6485
}
6486

    
6487

    
6488
void V8::RemoveCallCompletedCallback(CallCompletedCallback callback) {
6489
  i::V8::RemoveCallCompletedCallback(callback);
6490
}
6491

    
6492

    
6493
void V8::TerminateExecution(Isolate* isolate) {
6494
  // If no isolate is supplied, use the default isolate.
6495
  if (isolate != NULL) {
6496
    reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->TerminateExecution();
6497
  } else {
6498
    i::Isolate::GetDefaultIsolateStackGuard()->TerminateExecution();
6499
  }
6500
}
6501

    
6502

    
6503
bool V8::IsExecutionTerminating(Isolate* isolate) {
6504
  i::Isolate* i_isolate = isolate != NULL ?
6505
      reinterpret_cast<i::Isolate*>(isolate) : i::Isolate::Current();
6506
  return IsExecutionTerminatingCheck(i_isolate);
6507
}
6508

    
6509

    
6510
void V8::CancelTerminateExecution(Isolate* isolate) {
6511
  i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6512
  i_isolate->stack_guard()->CancelTerminateExecution();
6513
}
6514

    
6515

    
6516
Isolate* Isolate::GetCurrent() {
6517
  i::Isolate* isolate = i::Isolate::UncheckedCurrent();
6518
  return reinterpret_cast<Isolate*>(isolate);
6519
}
6520

    
6521

    
6522
Isolate* Isolate::New() {
6523
  i::Isolate* isolate = new i::Isolate();
6524
  return reinterpret_cast<Isolate*>(isolate);
6525
}
6526

    
6527

    
6528
void Isolate::Dispose() {
6529
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6530
  if (!ApiCheck(!isolate->IsInUse(),
6531
                "v8::Isolate::Dispose()",
6532
                "Disposing the isolate that is entered by a thread.")) {
6533
    return;
6534
  }
6535
  isolate->TearDown();
6536
}
6537

    
6538

    
6539
void Isolate::Enter() {
6540
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6541
  isolate->Enter();
6542
}
6543

    
6544

    
6545
void Isolate::Exit() {
6546
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6547
  isolate->Exit();
6548
}
6549

    
6550

    
6551
void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
6552
  i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6553
  if (!isolate->IsInitialized()) {
6554
    heap_statistics->total_heap_size_ = 0;
6555
    heap_statistics->total_heap_size_executable_ = 0;
6556
    heap_statistics->total_physical_size_ = 0;
6557
    heap_statistics->used_heap_size_ = 0;
6558
    heap_statistics->heap_size_limit_ = 0;
6559
    return;
6560
  }
6561
  i::Heap* heap = isolate->heap();
6562
  heap_statistics->total_heap_size_ = heap->CommittedMemory();
6563
  heap_statistics->total_heap_size_executable_ =
6564
      heap->CommittedMemoryExecutable();
6565
  heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
6566
  heap_statistics->used_heap_size_ = heap->SizeOfObjects();
6567
  heap_statistics->heap_size_limit_ = heap->MaxReserved();
6568
}
6569

    
6570

    
6571
String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
6572
    : str_(NULL), length_(0) {
6573
  i::Isolate* isolate = i::Isolate::Current();
6574
  if (obj.IsEmpty()) return;
6575
  ENTER_V8(isolate);
6576
  i::HandleScope scope(isolate);
6577
  TryCatch try_catch;
6578
  Handle<String> str = obj->ToString();
6579
  if (str.IsEmpty()) return;
6580
  i::Handle<i::String> i_str = Utils::OpenHandle(*str);
6581
  length_ = v8::Utf8Length(*i_str, isolate);
6582
  str_ = i::NewArray<char>(length_ + 1);
6583
  str->WriteUtf8(str_);
6584
}
6585

    
6586

    
6587
String::Utf8Value::~Utf8Value() {
6588
  i::DeleteArray(str_);
6589
}
6590

    
6591

    
6592
String::AsciiValue::AsciiValue(v8::Handle<v8::Value> obj)
6593
    : str_(NULL), length_(0) {
6594
  i::Isolate* isolate = i::Isolate::Current();
6595
  if (obj.IsEmpty()) return;
6596
  ENTER_V8(isolate);
6597
  i::HandleScope scope(isolate);
6598
  TryCatch try_catch;
6599
  Handle<String> str = obj->ToString();
6600
  if (str.IsEmpty()) return;
6601
  length_ = str->Utf8Length();
6602
  str_ = i::NewArray<char>(length_ + 1);
6603
  str->WriteUtf8(str_);
6604
  ASSERT(i::String::NonAsciiStart(str_, length_) >= length_);
6605
}
6606

    
6607

    
6608
String::AsciiValue::~AsciiValue() {
6609
  i::DeleteArray(str_);
6610
}
6611

    
6612

    
6613
String::Value::Value(v8::Handle<v8::Value> obj)
6614
    : str_(NULL), length_(0) {
6615
  i::Isolate* isolate = i::Isolate::Current();
6616
  if (obj.IsEmpty()) return;
6617
  ENTER_V8(isolate);
6618
  i::HandleScope scope(isolate);
6619
  TryCatch try_catch;
6620
  Handle<String> str = obj->ToString();
6621
  if (str.IsEmpty()) return;
6622
  length_ = str->Length();
6623
  str_ = i::NewArray<uint16_t>(length_ + 1);
6624
  str->Write(str_);
6625
}
6626

    
6627

    
6628
String::Value::~Value() {
6629
  i::DeleteArray(str_);
6630
}
6631

    
6632

    
6633
Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
6634
  i::Isolate* isolate = i::Isolate::Current();
6635
  LOG_API(isolate, "RangeError");
6636
  ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
6637
  ENTER_V8(isolate);
6638
  i::Object* error;
6639
  {
6640
    i::HandleScope scope(isolate);
6641
    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6642
    i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
6643
    error = *result;
6644
  }
6645
  i::Handle<i::Object> result(error, isolate);
6646
  return Utils::ToLocal(result);
6647
}
6648

    
6649

    
6650
Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
6651
  i::Isolate* isolate = i::Isolate::Current();
6652
  LOG_API(isolate, "ReferenceError");
6653
  ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>());
6654
  ENTER_V8(isolate);
6655
  i::Object* error;
6656
  {
6657
    i::HandleScope scope(isolate);
6658
    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6659
    i::Handle<i::Object> result =
6660
        isolate->factory()->NewReferenceError(message);
6661
    error = *result;
6662
  }
6663
  i::Handle<i::Object> result(error, isolate);
6664
  return Utils::ToLocal(result);
6665
}
6666

    
6667

    
6668
Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
6669
  i::Isolate* isolate = i::Isolate::Current();
6670
  LOG_API(isolate, "SyntaxError");
6671
  ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>());
6672
  ENTER_V8(isolate);
6673
  i::Object* error;
6674
  {
6675
    i::HandleScope scope(isolate);
6676
    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6677
    i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message);
6678
    error = *result;
6679
  }
6680
  i::Handle<i::Object> result(error, isolate);
6681
  return Utils::ToLocal(result);
6682
}
6683

    
6684

    
6685
Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
6686
  i::Isolate* isolate = i::Isolate::Current();
6687
  LOG_API(isolate, "TypeError");
6688
  ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>());
6689
  ENTER_V8(isolate);
6690
  i::Object* error;
6691
  {
6692
    i::HandleScope scope(isolate);
6693
    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6694
    i::Handle<i::Object> result = isolate->factory()->NewTypeError(message);
6695
    error = *result;
6696
  }
6697
  i::Handle<i::Object> result(error, isolate);
6698
  return Utils::ToLocal(result);
6699
}
6700

    
6701

    
6702
Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
6703
  i::Isolate* isolate = i::Isolate::Current();
6704
  LOG_API(isolate, "Error");
6705
  ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>());
6706
  ENTER_V8(isolate);
6707
  i::Object* error;
6708
  {
6709
    i::HandleScope scope(isolate);
6710
    i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6711
    i::Handle<i::Object> result = isolate->factory()->NewError(message);
6712
    error = *result;
6713
  }
6714
  i::Handle<i::Object> result(error, isolate);
6715
  return Utils::ToLocal(result);
6716
}
6717

    
6718

    
6719
// --- D e b u g   S u p p o r t ---
6720

    
6721
#ifdef ENABLE_DEBUGGER_SUPPORT
6722

    
6723
bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) {
6724
  i::Isolate* isolate = i::Isolate::Current();
6725
  EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener2()");
6726
  ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener2()", return false);
6727
  ENTER_V8(isolate);
6728
  i::HandleScope scope(isolate);
6729
  i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
6730
  if (that != NULL) {
6731
    foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
6732
  }
6733
  isolate->debugger()->SetEventListener(foreign,
6734
                                        Utils::OpenHandle(*data, true));
6735
  return true;
6736
}
6737

    
6738

    
6739
bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that,
6740
                                  Handle<Value> data) {
6741
  i::Isolate* isolate = i::Isolate::Current();
6742
  ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
6743
  ENTER_V8(isolate);
6744
  isolate->debugger()->SetEventListener(Utils::OpenHandle(*that),
6745
                                        Utils::OpenHandle(*data, true));
6746
  return true;
6747
}
6748

    
6749

    
6750
void Debug::DebugBreak(Isolate* isolate) {
6751
  // If no isolate is supplied, use the default isolate.
6752
  if (isolate != NULL) {
6753
    reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->DebugBreak();
6754
  } else {
6755
    i::Isolate::GetDefaultIsolateStackGuard()->DebugBreak();
6756
  }
6757
}
6758

    
6759

    
6760
void Debug::CancelDebugBreak(Isolate* isolate) {
6761
  // If no isolate is supplied, use the default isolate.
6762
  if (isolate != NULL) {
6763
    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6764
    internal_isolate->stack_guard()->Continue(i::DEBUGBREAK);
6765
  } else {
6766
    i::Isolate::GetDefaultIsolateStackGuard()->Continue(i::DEBUGBREAK);
6767
  }
6768
}
6769

    
6770

    
6771
void Debug::DebugBreakForCommand(ClientData* data, Isolate* isolate) {
6772
  // If no isolate is supplied, use the default isolate.
6773
  if (isolate != NULL) {
6774
    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6775
    internal_isolate->debugger()->EnqueueDebugCommand(data);
6776
  } else {
6777
    i::Isolate::GetDefaultIsolateDebugger()->EnqueueDebugCommand(data);
6778
  }
6779
}
6780

    
6781

    
6782
void Debug::SetMessageHandler2(v8::Debug::MessageHandler2 handler) {
6783
  i::Isolate* isolate = i::Isolate::Current();
6784
  EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
6785
  ENTER_V8(isolate);
6786
  isolate->debugger()->SetMessageHandler(handler);
6787
}
6788

    
6789

    
6790
void Debug::SendCommand(Isolate* isolate,
6791
                        const uint16_t* command,
6792
                        int length,
6793
                        ClientData* client_data) {
6794
  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6795
  internal_isolate->debugger()->ProcessCommand(
6796
      i::Vector<const uint16_t>(command, length), client_data);
6797
}
6798

    
6799

    
6800
void Debug::SendCommand(const uint16_t* command, int length,
6801
                        ClientData* client_data,
6802
                        Isolate* isolate) {
6803
  // If no isolate is supplied, use the default isolate.
6804
  if (isolate != NULL) {
6805
    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6806
    internal_isolate->debugger()->ProcessCommand(
6807
        i::Vector<const uint16_t>(command, length), client_data);
6808
  } else {
6809
    i::Isolate::GetDefaultIsolateDebugger()->ProcessCommand(
6810
        i::Vector<const uint16_t>(command, length), client_data);
6811
  }
6812
}
6813

    
6814

    
6815
void Debug::SetHostDispatchHandler(HostDispatchHandler handler,
6816
                                   int period) {
6817
  i::Isolate* isolate = i::Isolate::Current();
6818
  EnsureInitializedForIsolate(isolate, "v8::Debug::SetHostDispatchHandler");
6819
  ENTER_V8(isolate);
6820
  isolate->debugger()->SetHostDispatchHandler(
6821
      handler, i::TimeDelta::FromMilliseconds(period));
6822
}
6823

    
6824

    
6825
void Debug::SetDebugMessageDispatchHandler(
6826
    DebugMessageDispatchHandler handler, bool provide_locker) {
6827
  i::Isolate* isolate = i::Isolate::Current();
6828
  EnsureInitializedForIsolate(isolate,
6829
                              "v8::Debug::SetDebugMessageDispatchHandler");
6830
  ENTER_V8(isolate);
6831
  isolate->debugger()->SetDebugMessageDispatchHandler(
6832
      handler, provide_locker);
6833
}
6834

    
6835

    
6836
Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
6837
                         v8::Handle<v8::Value> data) {
6838
  i::Isolate* isolate = i::Isolate::Current();
6839
  if (!isolate->IsInitialized()) return Local<Value>();
6840
  ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
6841
  ENTER_V8(isolate);
6842
  i::Handle<i::Object> result;
6843
  EXCEPTION_PREAMBLE(isolate);
6844
  if (data.IsEmpty()) {
6845
    result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
6846
                                       isolate->factory()->undefined_value(),
6847
                                       &has_pending_exception);
6848
  } else {
6849
    result = isolate->debugger()->Call(Utils::OpenHandle(*fun),
6850
                                       Utils::OpenHandle(*data),
6851
                                       &has_pending_exception);
6852
  }
6853
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6854
  return Utils::ToLocal(result);
6855
}
6856

    
6857

    
6858
Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
6859
  i::Isolate* isolate = i::Isolate::Current();
6860
  if (!isolate->IsInitialized()) return Local<Value>();
6861
  ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
6862
  ENTER_V8(isolate);
6863
  v8::HandleScope scope(reinterpret_cast<Isolate*>(isolate));
6864
  i::Debug* isolate_debug = isolate->debug();
6865
  isolate_debug->Load();
6866
  i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object());
6867
  i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
6868
      STATIC_ASCII_VECTOR("MakeMirror"));
6869
  i::Handle<i::Object> fun_obj = i::GetProperty(isolate, debug, name);
6870
  i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
6871
  v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
6872
  const int kArgc = 1;
6873
  v8::Handle<v8::Value> argv[kArgc] = { obj };
6874
  EXCEPTION_PREAMBLE(isolate);
6875
  v8::Handle<v8::Value> result = v8_fun->Call(Utils::ToLocal(debug),
6876
                                              kArgc,
6877
                                              argv);
6878
  EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6879
  return scope.Close(result);
6880
}
6881

    
6882

    
6883
bool Debug::EnableAgent(const char* name, int port, bool wait_for_connection) {
6884
  return i::Isolate::Current()->debugger()->StartAgent(name, port,
6885
                                                       wait_for_connection);
6886
}
6887

    
6888

    
6889
void Debug::DisableAgent() {
6890
  return i::Isolate::Current()->debugger()->StopAgent();
6891
}
6892

    
6893

    
6894
void Debug::ProcessDebugMessages() {
6895
  i::Execution::ProcessDebugMessages(i::Isolate::Current(), true);
6896
}
6897

    
6898

    
6899
Local<Context> Debug::GetDebugContext() {
6900
  i::Isolate* isolate = i::Isolate::Current();
6901
  EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()");
6902
  ENTER_V8(isolate);
6903
  return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext());
6904
}
6905

    
6906

    
6907
void Debug::SetLiveEditEnabled(bool enable, Isolate* isolate) {
6908
  // If no isolate is supplied, use the default isolate.
6909
  i::Debugger* debugger;
6910
  if (isolate != NULL) {
6911
    i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6912
    debugger = internal_isolate->debugger();
6913
  } else {
6914
    debugger = i::Isolate::GetDefaultIsolateDebugger();
6915
  }
6916
  debugger->set_live_edit_enabled(enable);
6917
}
6918

    
6919

    
6920
#endif  // ENABLE_DEBUGGER_SUPPORT
6921

    
6922

    
6923
Handle<String> CpuProfileNode::GetFunctionName() const {
6924
  i::Isolate* isolate = i::Isolate::Current();
6925
  const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6926
  const i::CodeEntry* entry = node->entry();
6927
  if (!entry->has_name_prefix()) {
6928
    return ToApiHandle<String>(
6929
        isolate->factory()->InternalizeUtf8String(entry->name()));
6930
  } else {
6931
    return ToApiHandle<String>(isolate->factory()->NewConsString(
6932
        isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
6933
        isolate->factory()->InternalizeUtf8String(entry->name())));
6934
  }
6935
}
6936

    
6937

    
6938
int CpuProfileNode::GetScriptId() const {
6939
  const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6940
  const i::CodeEntry* entry = node->entry();
6941
  return entry->script_id();
6942
}
6943

    
6944

    
6945
Handle<String> CpuProfileNode::GetScriptResourceName() const {
6946
  i::Isolate* isolate = i::Isolate::Current();
6947
  const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6948
  return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
6949
      node->entry()->resource_name()));
6950
}
6951

    
6952

    
6953
int CpuProfileNode::GetLineNumber() const {
6954
  return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
6955
}
6956

    
6957

    
6958
int CpuProfileNode::GetColumnNumber() const {
6959
  return reinterpret_cast<const i::ProfileNode*>(this)->
6960
      entry()->column_number();
6961
}
6962

    
6963

    
6964
const char* CpuProfileNode::GetBailoutReason() const {
6965
  const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6966
  return node->entry()->bailout_reason();
6967
}
6968

    
6969

    
6970
unsigned CpuProfileNode::GetHitCount() const {
6971
  return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
6972
}
6973

    
6974

    
6975
unsigned CpuProfileNode::GetCallUid() const {
6976
  return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
6977
}
6978

    
6979

    
6980
unsigned CpuProfileNode::GetNodeId() const {
6981
  return reinterpret_cast<const i::ProfileNode*>(this)->id();
6982
}
6983

    
6984

    
6985
int CpuProfileNode::GetChildrenCount() const {
6986
  return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
6987
}
6988

    
6989

    
6990
const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
6991
  const i::ProfileNode* child =
6992
      reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
6993
  return reinterpret_cast<const CpuProfileNode*>(child);
6994
}
6995

    
6996

    
6997
void CpuProfile::Delete() {
6998
  i::Isolate* isolate = i::Isolate::Current();
6999
  i::CpuProfiler* profiler = isolate->cpu_profiler();
7000
  ASSERT(profiler != NULL);
7001
  profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
7002
  if (profiler->GetProfilesCount() == 0) {
7003
    // If this was the last profile, clean up all accessory data as well.
7004
    profiler->DeleteAllProfiles();
7005
  }
7006
}
7007

    
7008

    
7009
unsigned CpuProfile::GetUid() const {
7010
  return reinterpret_cast<const i::CpuProfile*>(this)->uid();
7011
}
7012

    
7013

    
7014
Handle<String> CpuProfile::GetTitle() const {
7015
  i::Isolate* isolate = i::Isolate::Current();
7016
  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7017
  return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7018
      profile->title()));
7019
}
7020

    
7021

    
7022
const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
7023
  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7024
  return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
7025
}
7026

    
7027

    
7028
const CpuProfileNode* CpuProfile::GetSample(int index) const {
7029
  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7030
  return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
7031
}
7032

    
7033

    
7034
int64_t CpuProfile::GetStartTime() const {
7035
  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7036
  return (profile->start_time() - i::Time::UnixEpoch()).InMicroseconds();
7037
}
7038

    
7039

    
7040
int64_t CpuProfile::GetEndTime() const {
7041
  const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7042
  return (profile->end_time() - i::Time::UnixEpoch()).InMicroseconds();
7043
}
7044

    
7045

    
7046
int CpuProfile::GetSamplesCount() const {
7047
  return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
7048
}
7049

    
7050

    
7051
int CpuProfiler::GetProfileCount() {
7052
  return reinterpret_cast<i::CpuProfiler*>(this)->GetProfilesCount();
7053
}
7054

    
7055

    
7056
void CpuProfiler::SetSamplingInterval(int us) {
7057
  ASSERT(us >= 0);
7058
  return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
7059
      i::TimeDelta::FromMicroseconds(us));
7060
}
7061

    
7062

    
7063
const CpuProfile* CpuProfiler::GetCpuProfile(int index) {
7064
  return reinterpret_cast<const CpuProfile*>(
7065
      reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(index));
7066
}
7067

    
7068

    
7069
void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
7070
  reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
7071
      *Utils::OpenHandle(*title), record_samples);
7072
}
7073

    
7074

    
7075
const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
7076
  return reinterpret_cast<const CpuProfile*>(
7077
      reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
7078
          *Utils::OpenHandle(*title)));
7079
}
7080

    
7081

    
7082
void CpuProfiler::DeleteAllCpuProfiles() {
7083
  reinterpret_cast<i::CpuProfiler*>(this)->DeleteAllProfiles();
7084
}
7085

    
7086

    
7087
void CpuProfiler::SetIdle(bool is_idle) {
7088
  i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
7089
  i::StateTag state = isolate->current_vm_state();
7090
  ASSERT(state == i::EXTERNAL || state == i::IDLE);
7091
  if (isolate->js_entry_sp() != NULL) return;
7092
  if (is_idle) {
7093
    isolate->set_current_vm_state(i::IDLE);
7094
  } else if (state == i::IDLE) {
7095
    isolate->set_current_vm_state(i::EXTERNAL);
7096
  }
7097
}
7098

    
7099

    
7100
static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
7101
  return const_cast<i::HeapGraphEdge*>(
7102
      reinterpret_cast<const i::HeapGraphEdge*>(edge));
7103
}
7104

    
7105

    
7106
HeapGraphEdge::Type HeapGraphEdge::GetType() const {
7107
  return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
7108
}
7109

    
7110

    
7111
Handle<Value> HeapGraphEdge::GetName() const {
7112
  i::Isolate* isolate = i::Isolate::Current();
7113
  i::HeapGraphEdge* edge = ToInternal(this);
7114
  switch (edge->type()) {
7115
    case i::HeapGraphEdge::kContextVariable:
7116
    case i::HeapGraphEdge::kInternal:
7117
    case i::HeapGraphEdge::kProperty:
7118
    case i::HeapGraphEdge::kShortcut:
7119
      return ToApiHandle<String>(
7120
          isolate->factory()->InternalizeUtf8String(edge->name()));
7121
    case i::HeapGraphEdge::kElement:
7122
    case i::HeapGraphEdge::kHidden:
7123
    case i::HeapGraphEdge::kWeak:
7124
      return ToApiHandle<Number>(
7125
          isolate->factory()->NewNumberFromInt(edge->index()));
7126
    default: UNREACHABLE();
7127
  }
7128
  return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
7129
}
7130

    
7131

    
7132
const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
7133
  const i::HeapEntry* from = ToInternal(this)->from();
7134
  return reinterpret_cast<const HeapGraphNode*>(from);
7135
}
7136

    
7137

    
7138
const HeapGraphNode* HeapGraphEdge::GetToNode() const {
7139
  const i::HeapEntry* to = ToInternal(this)->to();
7140
  return reinterpret_cast<const HeapGraphNode*>(to);
7141
}
7142

    
7143

    
7144
static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
7145
  return const_cast<i::HeapEntry*>(
7146
      reinterpret_cast<const i::HeapEntry*>(entry));
7147
}
7148

    
7149

    
7150
HeapGraphNode::Type HeapGraphNode::GetType() const {
7151
  return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
7152
}
7153

    
7154

    
7155
Handle<String> HeapGraphNode::GetName() const {
7156
  i::Isolate* isolate = i::Isolate::Current();
7157
  return ToApiHandle<String>(
7158
      isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
7159
}
7160

    
7161

    
7162
SnapshotObjectId HeapGraphNode::GetId() const {
7163
  return ToInternal(this)->id();
7164
}
7165

    
7166

    
7167
int HeapGraphNode::GetSelfSize() const {
7168
  return ToInternal(this)->self_size();
7169
}
7170

    
7171

    
7172
int HeapGraphNode::GetChildrenCount() const {
7173
  return ToInternal(this)->children().length();
7174
}
7175

    
7176

    
7177
const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
7178
  return reinterpret_cast<const HeapGraphEdge*>(
7179
      ToInternal(this)->children()[index]);
7180
}
7181

    
7182

    
7183
v8::Handle<v8::Value> HeapGraphNode::GetHeapValue() const {
7184
  i::Isolate* isolate = i::Isolate::Current();
7185
  i::Handle<i::HeapObject> object = ToInternal(this)->GetHeapObject();
7186
  return !object.is_null() ?
7187
      ToApiHandle<Value>(object) :
7188
      ToApiHandle<Value>(isolate->factory()->undefined_value());
7189
}
7190

    
7191

    
7192
static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
7193
  return const_cast<i::HeapSnapshot*>(
7194
      reinterpret_cast<const i::HeapSnapshot*>(snapshot));
7195
}
7196

    
7197

    
7198
void HeapSnapshot::Delete() {
7199
  i::Isolate* isolate = i::Isolate::Current();
7200
  if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
7201
    ToInternal(this)->Delete();
7202
  } else {
7203
    // If this is the last snapshot, clean up all accessory data as well.
7204
    isolate->heap_profiler()->DeleteAllSnapshots();
7205
  }
7206
}
7207

    
7208

    
7209
unsigned HeapSnapshot::GetUid() const {
7210
  return ToInternal(this)->uid();
7211
}
7212

    
7213

    
7214
Handle<String> HeapSnapshot::GetTitle() const {
7215
  i::Isolate* isolate = i::Isolate::Current();
7216
  return ToApiHandle<String>(
7217
      isolate->factory()->InternalizeUtf8String(ToInternal(this)->title()));
7218
}
7219

    
7220

    
7221
const HeapGraphNode* HeapSnapshot::GetRoot() const {
7222
  return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
7223
}
7224

    
7225

    
7226
const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
7227
  return reinterpret_cast<const HeapGraphNode*>(
7228
      ToInternal(this)->GetEntryById(id));
7229
}
7230

    
7231

    
7232
int HeapSnapshot::GetNodesCount() const {
7233
  return ToInternal(this)->entries().length();
7234
}
7235

    
7236

    
7237
const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
7238
  return reinterpret_cast<const HeapGraphNode*>(
7239
      &ToInternal(this)->entries().at(index));
7240
}
7241

    
7242

    
7243
SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
7244
  return ToInternal(this)->max_snapshot_js_object_id();
7245
}
7246

    
7247

    
7248
void HeapSnapshot::Serialize(OutputStream* stream,
7249
                             HeapSnapshot::SerializationFormat format) const {
7250
  ApiCheck(format == kJSON,
7251
           "v8::HeapSnapshot::Serialize",
7252
           "Unknown serialization format");
7253
  ApiCheck(stream->GetOutputEncoding() == OutputStream::kAscii,
7254
           "v8::HeapSnapshot::Serialize",
7255
           "Unsupported output encoding");
7256
  ApiCheck(stream->GetChunkSize() > 0,
7257
           "v8::HeapSnapshot::Serialize",
7258
           "Invalid stream chunk size");
7259
  i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
7260
  serializer.Serialize(stream);
7261
}
7262

    
7263

    
7264
int HeapProfiler::GetSnapshotCount() {
7265
  return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
7266
}
7267

    
7268

    
7269
const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
7270
  return reinterpret_cast<const HeapSnapshot*>(
7271
      reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
7272
}
7273

    
7274

    
7275
SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
7276
  i::Handle<i::Object> obj = Utils::OpenHandle(*value);
7277
  return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
7278
}
7279

    
7280

    
7281
const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
7282
    Handle<String> title,
7283
    ActivityControl* control,
7284
    ObjectNameResolver* resolver) {
7285
  return reinterpret_cast<const HeapSnapshot*>(
7286
      reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
7287
          *Utils::OpenHandle(*title), control, resolver));
7288
}
7289

    
7290

    
7291
void HeapProfiler::StartTrackingHeapObjects() {
7292
  reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking();
7293
}
7294

    
7295

    
7296
void HeapProfiler::StopTrackingHeapObjects() {
7297
  reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
7298
}
7299

    
7300

    
7301
SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
7302
  return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
7303
}
7304

    
7305

    
7306
void HeapProfiler::DeleteAllHeapSnapshots() {
7307
  reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
7308
}
7309

    
7310

    
7311
void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
7312
                                               WrapperInfoCallback callback) {
7313
  reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
7314
                                                               callback);
7315
}
7316

    
7317

    
7318
size_t HeapProfiler::GetProfilerMemorySize() {
7319
  return reinterpret_cast<i::HeapProfiler*>(this)->
7320
      GetMemorySizeUsedByProfiler();
7321
}
7322

    
7323

    
7324
void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
7325
                                         RetainedObjectInfo* info) {
7326
  reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info);
7327
}
7328

    
7329

    
7330
void HeapProfiler::StartRecordingHeapAllocations() {
7331
  reinterpret_cast<i::HeapProfiler*>(this)->StartHeapAllocationsRecording();
7332
}
7333

    
7334

    
7335
void HeapProfiler::StopRecordingHeapAllocations() {
7336
  reinterpret_cast<i::HeapProfiler*>(this)->StopHeapAllocationsRecording();
7337
}
7338

    
7339

    
7340
v8::Testing::StressType internal::Testing::stress_type_ =
7341
    v8::Testing::kStressTypeOpt;
7342

    
7343

    
7344
void Testing::SetStressRunType(Testing::StressType type) {
7345
  internal::Testing::set_stress_type(type);
7346
}
7347

    
7348

    
7349
int Testing::GetStressRuns() {
7350
  if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
7351
#ifdef DEBUG
7352
  // In debug mode the code runs much slower so stressing will only make two
7353
  // runs.
7354
  return 2;
7355
#else
7356
  return 5;
7357
#endif
7358
}
7359

    
7360

    
7361
static void SetFlagsFromString(const char* flags) {
7362
  V8::SetFlagsFromString(flags, i::StrLength(flags));
7363
}
7364

    
7365

    
7366
void Testing::PrepareStressRun(int run) {
7367
  static const char* kLazyOptimizations =
7368
      "--prepare-always-opt "
7369
      "--max-inlined-source-size=999999 "
7370
      "--max-inlined-nodes=999999 "
7371
      "--max-inlined-nodes-cumulative=999999 "
7372
      "--noalways-opt";
7373
  static const char* kForcedOptimizations = "--always-opt";
7374

    
7375
  // If deoptimization stressed turn on frequent deoptimization. If no value
7376
  // is spefified through --deopt-every-n-times use a default default value.
7377
  static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
7378
  if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
7379
      internal::FLAG_deopt_every_n_times == 0) {
7380
    SetFlagsFromString(kDeoptEvery13Times);
7381
  }
7382

    
7383
#ifdef DEBUG
7384
  // As stressing in debug mode only make two runs skip the deopt stressing
7385
  // here.
7386
  if (run == GetStressRuns() - 1) {
7387
    SetFlagsFromString(kForcedOptimizations);
7388
  } else {
7389
    SetFlagsFromString(kLazyOptimizations);
7390
  }
7391
#else
7392
  if (run == GetStressRuns() - 1) {
7393
    SetFlagsFromString(kForcedOptimizations);
7394
  } else if (run != GetStressRuns() - 2) {
7395
    SetFlagsFromString(kLazyOptimizations);
7396
  }
7397
#endif
7398
}
7399

    
7400

    
7401
// TODO(svenpanne) Deprecate this.
7402
void Testing::DeoptimizeAll() {
7403
  i::Isolate* isolate = i::Isolate::Current();
7404
  i::HandleScope scope(isolate);
7405
  internal::Deoptimizer::DeoptimizeAll(isolate);
7406
}
7407

    
7408

    
7409
namespace internal {
7410

    
7411

    
7412
void HandleScopeImplementer::FreeThreadResources() {
7413
  Free();
7414
}
7415

    
7416

    
7417
char* HandleScopeImplementer::ArchiveThread(char* storage) {
7418
  v8::ImplementationUtilities::HandleScopeData* current =
7419
      isolate_->handle_scope_data();
7420
  handle_scope_data_ = *current;
7421
  OS::MemCopy(storage, this, sizeof(*this));
7422

    
7423
  ResetAfterArchive();
7424
  current->Initialize();
7425

    
7426
  return storage + ArchiveSpacePerThread();
7427
}
7428

    
7429

    
7430
int HandleScopeImplementer::ArchiveSpacePerThread() {
7431
  return sizeof(HandleScopeImplementer);
7432
}
7433

    
7434

    
7435
char* HandleScopeImplementer::RestoreThread(char* storage) {
7436
  OS::MemCopy(this, storage, sizeof(*this));
7437
  *isolate_->handle_scope_data() = handle_scope_data_;
7438
  return storage + ArchiveSpacePerThread();
7439
}
7440

    
7441

    
7442
void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
7443
#ifdef DEBUG
7444
  bool found_block_before_deferred = false;
7445
#endif
7446
  // Iterate over all handles in the blocks except for the last.
7447
  for (int i = blocks()->length() - 2; i >= 0; --i) {
7448
    Object** block = blocks()->at(i);
7449
    if (last_handle_before_deferred_block_ != NULL &&
7450
        (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) &&
7451
        (last_handle_before_deferred_block_ >= block)) {
7452
      v->VisitPointers(block, last_handle_before_deferred_block_);
7453
      ASSERT(!found_block_before_deferred);
7454
#ifdef DEBUG
7455
      found_block_before_deferred = true;
7456
#endif
7457
    } else {
7458
      v->VisitPointers(block, &block[kHandleBlockSize]);
7459
    }
7460
  }
7461

    
7462
  ASSERT(last_handle_before_deferred_block_ == NULL ||
7463
         found_block_before_deferred);
7464

    
7465
  // Iterate over live handles in the last block (if any).
7466
  if (!blocks()->is_empty()) {
7467
    v->VisitPointers(blocks()->last(), handle_scope_data_.next);
7468
  }
7469

    
7470
  List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
7471
  for (unsigned i = 0; i < ARRAY_SIZE(context_lists); i++) {
7472
    if (context_lists[i]->is_empty()) continue;
7473
    Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
7474
    v->VisitPointers(start, start + context_lists[i]->length());
7475
  }
7476
}
7477

    
7478

    
7479
void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
7480
  v8::ImplementationUtilities::HandleScopeData* current =
7481
      isolate_->handle_scope_data();
7482
  handle_scope_data_ = *current;
7483
  IterateThis(v);
7484
}
7485

    
7486

    
7487
char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
7488
  HandleScopeImplementer* scope_implementer =
7489
      reinterpret_cast<HandleScopeImplementer*>(storage);
7490
  scope_implementer->IterateThis(v);
7491
  return storage + ArchiveSpacePerThread();
7492
}
7493

    
7494

    
7495
DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) {
7496
  DeferredHandles* deferred =
7497
      new DeferredHandles(isolate()->handle_scope_data()->next, isolate());
7498

    
7499
  while (!blocks_.is_empty()) {
7500
    Object** block_start = blocks_.last();
7501
    Object** block_limit = &block_start[kHandleBlockSize];
7502
    // We should not need to check for SealHandleScope here. Assert this.
7503
    ASSERT(prev_limit == block_limit ||
7504
           !(block_start <= prev_limit && prev_limit <= block_limit));
7505
    if (prev_limit == block_limit) break;
7506
    deferred->blocks_.Add(blocks_.last());
7507
    blocks_.RemoveLast();
7508
  }
7509

    
7510
  // deferred->blocks_ now contains the blocks installed on the
7511
  // HandleScope stack since BeginDeferredScope was called, but in
7512
  // reverse order.
7513

    
7514
  ASSERT(prev_limit == NULL || !blocks_.is_empty());
7515

    
7516
  ASSERT(!blocks_.is_empty() && prev_limit != NULL);
7517
  ASSERT(last_handle_before_deferred_block_ != NULL);
7518
  last_handle_before_deferred_block_ = NULL;
7519
  return deferred;
7520
}
7521

    
7522

    
7523
void HandleScopeImplementer::BeginDeferredScope() {
7524
  ASSERT(last_handle_before_deferred_block_ == NULL);
7525
  last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
7526
}
7527

    
7528

    
7529
DeferredHandles::~DeferredHandles() {
7530
  isolate_->UnlinkDeferredHandles(this);
7531

    
7532
  for (int i = 0; i < blocks_.length(); i++) {
7533
#ifdef ENABLE_HANDLE_ZAPPING
7534
    HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
7535
#endif
7536
    isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
7537
  }
7538
}
7539

    
7540

    
7541
void DeferredHandles::Iterate(ObjectVisitor* v) {
7542
  ASSERT(!blocks_.is_empty());
7543

    
7544
  ASSERT((first_block_limit_ >= blocks_.first()) &&
7545
         (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize]));
7546

    
7547
  v->VisitPointers(blocks_.first(), first_block_limit_);
7548

    
7549
  for (int i = 1; i < blocks_.length(); i++) {
7550
    v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
7551
  }
7552
}
7553

    
7554

    
7555
void InvokeAccessorGetterCallback(
7556
    v8::Local<v8::String> property,
7557
    const v8::PropertyCallbackInfo<v8::Value>& info,
7558
    v8::AccessorGetterCallback getter) {
7559
  // Leaving JavaScript.
7560
  Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7561
  Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
7562
      getter));
7563
  VMState<EXTERNAL> state(isolate);
7564
  ExternalCallbackScope call_scope(isolate, getter_address);
7565
  getter(property, info);
7566
}
7567

    
7568

    
7569
void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
7570
                            v8::FunctionCallback callback) {
7571
  Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7572
  Address callback_address =
7573
      reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
7574
  VMState<EXTERNAL> state(isolate);
7575
  ExternalCallbackScope call_scope(isolate, callback_address);
7576
  callback(info);
7577
}
7578

    
7579

    
7580
} }  // namespace v8::internal