Upstream version 9.38.204.0
[platform/framework/web/crosswalk.git] / src / v8 / src / api.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/api.h"
6
7 #include <string.h>  // For memcpy, strlen.
8 #ifdef V8_USE_ADDRESS_SANITIZER
9 #include <sanitizer/asan_interface.h>
10 #endif  // V8_USE_ADDRESS_SANITIZER
11 #include <cmath>  // For isnan.
12 #include "include/v8-debug.h"
13 #include "include/v8-profiler.h"
14 #include "include/v8-testing.h"
15 #include "src/assert-scope.h"
16 #include "src/base/platform/platform.h"
17 #include "src/base/platform/time.h"
18 #include "src/base/utils/random-number-generator.h"
19 #include "src/bootstrapper.h"
20 #include "src/code-stubs.h"
21 #include "src/compiler.h"
22 #include "src/conversions-inl.h"
23 #include "src/counters.h"
24 #include "src/cpu-profiler.h"
25 #include "src/debug.h"
26 #include "src/deoptimizer.h"
27 #include "src/execution.h"
28 #include "src/global-handles.h"
29 #include "src/heap-profiler.h"
30 #include "src/heap-snapshot-generator-inl.h"
31 #include "src/icu_util.h"
32 #include "src/json-parser.h"
33 #include "src/messages.h"
34 #include "src/natives.h"
35 #include "src/parser.h"
36 #include "src/profile-generator-inl.h"
37 #include "src/property.h"
38 #include "src/property-details.h"
39 #include "src/prototype.h"
40 #include "src/runtime.h"
41 #include "src/runtime-profiler.h"
42 #include "src/scanner-character-streams.h"
43 #include "src/simulator.h"
44 #include "src/snapshot.h"
45 #include "src/unicode-inl.h"
46 #include "src/v8threads.h"
47 #include "src/version.h"
48 #include "src/vm-state-inl.h"
49
50
51 #define LOG_API(isolate, expr) LOG(isolate, ApiEntryCall(expr))
52
53 #define ENTER_V8(isolate)                                          \
54   DCHECK((isolate)->IsInitialized());                              \
55   i::VMState<i::OTHER> __state__((isolate))
56
57 namespace v8 {
58
59 #define ON_BAILOUT(isolate, location, code)                        \
60   if (IsExecutionTerminatingCheck(isolate)) {                      \
61     code;                                                          \
62     UNREACHABLE();                                                 \
63   }
64
65
66 #define EXCEPTION_PREAMBLE(isolate)                                         \
67   (isolate)->handle_scope_implementer()->IncrementCallDepth();              \
68   DCHECK(!(isolate)->external_caught_exception());                          \
69   bool has_pending_exception = false
70
71
72 #define EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, do_callback)           \
73   do {                                                                         \
74     i::HandleScopeImplementer* handle_scope_implementer =                      \
75         (isolate)->handle_scope_implementer();                                 \
76     handle_scope_implementer->DecrementCallDepth();                            \
77     if (has_pending_exception) {                                               \
78       bool call_depth_is_zero = handle_scope_implementer->CallDepthIsZero();   \
79       (isolate)->OptionalRescheduleException(call_depth_is_zero);              \
80       do_callback                                                              \
81       return value;                                                            \
82     }                                                                          \
83     do_callback                                                                \
84   } while (false)
85
86
87 #define EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, value)                    \
88   EXCEPTION_BAILOUT_CHECK_GENERIC(                                             \
89       isolate, value, isolate->FireCallCompletedCallback();)
90
91
92 #define EXCEPTION_BAILOUT_CHECK(isolate, value)                                \
93   EXCEPTION_BAILOUT_CHECK_GENERIC(isolate, value, ;)
94
95
96 // --- E x c e p t i o n   B e h a v i o r ---
97
98
99 void i::FatalProcessOutOfMemory(const char* location) {
100   i::V8::FatalProcessOutOfMemory(location, false);
101 }
102
103
104 // When V8 cannot allocated memory FatalProcessOutOfMemory is called.
105 // The default fatal error handler is called and execution is stopped.
106 void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
107   i::HeapStats heap_stats;
108   int start_marker;
109   heap_stats.start_marker = &start_marker;
110   int new_space_size;
111   heap_stats.new_space_size = &new_space_size;
112   int new_space_capacity;
113   heap_stats.new_space_capacity = &new_space_capacity;
114   intptr_t old_pointer_space_size;
115   heap_stats.old_pointer_space_size = &old_pointer_space_size;
116   intptr_t old_pointer_space_capacity;
117   heap_stats.old_pointer_space_capacity = &old_pointer_space_capacity;
118   intptr_t old_data_space_size;
119   heap_stats.old_data_space_size = &old_data_space_size;
120   intptr_t old_data_space_capacity;
121   heap_stats.old_data_space_capacity = &old_data_space_capacity;
122   intptr_t code_space_size;
123   heap_stats.code_space_size = &code_space_size;
124   intptr_t code_space_capacity;
125   heap_stats.code_space_capacity = &code_space_capacity;
126   intptr_t map_space_size;
127   heap_stats.map_space_size = &map_space_size;
128   intptr_t map_space_capacity;
129   heap_stats.map_space_capacity = &map_space_capacity;
130   intptr_t cell_space_size;
131   heap_stats.cell_space_size = &cell_space_size;
132   intptr_t cell_space_capacity;
133   heap_stats.cell_space_capacity = &cell_space_capacity;
134   intptr_t property_cell_space_size;
135   heap_stats.property_cell_space_size = &property_cell_space_size;
136   intptr_t property_cell_space_capacity;
137   heap_stats.property_cell_space_capacity = &property_cell_space_capacity;
138   intptr_t lo_space_size;
139   heap_stats.lo_space_size = &lo_space_size;
140   int global_handle_count;
141   heap_stats.global_handle_count = &global_handle_count;
142   int weak_global_handle_count;
143   heap_stats.weak_global_handle_count = &weak_global_handle_count;
144   int pending_global_handle_count;
145   heap_stats.pending_global_handle_count = &pending_global_handle_count;
146   int near_death_global_handle_count;
147   heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
148   int free_global_handle_count;
149   heap_stats.free_global_handle_count = &free_global_handle_count;
150   intptr_t memory_allocator_size;
151   heap_stats.memory_allocator_size = &memory_allocator_size;
152   intptr_t memory_allocator_capacity;
153   heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
154   int objects_per_type[LAST_TYPE + 1] = {0};
155   heap_stats.objects_per_type = objects_per_type;
156   int size_per_type[LAST_TYPE + 1] = {0};
157   heap_stats.size_per_type = size_per_type;
158   int os_error;
159   heap_stats.os_error = &os_error;
160   int end_marker;
161   heap_stats.end_marker = &end_marker;
162   i::Isolate* isolate = i::Isolate::Current();
163   if (isolate->heap()->HasBeenSetUp()) {
164     // BUG(1718): Don't use the take_snapshot since we don't support
165     // HeapIterator here without doing a special GC.
166     isolate->heap()->RecordStats(&heap_stats, false);
167   }
168   Utils::ApiCheck(false, location, "Allocation failed - process out of memory");
169   // If the fatal error handler returns, we stop execution.
170   FATAL("API fatal error handler returned after process out of memory");
171 }
172
173
174 void Utils::ReportApiFailure(const char* location, const char* message) {
175   i::Isolate* isolate = i::Isolate::Current();
176   FatalErrorCallback callback = isolate->exception_behavior();
177   if (callback == NULL) {
178     base::OS::PrintError("\n#\n# Fatal error in %s\n# %s\n#\n\n", location,
179                          message);
180     base::OS::Abort();
181   } else {
182     callback(location, message);
183   }
184   isolate->SignalFatalError();
185 }
186
187
188 bool V8::IsDead() {
189   i::Isolate* isolate = i::Isolate::Current();
190   return isolate->IsDead();
191 }
192
193
194 static inline bool IsExecutionTerminatingCheck(i::Isolate* isolate) {
195   if (!isolate->IsInitialized()) return false;
196   if (isolate->has_scheduled_exception()) {
197     return isolate->scheduled_exception() ==
198         isolate->heap()->termination_exception();
199   }
200   return false;
201 }
202
203
204 // --- S t a t i c s ---
205
206
207 static bool InitializeHelper(i::Isolate* isolate) {
208   // If the isolate has a function entry hook, it needs to re-build all its
209   // code stubs with entry hooks embedded, so let's deserialize a snapshot.
210   if (isolate == NULL || isolate->function_entry_hook() == NULL) {
211     if (i::Snapshot::Initialize())
212       return true;
213   }
214   return i::V8::Initialize(NULL);
215 }
216
217
218 static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,
219                                                const char* location) {
220   return (isolate != NULL && isolate->IsInitialized()) ||
221       Utils::ApiCheck(InitializeHelper(isolate),
222                       location,
223                       "Error initializing V8");
224 }
225
226
227 StartupDataDecompressor::StartupDataDecompressor()
228     : raw_data(i::NewArray<char*>(V8::GetCompressedStartupDataCount())) {
229   for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
230     raw_data[i] = NULL;
231   }
232 }
233
234
235 StartupDataDecompressor::~StartupDataDecompressor() {
236   for (int i = 0; i < V8::GetCompressedStartupDataCount(); ++i) {
237     i::DeleteArray(raw_data[i]);
238   }
239   i::DeleteArray(raw_data);
240 }
241
242
243 int StartupDataDecompressor::Decompress() {
244   int compressed_data_count = V8::GetCompressedStartupDataCount();
245   StartupData* compressed_data =
246       i::NewArray<StartupData>(compressed_data_count);
247   V8::GetCompressedStartupData(compressed_data);
248   for (int i = 0; i < compressed_data_count; ++i) {
249     char* decompressed = raw_data[i] =
250         i::NewArray<char>(compressed_data[i].raw_size);
251     if (compressed_data[i].compressed_size != 0) {
252       int result = DecompressData(decompressed,
253                                   &compressed_data[i].raw_size,
254                                   compressed_data[i].data,
255                                   compressed_data[i].compressed_size);
256       if (result != 0) return result;
257     } else {
258       DCHECK_EQ(0, compressed_data[i].raw_size);
259     }
260     compressed_data[i].data = decompressed;
261   }
262   V8::SetDecompressedStartupData(compressed_data);
263   i::DeleteArray(compressed_data);
264   return 0;
265 }
266
267
268 StartupData::CompressionAlgorithm V8::GetCompressedStartupDataAlgorithm() {
269 #ifdef COMPRESS_STARTUP_DATA_BZ2
270   return StartupData::kBZip2;
271 #else
272   return StartupData::kUncompressed;
273 #endif
274 }
275
276
277 enum CompressedStartupDataItems {
278   kSnapshot = 0,
279   kSnapshotContext,
280   kLibraries,
281   kExperimentalLibraries,
282   kCompressedStartupDataCount
283 };
284
285
286 int V8::GetCompressedStartupDataCount() {
287 #ifdef COMPRESS_STARTUP_DATA_BZ2
288   return kCompressedStartupDataCount;
289 #else
290   return 0;
291 #endif
292 }
293
294
295 void V8::GetCompressedStartupData(StartupData* compressed_data) {
296 #ifdef COMPRESS_STARTUP_DATA_BZ2
297   compressed_data[kSnapshot].data =
298       reinterpret_cast<const char*>(i::Snapshot::data());
299   compressed_data[kSnapshot].compressed_size = i::Snapshot::size();
300   compressed_data[kSnapshot].raw_size = i::Snapshot::raw_size();
301
302   compressed_data[kSnapshotContext].data =
303       reinterpret_cast<const char*>(i::Snapshot::context_data());
304   compressed_data[kSnapshotContext].compressed_size =
305       i::Snapshot::context_size();
306   compressed_data[kSnapshotContext].raw_size = i::Snapshot::context_raw_size();
307
308   i::Vector<const i::byte> libraries_source = i::Natives::GetScriptsSource();
309   compressed_data[kLibraries].data =
310       reinterpret_cast<const char*>(libraries_source.start());
311   compressed_data[kLibraries].compressed_size = libraries_source.length();
312   compressed_data[kLibraries].raw_size = i::Natives::GetRawScriptsSize();
313
314   i::Vector<const i::byte> exp_libraries_source =
315       i::ExperimentalNatives::GetScriptsSource();
316   compressed_data[kExperimentalLibraries].data =
317       reinterpret_cast<const char*>(exp_libraries_source.start());
318   compressed_data[kExperimentalLibraries].compressed_size =
319       exp_libraries_source.length();
320   compressed_data[kExperimentalLibraries].raw_size =
321       i::ExperimentalNatives::GetRawScriptsSize();
322 #endif
323 }
324
325
326 void V8::SetDecompressedStartupData(StartupData* decompressed_data) {
327 #ifdef COMPRESS_STARTUP_DATA_BZ2
328   DCHECK_EQ(i::Snapshot::raw_size(), decompressed_data[kSnapshot].raw_size);
329   i::Snapshot::set_raw_data(
330       reinterpret_cast<const i::byte*>(decompressed_data[kSnapshot].data));
331
332   DCHECK_EQ(i::Snapshot::context_raw_size(),
333             decompressed_data[kSnapshotContext].raw_size);
334   i::Snapshot::set_context_raw_data(
335       reinterpret_cast<const i::byte*>(
336           decompressed_data[kSnapshotContext].data));
337
338   DCHECK_EQ(i::Natives::GetRawScriptsSize(),
339             decompressed_data[kLibraries].raw_size);
340   i::Vector<const char> libraries_source(
341       decompressed_data[kLibraries].data,
342       decompressed_data[kLibraries].raw_size);
343   i::Natives::SetRawScriptsSource(libraries_source);
344
345   DCHECK_EQ(i::ExperimentalNatives::GetRawScriptsSize(),
346             decompressed_data[kExperimentalLibraries].raw_size);
347   i::Vector<const char> exp_libraries_source(
348       decompressed_data[kExperimentalLibraries].data,
349       decompressed_data[kExperimentalLibraries].raw_size);
350   i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source);
351 #endif
352 }
353
354
355 void V8::SetNativesDataBlob(StartupData* natives_blob) {
356 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
357   i::SetNativesFromFile(natives_blob);
358 #else
359   CHECK(false);
360 #endif
361 }
362
363
364 void V8::SetSnapshotDataBlob(StartupData* snapshot_blob) {
365 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
366   i::SetSnapshotFromFile(snapshot_blob);
367 #else
368   CHECK(false);
369 #endif
370 }
371
372
373 void V8::SetFatalErrorHandler(FatalErrorCallback that) {
374   i::Isolate* isolate = i::Isolate::Current();
375   isolate->set_exception_behavior(that);
376 }
377
378
379 void V8::SetAllowCodeGenerationFromStringsCallback(
380     AllowCodeGenerationFromStringsCallback callback) {
381   i::Isolate* isolate = i::Isolate::Current();
382   isolate->set_allow_code_gen_callback(callback);
383 }
384
385
386 void V8::SetFlagsFromString(const char* str, int length) {
387   i::FlagList::SetFlagsFromString(str, length);
388 }
389
390
391 void V8::SetFlagsFromCommandLine(int* argc, char** argv, bool remove_flags) {
392   i::FlagList::SetFlagsFromCommandLine(argc, argv, remove_flags);
393 }
394
395
396 RegisteredExtension* RegisteredExtension::first_extension_ = NULL;
397
398
399 RegisteredExtension::RegisteredExtension(Extension* extension)
400     : extension_(extension) { }
401
402
403 void RegisteredExtension::Register(RegisteredExtension* that) {
404   that->next_ = first_extension_;
405   first_extension_ = that;
406 }
407
408
409 void RegisteredExtension::UnregisterAll() {
410   RegisteredExtension* re = first_extension_;
411   while (re != NULL) {
412     RegisteredExtension* next = re->next();
413     delete re;
414     re = next;
415   }
416 }
417
418
419 void RegisterExtension(Extension* that) {
420   RegisteredExtension* extension = new RegisteredExtension(that);
421   RegisteredExtension::Register(extension);
422 }
423
424
425 Extension::Extension(const char* name,
426                      const char* source,
427                      int dep_count,
428                      const char** deps,
429                      int source_length)
430     : name_(name),
431       source_length_(source_length >= 0 ?
432                      source_length :
433                      (source ? static_cast<int>(strlen(source)) : 0)),
434       source_(source, source_length_),
435       dep_count_(dep_count),
436       deps_(deps),
437       auto_enable_(false) {
438   CHECK(source != NULL || source_length_ == 0);
439 }
440
441
442 ResourceConstraints::ResourceConstraints()
443     : max_semi_space_size_(0),
444       max_old_space_size_(0),
445       max_executable_size_(0),
446       stack_limit_(NULL),
447       max_available_threads_(0),
448       code_range_size_(0) { }
449
450 void ResourceConstraints::ConfigureDefaults(uint64_t physical_memory,
451                                             uint64_t virtual_memory_limit,
452                                             uint32_t number_of_processors) {
453 #if V8_OS_ANDROID
454   // Android has higher physical memory requirements before raising the maximum
455   // heap size limits since it has no swap space.
456   const uint64_t low_limit = 512ul * i::MB;
457   const uint64_t medium_limit = 1ul * i::GB;
458   const uint64_t high_limit = 2ul * i::GB;
459 #else
460   const uint64_t low_limit = 512ul * i::MB;
461   const uint64_t medium_limit = 768ul * i::MB;
462   const uint64_t high_limit = 1ul  * i::GB;
463 #endif
464
465   if (physical_memory <= low_limit) {
466     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeLowMemoryDevice);
467     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeLowMemoryDevice);
468     set_max_executable_size(i::Heap::kMaxExecutableSizeLowMemoryDevice);
469   } else if (physical_memory <= medium_limit) {
470     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeMediumMemoryDevice);
471     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeMediumMemoryDevice);
472     set_max_executable_size(i::Heap::kMaxExecutableSizeMediumMemoryDevice);
473   } else if (physical_memory <= high_limit) {
474     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHighMemoryDevice);
475     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHighMemoryDevice);
476     set_max_executable_size(i::Heap::kMaxExecutableSizeHighMemoryDevice);
477   } else {
478     set_max_semi_space_size(i::Heap::kMaxSemiSpaceSizeHugeMemoryDevice);
479     set_max_old_space_size(i::Heap::kMaxOldSpaceSizeHugeMemoryDevice);
480     set_max_executable_size(i::Heap::kMaxExecutableSizeHugeMemoryDevice);
481   }
482
483   set_max_available_threads(i::Max(i::Min(number_of_processors, 4u), 1u));
484
485   if (virtual_memory_limit > 0 && i::kRequiresCodeRange) {
486     // Reserve no more than 1/8 of the memory for the code range, but at most
487     // kMaximalCodeRangeSize.
488     set_code_range_size(
489         i::Min(i::kMaximalCodeRangeSize / i::MB,
490                static_cast<size_t>((virtual_memory_limit >> 3) / i::MB)));
491   }
492 }
493
494
495 bool SetResourceConstraints(Isolate* v8_isolate,
496                             ResourceConstraints* constraints) {
497   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
498   int semi_space_size = constraints->max_semi_space_size();
499   int old_space_size = constraints->max_old_space_size();
500   int max_executable_size = constraints->max_executable_size();
501   size_t code_range_size = constraints->code_range_size();
502   if (semi_space_size != 0 || old_space_size != 0 ||
503       max_executable_size != 0 || code_range_size != 0) {
504     // After initialization it's too late to change Heap constraints.
505     DCHECK(!isolate->IsInitialized());
506     bool result = isolate->heap()->ConfigureHeap(semi_space_size,
507                                                  old_space_size,
508                                                  max_executable_size,
509                                                  code_range_size);
510     if (!result) return false;
511   }
512   if (constraints->stack_limit() != NULL) {
513     uintptr_t limit = reinterpret_cast<uintptr_t>(constraints->stack_limit());
514     isolate->stack_guard()->SetStackLimit(limit);
515   }
516
517   isolate->set_max_available_threads(constraints->max_available_threads());
518   return true;
519 }
520
521
522 i::Object** V8::GlobalizeReference(i::Isolate* isolate, i::Object** obj) {
523   LOG_API(isolate, "Persistent::New");
524   i::Handle<i::Object> result = isolate->global_handles()->Create(*obj);
525 #ifdef DEBUG
526   (*obj)->ObjectVerify();
527 #endif  // DEBUG
528   return result.location();
529 }
530
531
532 i::Object** V8::CopyPersistent(i::Object** obj) {
533   i::Handle<i::Object> result = i::GlobalHandles::CopyGlobal(obj);
534 #ifdef DEBUG
535   (*obj)->ObjectVerify();
536 #endif  // DEBUG
537   return result.location();
538 }
539
540
541 void V8::MakeWeak(i::Object** object,
542                   void* parameters,
543                   WeakCallback weak_callback) {
544   i::GlobalHandles::MakeWeak(object, parameters, weak_callback);
545 }
546
547
548 void* V8::ClearWeak(i::Object** obj) {
549   return i::GlobalHandles::ClearWeakness(obj);
550 }
551
552
553 void V8::DisposeGlobal(i::Object** obj) {
554   i::GlobalHandles::Destroy(obj);
555 }
556
557
558 void V8::Eternalize(Isolate* v8_isolate, Value* value, int* index) {
559   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
560   i::Object* object = *Utils::OpenHandle(value);
561   isolate->eternal_handles()->Create(isolate, object, index);
562 }
563
564
565 Local<Value> V8::GetEternal(Isolate* v8_isolate, int index) {
566   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
567   return Utils::ToLocal(isolate->eternal_handles()->Get(index));
568 }
569
570
571 // --- H a n d l e s ---
572
573
574 HandleScope::HandleScope(Isolate* isolate) {
575   Initialize(isolate);
576 }
577
578
579 void HandleScope::Initialize(Isolate* isolate) {
580   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
581   // We do not want to check the correct usage of the Locker class all over the
582   // place, so we do it only here: Without a HandleScope, an embedder can do
583   // almost nothing, so it is enough to check in this central place.
584   Utils::ApiCheck(!v8::Locker::IsActive() ||
585                   internal_isolate->thread_manager()->IsLockedByCurrentThread(),
586                   "HandleScope::HandleScope",
587                   "Entering the V8 API without proper locking in place");
588   i::HandleScopeData* current = internal_isolate->handle_scope_data();
589   isolate_ = internal_isolate;
590   prev_next_ = current->next;
591   prev_limit_ = current->limit;
592   current->level++;
593 }
594
595
596 HandleScope::~HandleScope() {
597   i::HandleScope::CloseScope(isolate_, prev_next_, prev_limit_);
598 }
599
600
601 int HandleScope::NumberOfHandles(Isolate* isolate) {
602   return i::HandleScope::NumberOfHandles(
603       reinterpret_cast<i::Isolate*>(isolate));
604 }
605
606
607 i::Object** HandleScope::CreateHandle(i::Isolate* isolate, i::Object* value) {
608   return i::HandleScope::CreateHandle(isolate, value);
609 }
610
611
612 i::Object** HandleScope::CreateHandle(i::HeapObject* heap_object,
613                                       i::Object* value) {
614   DCHECK(heap_object->IsHeapObject());
615   return i::HandleScope::CreateHandle(heap_object->GetIsolate(), value);
616 }
617
618
619 EscapableHandleScope::EscapableHandleScope(Isolate* v8_isolate) {
620   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
621   escape_slot_ = CreateHandle(isolate, isolate->heap()->the_hole_value());
622   Initialize(v8_isolate);
623 }
624
625
626 i::Object** EscapableHandleScope::Escape(i::Object** escape_value) {
627   i::Heap* heap = reinterpret_cast<i::Isolate*>(GetIsolate())->heap();
628   Utils::ApiCheck(*escape_slot_ == heap->the_hole_value(),
629                   "EscapeableHandleScope::Escape",
630                   "Escape value set twice");
631   if (escape_value == NULL) {
632     *escape_slot_ = heap->undefined_value();
633     return NULL;
634   }
635   *escape_slot_ = *escape_value;
636   return escape_slot_;
637 }
638
639
640 void Context::Enter() {
641   i::Handle<i::Context> env = Utils::OpenHandle(this);
642   i::Isolate* isolate = env->GetIsolate();
643   ENTER_V8(isolate);
644   i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
645   impl->EnterContext(env);
646   impl->SaveContext(isolate->context());
647   isolate->set_context(*env);
648 }
649
650
651 void Context::Exit() {
652   i::Handle<i::Context> env = Utils::OpenHandle(this);
653   i::Isolate* isolate = env->GetIsolate();
654   ENTER_V8(isolate);
655   i::HandleScopeImplementer* impl = isolate->handle_scope_implementer();
656   if (!Utils::ApiCheck(impl->LastEnteredContextWas(env),
657                        "v8::Context::Exit()",
658                        "Cannot exit non-entered context")) {
659     return;
660   }
661   impl->LeaveContext();
662   isolate->set_context(impl->RestoreContext());
663 }
664
665
666 static void* DecodeSmiToAligned(i::Object* value, const char* location) {
667   Utils::ApiCheck(value->IsSmi(), location, "Not a Smi");
668   return reinterpret_cast<void*>(value);
669 }
670
671
672 static i::Smi* EncodeAlignedAsSmi(void* value, const char* location) {
673   i::Smi* smi = reinterpret_cast<i::Smi*>(value);
674   Utils::ApiCheck(smi->IsSmi(), location, "Pointer is not aligned");
675   return smi;
676 }
677
678
679 static i::Handle<i::FixedArray> EmbedderDataFor(Context* context,
680                                                 int index,
681                                                 bool can_grow,
682                                                 const char* location) {
683   i::Handle<i::Context> env = Utils::OpenHandle(context);
684   bool ok =
685       Utils::ApiCheck(env->IsNativeContext(),
686                       location,
687                       "Not a native context") &&
688       Utils::ApiCheck(index >= 0, location, "Negative index");
689   if (!ok) return i::Handle<i::FixedArray>();
690   i::Handle<i::FixedArray> data(env->embedder_data());
691   if (index < data->length()) return data;
692   if (!Utils::ApiCheck(can_grow, location, "Index too large")) {
693     return i::Handle<i::FixedArray>();
694   }
695   int new_size = i::Max(index, data->length() << 1) + 1;
696   data = i::FixedArray::CopySize(data, new_size);
697   env->set_embedder_data(*data);
698   return data;
699 }
700
701
702 v8::Local<v8::Value> Context::SlowGetEmbedderData(int index) {
703   const char* location = "v8::Context::GetEmbedderData()";
704   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
705   if (data.is_null()) return Local<Value>();
706   i::Handle<i::Object> result(data->get(index), data->GetIsolate());
707   return Utils::ToLocal(result);
708 }
709
710
711 void Context::SetEmbedderData(int index, v8::Handle<Value> value) {
712   const char* location = "v8::Context::SetEmbedderData()";
713   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
714   if (data.is_null()) return;
715   i::Handle<i::Object> val = Utils::OpenHandle(*value);
716   data->set(index, *val);
717   DCHECK_EQ(*Utils::OpenHandle(*value),
718             *Utils::OpenHandle(*GetEmbedderData(index)));
719 }
720
721
722 void* Context::SlowGetAlignedPointerFromEmbedderData(int index) {
723   const char* location = "v8::Context::GetAlignedPointerFromEmbedderData()";
724   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, false, location);
725   if (data.is_null()) return NULL;
726   return DecodeSmiToAligned(data->get(index), location);
727 }
728
729
730 void Context::SetAlignedPointerInEmbedderData(int index, void* value) {
731   const char* location = "v8::Context::SetAlignedPointerInEmbedderData()";
732   i::Handle<i::FixedArray> data = EmbedderDataFor(this, index, true, location);
733   data->set(index, EncodeAlignedAsSmi(value, location));
734   DCHECK_EQ(value, GetAlignedPointerFromEmbedderData(index));
735 }
736
737
738 // --- N e a n d e r ---
739
740
741 // A constructor cannot easily return an error value, therefore it is necessary
742 // to check for a dead VM with ON_BAILOUT before constructing any Neander
743 // objects.  To remind you about this there is no HandleScope in the
744 // NeanderObject constructor.  When you add one to the site calling the
745 // constructor you should check that you ensured the VM was not dead first.
746 NeanderObject::NeanderObject(v8::internal::Isolate* isolate, int size) {
747   EnsureInitializedForIsolate(isolate, "v8::Nowhere");
748   ENTER_V8(isolate);
749   value_ = isolate->factory()->NewNeanderObject();
750   i::Handle<i::FixedArray> elements = isolate->factory()->NewFixedArray(size);
751   value_->set_elements(*elements);
752 }
753
754
755 int NeanderObject::size() {
756   return i::FixedArray::cast(value_->elements())->length();
757 }
758
759
760 NeanderArray::NeanderArray(v8::internal::Isolate* isolate) : obj_(isolate, 2) {
761   obj_.set(0, i::Smi::FromInt(0));
762 }
763
764
765 int NeanderArray::length() {
766   return i::Smi::cast(obj_.get(0))->value();
767 }
768
769
770 i::Object* NeanderArray::get(int offset) {
771   DCHECK(0 <= offset);
772   DCHECK(offset < length());
773   return obj_.get(offset + 1);
774 }
775
776
777 // This method cannot easily return an error value, therefore it is necessary
778 // to check for a dead VM with ON_BAILOUT before calling it.  To remind you
779 // about this there is no HandleScope in this method.  When you add one to the
780 // site calling this method you should check that you ensured the VM was not
781 // dead first.
782 void NeanderArray::add(i::Handle<i::Object> value) {
783   int length = this->length();
784   int size = obj_.size();
785   if (length == size - 1) {
786     i::Factory* factory = i::Isolate::Current()->factory();
787     i::Handle<i::FixedArray> new_elms = factory->NewFixedArray(2 * size);
788     for (int i = 0; i < length; i++)
789       new_elms->set(i + 1, get(i));
790     obj_.value()->set_elements(*new_elms);
791   }
792   obj_.set(length + 1, *value);
793   obj_.set(0, i::Smi::FromInt(length + 1));
794 }
795
796
797 void NeanderArray::set(int index, i::Object* value) {
798   if (index < 0 || index >= this->length()) return;
799   obj_.set(index + 1, value);
800 }
801
802
803 // --- T e m p l a t e ---
804
805
806 static void InitializeTemplate(i::Handle<i::TemplateInfo> that, int type) {
807   that->set_tag(i::Smi::FromInt(type));
808 }
809
810
811 static void TemplateSet(i::Isolate* isolate,
812                         v8::Template* templ,
813                         int length,
814                         v8::Handle<v8::Data>* data) {
815   i::Handle<i::Object> list(Utils::OpenHandle(templ)->property_list(), isolate);
816   if (list->IsUndefined()) {
817     list = NeanderArray(isolate).value();
818     Utils::OpenHandle(templ)->set_property_list(*list);
819   }
820   NeanderArray array(list);
821   array.add(isolate->factory()->NewNumberFromInt(length));
822   for (int i = 0; i < length; i++) {
823     i::Handle<i::Object> value = data[i].IsEmpty() ?
824         i::Handle<i::Object>(isolate->factory()->undefined_value()) :
825         Utils::OpenHandle(*data[i]);
826     array.add(value);
827   }
828 }
829
830
831 void Template::Set(v8::Handle<String> name,
832                    v8::Handle<Data> value,
833                    v8::PropertyAttribute attribute) {
834   i::Isolate* isolate = i::Isolate::Current();
835   ENTER_V8(isolate);
836   i::HandleScope scope(isolate);
837   const int kSize = 3;
838   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
839   v8::Handle<v8::Data> data[kSize] = {
840     name,
841     value,
842     v8::Integer::New(v8_isolate, attribute)};
843   TemplateSet(isolate, this, kSize, data);
844 }
845
846
847 void Template::SetAccessorProperty(
848     v8::Local<v8::String> name,
849     v8::Local<FunctionTemplate> getter,
850     v8::Local<FunctionTemplate> setter,
851     v8::PropertyAttribute attribute,
852     v8::AccessControl access_control) {
853   // TODO(verwaest): Remove |access_control|.
854   DCHECK_EQ(v8::DEFAULT, access_control);
855   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
856   ENTER_V8(isolate);
857   DCHECK(!name.IsEmpty());
858   DCHECK(!getter.IsEmpty() || !setter.IsEmpty());
859   i::HandleScope scope(isolate);
860   const int kSize = 5;
861   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
862   v8::Handle<v8::Data> data[kSize] = {
863     name,
864     getter,
865     setter,
866     v8::Integer::New(v8_isolate, attribute)};
867   TemplateSet(isolate, this, kSize, data);
868 }
869
870
871 // --- F u n c t i o n   T e m p l a t e ---
872 static void InitializeFunctionTemplate(
873     i::Handle<i::FunctionTemplateInfo> info) {
874   info->set_tag(i::Smi::FromInt(Consts::FUNCTION_TEMPLATE));
875   info->set_flag(0);
876 }
877
878
879 Local<ObjectTemplate> FunctionTemplate::PrototypeTemplate() {
880   i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
881   ENTER_V8(i_isolate);
882   i::Handle<i::Object> result(Utils::OpenHandle(this)->prototype_template(),
883                               i_isolate);
884   if (result->IsUndefined()) {
885     v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(i_isolate);
886     result = Utils::OpenHandle(*ObjectTemplate::New(isolate));
887     Utils::OpenHandle(this)->set_prototype_template(*result);
888   }
889   return ToApiHandle<ObjectTemplate>(result);
890 }
891
892
893 void FunctionTemplate::Inherit(v8::Handle<FunctionTemplate> value) {
894   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
895   ENTER_V8(isolate);
896   Utils::OpenHandle(this)->set_parent_template(*Utils::OpenHandle(*value));
897 }
898
899
900 static Local<FunctionTemplate> FunctionTemplateNew(
901     i::Isolate* isolate,
902     FunctionCallback callback,
903     v8::Handle<Value> data,
904     v8::Handle<Signature> signature,
905     int length,
906     bool do_not_cache) {
907   i::Handle<i::Struct> struct_obj =
908       isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
909   i::Handle<i::FunctionTemplateInfo> obj =
910       i::Handle<i::FunctionTemplateInfo>::cast(struct_obj);
911   InitializeFunctionTemplate(obj);
912   obj->set_do_not_cache(do_not_cache);
913   int next_serial_number = 0;
914   if (!do_not_cache) {
915     next_serial_number = isolate->next_serial_number() + 1;
916     isolate->set_next_serial_number(next_serial_number);
917   }
918   obj->set_serial_number(i::Smi::FromInt(next_serial_number));
919   if (callback != 0) {
920     if (data.IsEmpty()) {
921       data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
922     }
923     Utils::ToLocal(obj)->SetCallHandler(callback, data);
924   }
925   obj->set_length(length);
926   obj->set_undetectable(false);
927   obj->set_needs_access_check(false);
928   if (!signature.IsEmpty())
929     obj->set_signature(*Utils::OpenHandle(*signature));
930   return Utils::ToLocal(obj);
931 }
932
933 Local<FunctionTemplate> FunctionTemplate::New(
934     Isolate* isolate,
935     FunctionCallback callback,
936     v8::Handle<Value> data,
937     v8::Handle<Signature> signature,
938     int length) {
939   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
940   EnsureInitializedForIsolate(i_isolate, "v8::FunctionTemplate::New()");
941   LOG_API(i_isolate, "FunctionTemplate::New");
942   ENTER_V8(i_isolate);
943   return FunctionTemplateNew(
944       i_isolate, callback, data, signature, length, false);
945 }
946
947
948 Local<Signature> Signature::New(Isolate* isolate,
949                                 Handle<FunctionTemplate> receiver, int argc,
950                                 Handle<FunctionTemplate> argv[]) {
951   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
952   EnsureInitializedForIsolate(i_isolate, "v8::Signature::New()");
953   LOG_API(i_isolate, "Signature::New");
954   ENTER_V8(i_isolate);
955   i::Handle<i::Struct> struct_obj =
956       i_isolate->factory()->NewStruct(i::SIGNATURE_INFO_TYPE);
957   i::Handle<i::SignatureInfo> obj =
958       i::Handle<i::SignatureInfo>::cast(struct_obj);
959   if (!receiver.IsEmpty()) obj->set_receiver(*Utils::OpenHandle(*receiver));
960   if (argc > 0) {
961     i::Handle<i::FixedArray> args = i_isolate->factory()->NewFixedArray(argc);
962     for (int i = 0; i < argc; i++) {
963       if (!argv[i].IsEmpty())
964         args->set(i, *Utils::OpenHandle(*argv[i]));
965     }
966     obj->set_args(*args);
967   }
968   return Utils::ToLocal(obj);
969 }
970
971
972 Local<AccessorSignature> AccessorSignature::New(
973     Isolate* isolate,
974     Handle<FunctionTemplate> receiver) {
975   return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver));
976 }
977
978
979 template<typename Operation>
980 static Local<Operation> NewDescriptor(
981     Isolate* isolate,
982     const i::DeclaredAccessorDescriptorData& data,
983     Data* previous_descriptor) {
984   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
985   i::Handle<i::DeclaredAccessorDescriptor> previous =
986       i::Handle<i::DeclaredAccessorDescriptor>();
987   if (previous_descriptor != NULL) {
988     previous = Utils::OpenHandle(
989         static_cast<DeclaredAccessorDescriptor*>(previous_descriptor));
990   }
991   i::Handle<i::DeclaredAccessorDescriptor> descriptor =
992       i::DeclaredAccessorDescriptor::Create(internal_isolate, data, previous);
993   return Utils::Convert<i::DeclaredAccessorDescriptor, Operation>(descriptor);
994 }
995
996
997 Local<RawOperationDescriptor>
998 ObjectOperationDescriptor::NewInternalFieldDereference(
999     Isolate* isolate,
1000     int internal_field) {
1001   i::DeclaredAccessorDescriptorData data;
1002   data.type = i::kDescriptorObjectDereference;
1003   data.object_dereference_descriptor.internal_field = internal_field;
1004   return NewDescriptor<RawOperationDescriptor>(isolate, data, NULL);
1005 }
1006
1007
1008 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawShift(
1009     Isolate* isolate,
1010     int16_t byte_offset) {
1011   i::DeclaredAccessorDescriptorData data;
1012   data.type = i::kDescriptorPointerShift;
1013   data.pointer_shift_descriptor.byte_offset = byte_offset;
1014   return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1015 }
1016
1017
1018 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewHandleDereference(
1019     Isolate* isolate) {
1020   i::DeclaredAccessorDescriptorData data;
1021   data.type = i::kDescriptorReturnObject;
1022   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1023 }
1024
1025
1026 Local<RawOperationDescriptor> RawOperationDescriptor::NewRawDereference(
1027     Isolate* isolate) {
1028   i::DeclaredAccessorDescriptorData data;
1029   data.type = i::kDescriptorPointerDereference;
1030   return NewDescriptor<RawOperationDescriptor>(isolate, data, this);
1031 }
1032
1033
1034 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPointerCompare(
1035     Isolate* isolate,
1036     void* compare_value) {
1037   i::DeclaredAccessorDescriptorData data;
1038   data.type = i::kDescriptorPointerCompare;
1039   data.pointer_compare_descriptor.compare_value = compare_value;
1040   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1041 }
1042
1043
1044 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewPrimitiveValue(
1045     Isolate* isolate,
1046     DeclaredAccessorDescriptorDataType data_type,
1047     uint8_t bool_offset) {
1048   i::DeclaredAccessorDescriptorData data;
1049   data.type = i::kDescriptorPrimitiveValue;
1050   data.primitive_value_descriptor.data_type = data_type;
1051   data.primitive_value_descriptor.bool_offset = bool_offset;
1052   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, this);
1053 }
1054
1055
1056 template<typename T>
1057 static Local<DeclaredAccessorDescriptor> NewBitmaskCompare(
1058     Isolate* isolate,
1059     T bitmask,
1060     T compare_value,
1061     RawOperationDescriptor* operation) {
1062   i::DeclaredAccessorDescriptorData data;
1063   data.type = i::kDescriptorBitmaskCompare;
1064   data.bitmask_compare_descriptor.bitmask = bitmask;
1065   data.bitmask_compare_descriptor.compare_value = compare_value;
1066   data.bitmask_compare_descriptor.size = sizeof(T);
1067   return NewDescriptor<DeclaredAccessorDescriptor>(isolate, data, operation);
1068 }
1069
1070
1071 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare8(
1072     Isolate* isolate,
1073     uint8_t bitmask,
1074     uint8_t compare_value) {
1075   return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1076 }
1077
1078
1079 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare16(
1080     Isolate* isolate,
1081     uint16_t bitmask,
1082     uint16_t compare_value) {
1083   return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1084 }
1085
1086
1087 Local<DeclaredAccessorDescriptor> RawOperationDescriptor::NewBitmaskCompare32(
1088     Isolate* isolate,
1089     uint32_t bitmask,
1090     uint32_t compare_value) {
1091   return NewBitmaskCompare(isolate, bitmask, compare_value, this);
1092 }
1093
1094
1095 Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) {
1096   Handle<FunctionTemplate> types[1] = { type };
1097   return TypeSwitch::New(1, types);
1098 }
1099
1100
1101 Local<TypeSwitch> TypeSwitch::New(int argc, Handle<FunctionTemplate> types[]) {
1102   i::Isolate* isolate = i::Isolate::Current();
1103   EnsureInitializedForIsolate(isolate, "v8::TypeSwitch::New()");
1104   LOG_API(isolate, "TypeSwitch::New");
1105   ENTER_V8(isolate);
1106   i::Handle<i::FixedArray> vector = isolate->factory()->NewFixedArray(argc);
1107   for (int i = 0; i < argc; i++)
1108     vector->set(i, *Utils::OpenHandle(*types[i]));
1109   i::Handle<i::Struct> struct_obj =
1110       isolate->factory()->NewStruct(i::TYPE_SWITCH_INFO_TYPE);
1111   i::Handle<i::TypeSwitchInfo> obj =
1112       i::Handle<i::TypeSwitchInfo>::cast(struct_obj);
1113   obj->set_types(*vector);
1114   return Utils::ToLocal(obj);
1115 }
1116
1117
1118 int TypeSwitch::match(v8::Handle<Value> value) {
1119   i::Isolate* isolate = i::Isolate::Current();
1120   LOG_API(isolate, "TypeSwitch::match");
1121   USE(isolate);
1122   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
1123   i::Handle<i::TypeSwitchInfo> info = Utils::OpenHandle(this);
1124   i::FixedArray* types = i::FixedArray::cast(info->types());
1125   for (int i = 0; i < types->length(); i++) {
1126     if (i::FunctionTemplateInfo::cast(types->get(i))->IsTemplateFor(*obj))
1127       return i + 1;
1128   }
1129   return 0;
1130 }
1131
1132
1133 #define SET_FIELD_WRAPPED(obj, setter, cdata) do {                      \
1134     i::Handle<i::Object> foreign = FromCData(obj->GetIsolate(), cdata); \
1135     (obj)->setter(*foreign);                                            \
1136   } while (false)
1137
1138
1139 void FunctionTemplate::SetCallHandler(FunctionCallback callback,
1140                                       v8::Handle<Value> data) {
1141   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1142   ENTER_V8(isolate);
1143   i::HandleScope scope(isolate);
1144   i::Handle<i::Struct> struct_obj =
1145       isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1146   i::Handle<i::CallHandlerInfo> obj =
1147       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1148   SET_FIELD_WRAPPED(obj, set_callback, callback);
1149   if (data.IsEmpty()) {
1150     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1151   }
1152   obj->set_data(*Utils::OpenHandle(*data));
1153   Utils::OpenHandle(this)->set_call_code(*obj);
1154 }
1155
1156
1157 static i::Handle<i::AccessorInfo> SetAccessorInfoProperties(
1158     i::Handle<i::AccessorInfo> obj,
1159     v8::Handle<String> name,
1160     v8::AccessControl settings,
1161     v8::PropertyAttribute attributes,
1162     v8::Handle<AccessorSignature> signature) {
1163   obj->set_name(*Utils::OpenHandle(*name));
1164   if (settings & ALL_CAN_READ) obj->set_all_can_read(true);
1165   if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true);
1166   obj->set_property_attributes(static_cast<PropertyAttributes>(attributes));
1167   if (!signature.IsEmpty()) {
1168     obj->set_expected_receiver_type(*Utils::OpenHandle(*signature));
1169   }
1170   return obj;
1171 }
1172
1173
1174 template<typename Getter, typename Setter>
1175 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1176     v8::Handle<String> name,
1177     Getter getter,
1178     Setter setter,
1179     v8::Handle<Value> data,
1180     v8::AccessControl settings,
1181     v8::PropertyAttribute attributes,
1182     v8::Handle<AccessorSignature> signature) {
1183   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1184   i::Handle<i::ExecutableAccessorInfo> obj =
1185       isolate->factory()->NewExecutableAccessorInfo();
1186   SET_FIELD_WRAPPED(obj, set_getter, getter);
1187   SET_FIELD_WRAPPED(obj, set_setter, setter);
1188   if (data.IsEmpty()) {
1189     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1190   }
1191   obj->set_data(*Utils::OpenHandle(*data));
1192   return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1193 }
1194
1195
1196 static i::Handle<i::AccessorInfo> MakeAccessorInfo(
1197     v8::Handle<String> name,
1198     v8::Handle<v8::DeclaredAccessorDescriptor> descriptor,
1199     void* setter_ignored,
1200     void* data_ignored,
1201     v8::AccessControl settings,
1202     v8::PropertyAttribute attributes,
1203     v8::Handle<AccessorSignature> signature) {
1204   i::Isolate* isolate = Utils::OpenHandle(*name)->GetIsolate();
1205   if (descriptor.IsEmpty()) return i::Handle<i::DeclaredAccessorInfo>();
1206   i::Handle<i::DeclaredAccessorInfo> obj =
1207       isolate->factory()->NewDeclaredAccessorInfo();
1208   obj->set_descriptor(*Utils::OpenHandle(*descriptor));
1209   return SetAccessorInfoProperties(obj, name, settings, attributes, signature);
1210 }
1211
1212
1213 Local<ObjectTemplate> FunctionTemplate::InstanceTemplate() {
1214   i::Handle<i::FunctionTemplateInfo> handle = Utils::OpenHandle(this, true);
1215   if (!Utils::ApiCheck(!handle.is_null(),
1216                        "v8::FunctionTemplate::InstanceTemplate()",
1217                        "Reading from empty handle")) {
1218     return Local<ObjectTemplate>();
1219   }
1220   i::Isolate* isolate = handle->GetIsolate();
1221   ENTER_V8(isolate);
1222   if (handle->instance_template()->IsUndefined()) {
1223     Local<ObjectTemplate> templ =
1224         ObjectTemplate::New(isolate, ToApiHandle<FunctionTemplate>(handle));
1225     handle->set_instance_template(*Utils::OpenHandle(*templ));
1226   }
1227   i::Handle<i::ObjectTemplateInfo> result(
1228       i::ObjectTemplateInfo::cast(handle->instance_template()));
1229   return Utils::ToLocal(result);
1230 }
1231
1232
1233 void FunctionTemplate::SetLength(int length) {
1234   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1235   ENTER_V8(isolate);
1236   Utils::OpenHandle(this)->set_length(length);
1237 }
1238
1239
1240 void FunctionTemplate::SetClassName(Handle<String> name) {
1241   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1242   ENTER_V8(isolate);
1243   Utils::OpenHandle(this)->set_class_name(*Utils::OpenHandle(*name));
1244 }
1245
1246
1247 void FunctionTemplate::SetHiddenPrototype(bool value) {
1248   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1249   ENTER_V8(isolate);
1250   Utils::OpenHandle(this)->set_hidden_prototype(value);
1251 }
1252
1253
1254 void FunctionTemplate::ReadOnlyPrototype() {
1255   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1256   ENTER_V8(isolate);
1257   Utils::OpenHandle(this)->set_read_only_prototype(true);
1258 }
1259
1260
1261 void FunctionTemplate::RemovePrototype() {
1262   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1263   ENTER_V8(isolate);
1264   Utils::OpenHandle(this)->set_remove_prototype(true);
1265 }
1266
1267
1268 // --- O b j e c t T e m p l a t e ---
1269
1270
1271 Local<ObjectTemplate> ObjectTemplate::New(Isolate* isolate) {
1272   return New(reinterpret_cast<i::Isolate*>(isolate), Local<FunctionTemplate>());
1273 }
1274
1275
1276 Local<ObjectTemplate> ObjectTemplate::New() {
1277   return New(i::Isolate::Current(), Local<FunctionTemplate>());
1278 }
1279
1280
1281 Local<ObjectTemplate> ObjectTemplate::New(
1282     i::Isolate* isolate,
1283     v8::Handle<FunctionTemplate> constructor) {
1284   EnsureInitializedForIsolate(isolate, "v8::ObjectTemplate::New()");
1285   LOG_API(isolate, "ObjectTemplate::New");
1286   ENTER_V8(isolate);
1287   i::Handle<i::Struct> struct_obj =
1288       isolate->factory()->NewStruct(i::OBJECT_TEMPLATE_INFO_TYPE);
1289   i::Handle<i::ObjectTemplateInfo> obj =
1290       i::Handle<i::ObjectTemplateInfo>::cast(struct_obj);
1291   InitializeTemplate(obj, Consts::OBJECT_TEMPLATE);
1292   if (!constructor.IsEmpty())
1293     obj->set_constructor(*Utils::OpenHandle(*constructor));
1294   obj->set_internal_field_count(i::Smi::FromInt(0));
1295   return Utils::ToLocal(obj);
1296 }
1297
1298
1299 // Ensure that the object template has a constructor.  If no
1300 // constructor is available we create one.
1301 static i::Handle<i::FunctionTemplateInfo> EnsureConstructor(
1302     i::Isolate* isolate,
1303     ObjectTemplate* object_template) {
1304   i::Object* obj = Utils::OpenHandle(object_template)->constructor();
1305   if (!obj ->IsUndefined()) {
1306     i::FunctionTemplateInfo* info = i::FunctionTemplateInfo::cast(obj);
1307     return i::Handle<i::FunctionTemplateInfo>(info, isolate);
1308   }
1309   Local<FunctionTemplate> templ =
1310       FunctionTemplate::New(reinterpret_cast<Isolate*>(isolate));
1311   i::Handle<i::FunctionTemplateInfo> constructor = Utils::OpenHandle(*templ);
1312   constructor->set_instance_template(*Utils::OpenHandle(object_template));
1313   Utils::OpenHandle(object_template)->set_constructor(*constructor);
1314   return constructor;
1315 }
1316
1317
1318 static inline void AddPropertyToTemplate(
1319     i::Handle<i::TemplateInfo> info,
1320     i::Handle<i::AccessorInfo> obj) {
1321   i::Isolate* isolate = info->GetIsolate();
1322   i::Handle<i::Object> list(info->property_accessors(), isolate);
1323   if (list->IsUndefined()) {
1324     list = NeanderArray(isolate).value();
1325     info->set_property_accessors(*list);
1326   }
1327   NeanderArray array(list);
1328   array.add(obj);
1329 }
1330
1331
1332 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1333     i::Isolate* isolate,
1334     Template* template_obj) {
1335   return Utils::OpenHandle(template_obj);
1336 }
1337
1338
1339 // TODO(dcarney): remove this with ObjectTemplate::SetAccessor
1340 static inline i::Handle<i::TemplateInfo> GetTemplateInfo(
1341     i::Isolate* isolate,
1342     ObjectTemplate* object_template) {
1343   EnsureConstructor(isolate, object_template);
1344   return Utils::OpenHandle(object_template);
1345 }
1346
1347
1348 template<typename Setter, typename Getter, typename Data, typename Template>
1349 static bool TemplateSetAccessor(
1350     Template* template_obj,
1351     v8::Local<String> name,
1352     Getter getter,
1353     Setter setter,
1354     Data data,
1355     AccessControl settings,
1356     PropertyAttribute attribute,
1357     v8::Local<AccessorSignature> signature) {
1358   i::Isolate* isolate = Utils::OpenHandle(template_obj)->GetIsolate();
1359   ENTER_V8(isolate);
1360   i::HandleScope scope(isolate);
1361   i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(
1362       name, getter, setter, data, settings, attribute, signature);
1363   if (obj.is_null()) return false;
1364   i::Handle<i::TemplateInfo> info = GetTemplateInfo(isolate, template_obj);
1365   AddPropertyToTemplate(info, obj);
1366   return true;
1367 }
1368
1369
1370 bool Template::SetDeclaredAccessor(
1371     Local<String> name,
1372     Local<DeclaredAccessorDescriptor> descriptor,
1373     PropertyAttribute attribute,
1374     Local<AccessorSignature> signature,
1375     AccessControl settings) {
1376   void* null = NULL;
1377   return TemplateSetAccessor(
1378       this, name, descriptor, null, null, settings, attribute, signature);
1379 }
1380
1381
1382 void Template::SetNativeDataProperty(v8::Local<String> name,
1383                                      AccessorGetterCallback getter,
1384                                      AccessorSetterCallback setter,
1385                                      v8::Handle<Value> data,
1386                                      PropertyAttribute attribute,
1387                                      v8::Local<AccessorSignature> signature,
1388                                      AccessControl settings) {
1389   TemplateSetAccessor(
1390       this, name, getter, setter, data, settings, attribute, signature);
1391 }
1392
1393
1394 void ObjectTemplate::SetAccessor(v8::Handle<String> name,
1395                                  AccessorGetterCallback getter,
1396                                  AccessorSetterCallback setter,
1397                                  v8::Handle<Value> data,
1398                                  AccessControl settings,
1399                                  PropertyAttribute attribute,
1400                                  v8::Handle<AccessorSignature> signature) {
1401   TemplateSetAccessor(
1402       this, name, getter, setter, data, settings, attribute, signature);
1403 }
1404
1405
1406 void ObjectTemplate::SetNamedPropertyHandler(
1407     NamedPropertyGetterCallback getter,
1408     NamedPropertySetterCallback setter,
1409     NamedPropertyQueryCallback query,
1410     NamedPropertyDeleterCallback remover,
1411     NamedPropertyEnumeratorCallback enumerator,
1412     Handle<Value> data) {
1413   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1414   ENTER_V8(isolate);
1415   i::HandleScope scope(isolate);
1416   EnsureConstructor(isolate, this);
1417   i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1418       Utils::OpenHandle(this)->constructor());
1419   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1420   i::Handle<i::Struct> struct_obj =
1421       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1422   i::Handle<i::InterceptorInfo> obj =
1423       i::Handle<i::InterceptorInfo>::cast(struct_obj);
1424
1425   if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1426   if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1427   if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1428   if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1429   if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1430
1431   if (data.IsEmpty()) {
1432     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1433   }
1434   obj->set_data(*Utils::OpenHandle(*data));
1435   cons->set_named_property_handler(*obj);
1436 }
1437
1438
1439 void ObjectTemplate::MarkAsUndetectable() {
1440   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1441   ENTER_V8(isolate);
1442   i::HandleScope scope(isolate);
1443   EnsureConstructor(isolate, this);
1444   i::FunctionTemplateInfo* constructor =
1445       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1446   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1447   cons->set_undetectable(true);
1448 }
1449
1450
1451 void ObjectTemplate::SetAccessCheckCallbacks(
1452     NamedSecurityCallback named_callback,
1453     IndexedSecurityCallback indexed_callback,
1454     Handle<Value> data,
1455     bool turned_on_by_default) {
1456   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1457   ENTER_V8(isolate);
1458   i::HandleScope scope(isolate);
1459   EnsureConstructor(isolate, this);
1460
1461   i::Handle<i::Struct> struct_info =
1462       isolate->factory()->NewStruct(i::ACCESS_CHECK_INFO_TYPE);
1463   i::Handle<i::AccessCheckInfo> info =
1464       i::Handle<i::AccessCheckInfo>::cast(struct_info);
1465
1466   SET_FIELD_WRAPPED(info, set_named_callback, named_callback);
1467   SET_FIELD_WRAPPED(info, set_indexed_callback, indexed_callback);
1468
1469   if (data.IsEmpty()) {
1470     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1471   }
1472   info->set_data(*Utils::OpenHandle(*data));
1473
1474   i::FunctionTemplateInfo* constructor =
1475       i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
1476   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1477   cons->set_access_check_info(*info);
1478   cons->set_needs_access_check(turned_on_by_default);
1479 }
1480
1481
1482 void ObjectTemplate::SetIndexedPropertyHandler(
1483     IndexedPropertyGetterCallback getter,
1484     IndexedPropertySetterCallback setter,
1485     IndexedPropertyQueryCallback query,
1486     IndexedPropertyDeleterCallback remover,
1487     IndexedPropertyEnumeratorCallback enumerator,
1488     Handle<Value> data) {
1489   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1490   ENTER_V8(isolate);
1491   i::HandleScope scope(isolate);
1492   EnsureConstructor(isolate, this);
1493   i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1494       Utils::OpenHandle(this)->constructor());
1495   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1496   i::Handle<i::Struct> struct_obj =
1497       isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE);
1498   i::Handle<i::InterceptorInfo> obj =
1499       i::Handle<i::InterceptorInfo>::cast(struct_obj);
1500
1501   if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter);
1502   if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter);
1503   if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
1504   if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
1505   if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
1506
1507   if (data.IsEmpty()) {
1508     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1509   }
1510   obj->set_data(*Utils::OpenHandle(*data));
1511   cons->set_indexed_property_handler(*obj);
1512 }
1513
1514
1515 void ObjectTemplate::SetCallAsFunctionHandler(FunctionCallback callback,
1516                                               Handle<Value> data) {
1517   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1518   ENTER_V8(isolate);
1519   i::HandleScope scope(isolate);
1520   EnsureConstructor(isolate, this);
1521   i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(
1522       Utils::OpenHandle(this)->constructor());
1523   i::Handle<i::FunctionTemplateInfo> cons(constructor);
1524   i::Handle<i::Struct> struct_obj =
1525       isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE);
1526   i::Handle<i::CallHandlerInfo> obj =
1527       i::Handle<i::CallHandlerInfo>::cast(struct_obj);
1528   SET_FIELD_WRAPPED(obj, set_callback, callback);
1529   if (data.IsEmpty()) {
1530     data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
1531   }
1532   obj->set_data(*Utils::OpenHandle(*data));
1533   cons->set_instance_call_handler(*obj);
1534 }
1535
1536
1537 int ObjectTemplate::InternalFieldCount() {
1538   return i::Smi::cast(Utils::OpenHandle(this)->internal_field_count())->value();
1539 }
1540
1541
1542 void ObjectTemplate::SetInternalFieldCount(int value) {
1543   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1544   if (!Utils::ApiCheck(i::Smi::IsValid(value),
1545                        "v8::ObjectTemplate::SetInternalFieldCount()",
1546                        "Invalid internal field count")) {
1547     return;
1548   }
1549   ENTER_V8(isolate);
1550   if (value > 0) {
1551     // The internal field count is set by the constructor function's
1552     // construct code, so we ensure that there is a constructor
1553     // function to do the setting.
1554     EnsureConstructor(isolate, this);
1555   }
1556   Utils::OpenHandle(this)->set_internal_field_count(i::Smi::FromInt(value));
1557 }
1558
1559
1560 // --- S c r i p t s ---
1561
1562
1563 // Internally, UnboundScript is a SharedFunctionInfo, and Script is a
1564 // JSFunction.
1565
1566 ScriptCompiler::CachedData::CachedData(const uint8_t* data_, int length_,
1567                                        BufferPolicy buffer_policy_)
1568     : data(data_), length(length_), buffer_policy(buffer_policy_) {}
1569
1570
1571 ScriptCompiler::CachedData::~CachedData() {
1572   if (buffer_policy == BufferOwned) {
1573     delete[] data;
1574   }
1575 }
1576
1577
1578 Local<Script> UnboundScript::BindToCurrentContext() {
1579   i::Handle<i::HeapObject> obj =
1580       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1581   i::Handle<i::SharedFunctionInfo>
1582       function_info(i::SharedFunctionInfo::cast(*obj), obj->GetIsolate());
1583   i::Handle<i::JSFunction> function =
1584       obj->GetIsolate()->factory()->NewFunctionFromSharedFunctionInfo(
1585           function_info, obj->GetIsolate()->global_context());
1586   return ToApiHandle<Script>(function);
1587 }
1588
1589
1590 int UnboundScript::GetId() {
1591   i::Handle<i::HeapObject> obj =
1592       i::Handle<i::HeapObject>::cast(Utils::OpenHandle(this));
1593   i::Isolate* isolate = obj->GetIsolate();
1594   ON_BAILOUT(isolate, "v8::UnboundScript::GetId()", return -1);
1595   LOG_API(isolate, "v8::UnboundScript::GetId");
1596   {
1597     i::HandleScope scope(isolate);
1598     i::Handle<i::SharedFunctionInfo> function_info(
1599         i::SharedFunctionInfo::cast(*obj));
1600     i::Handle<i::Script> script(i::Script::cast(function_info->script()));
1601     return script->id()->value();
1602   }
1603 }
1604
1605
1606 int UnboundScript::GetLineNumber(int code_pos) {
1607   i::Handle<i::SharedFunctionInfo> obj =
1608       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1609   i::Isolate* isolate = obj->GetIsolate();
1610   ON_BAILOUT(isolate, "v8::UnboundScript::GetLineNumber()", return -1);
1611   LOG_API(isolate, "UnboundScript::GetLineNumber");
1612   if (obj->script()->IsScript()) {
1613     i::Handle<i::Script> script(i::Script::cast(obj->script()));
1614     return i::Script::GetLineNumber(script, code_pos);
1615   } else {
1616     return -1;
1617   }
1618 }
1619
1620
1621 Handle<Value> UnboundScript::GetScriptName() {
1622   i::Handle<i::SharedFunctionInfo> obj =
1623       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1624   i::Isolate* isolate = obj->GetIsolate();
1625   ON_BAILOUT(isolate, "v8::UnboundScript::GetName()",
1626              return Handle<String>());
1627   LOG_API(isolate, "UnboundScript::GetName");
1628   if (obj->script()->IsScript()) {
1629     i::Object* name = i::Script::cast(obj->script())->name();
1630     return Utils::ToLocal(i::Handle<i::Object>(name, isolate));
1631   } else {
1632     return Handle<String>();
1633   }
1634 }
1635
1636
1637 Handle<Value> UnboundScript::GetSourceURL() {
1638   i::Handle<i::SharedFunctionInfo> obj =
1639       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1640   i::Isolate* isolate = obj->GetIsolate();
1641   ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceURL()",
1642              return Handle<String>());
1643   LOG_API(isolate, "UnboundScript::GetSourceURL");
1644   if (obj->script()->IsScript()) {
1645     i::Object* url = i::Script::cast(obj->script())->source_url();
1646     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
1647   } else {
1648     return Handle<String>();
1649   }
1650 }
1651
1652
1653 Handle<Value> UnboundScript::GetSourceMappingURL() {
1654   i::Handle<i::SharedFunctionInfo> obj =
1655       i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
1656   i::Isolate* isolate = obj->GetIsolate();
1657   ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceMappingURL()",
1658              return Handle<String>());
1659   LOG_API(isolate, "UnboundScript::GetSourceMappingURL");
1660   if (obj->script()->IsScript()) {
1661     i::Object* url = i::Script::cast(obj->script())->source_mapping_url();
1662     return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
1663   } else {
1664     return Handle<String>();
1665   }
1666 }
1667
1668
1669 Local<Value> Script::Run() {
1670   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
1671   // If execution is terminating, Compile(..)->Run() requires this
1672   // check.
1673   if (obj.is_null()) return Local<Value>();
1674   i::Isolate* isolate = i::Handle<i::HeapObject>::cast(obj)->GetIsolate();
1675   ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>());
1676   LOG_API(isolate, "Script::Run");
1677   ENTER_V8(isolate);
1678   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
1679   i::HandleScope scope(isolate);
1680   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
1681   EXCEPTION_PREAMBLE(isolate);
1682   i::Handle<i::Object> receiver(isolate->global_proxy(), isolate);
1683   i::Handle<i::Object> result;
1684   has_pending_exception = !i::Execution::Call(
1685       isolate, fun, receiver, 0, NULL).ToHandle(&result);
1686   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
1687   return Utils::ToLocal(scope.CloseAndEscape(result));
1688 }
1689
1690
1691 Local<UnboundScript> Script::GetUnboundScript() {
1692   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1693   return ToApiHandle<UnboundScript>(
1694       i::Handle<i::SharedFunctionInfo>(i::JSFunction::cast(*obj)->shared()));
1695 }
1696
1697
1698 Local<UnboundScript> ScriptCompiler::CompileUnbound(
1699     Isolate* v8_isolate,
1700     Source* source,
1701     CompileOptions options) {
1702   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1703   ON_BAILOUT(isolate, "v8::ScriptCompiler::CompileUnbound()",
1704              return Local<UnboundScript>());
1705
1706   // Support the old API for a transition period:
1707   // - kProduceToCache -> kProduceParserCache
1708   // - kNoCompileOptions + cached_data != NULL -> kConsumeParserCache
1709   if (options == kProduceDataToCache) {
1710     options = kProduceParserCache;
1711   } else if (options == kNoCompileOptions && source->cached_data) {
1712     options = kConsumeParserCache;
1713   }
1714
1715   i::ScriptData* script_data = NULL;
1716   if (options == kConsumeParserCache || options == kConsumeCodeCache) {
1717     DCHECK(source->cached_data);
1718     // ScriptData takes care of pointer-aligning the data.
1719     script_data = new i::ScriptData(source->cached_data->data,
1720                                     source->cached_data->length);
1721   }
1722
1723   i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
1724   LOG_API(isolate, "ScriptCompiler::CompileUnbound");
1725   ENTER_V8(isolate);
1726   i::SharedFunctionInfo* raw_result = NULL;
1727   { i::HandleScope scope(isolate);
1728     i::Handle<i::Object> name_obj;
1729     int line_offset = 0;
1730     int column_offset = 0;
1731     bool is_shared_cross_origin = false;
1732     if (!source->resource_name.IsEmpty()) {
1733       name_obj = Utils::OpenHandle(*(source->resource_name));
1734     }
1735     if (!source->resource_line_offset.IsEmpty()) {
1736       line_offset = static_cast<int>(source->resource_line_offset->Value());
1737     }
1738     if (!source->resource_column_offset.IsEmpty()) {
1739       column_offset =
1740           static_cast<int>(source->resource_column_offset->Value());
1741     }
1742     if (!source->resource_is_shared_cross_origin.IsEmpty()) {
1743       v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1744       is_shared_cross_origin =
1745           source->resource_is_shared_cross_origin == v8::True(v8_isolate);
1746     }
1747     EXCEPTION_PREAMBLE(isolate);
1748     i::Handle<i::SharedFunctionInfo> result = i::Compiler::CompileScript(
1749         str, name_obj, line_offset, column_offset, is_shared_cross_origin,
1750         isolate->global_context(), NULL, &script_data, options,
1751         i::NOT_NATIVES_CODE);
1752     has_pending_exception = result.is_null();
1753     if (has_pending_exception && script_data != NULL) {
1754       // This case won't happen during normal operation; we have compiled
1755       // successfully and produced cached data, and but the second compilation
1756       // of the same source code fails.
1757       delete script_data;
1758       script_data = NULL;
1759     }
1760     EXCEPTION_BAILOUT_CHECK(isolate, Local<UnboundScript>());
1761     raw_result = *result;
1762
1763     if ((options == kProduceParserCache || options == kProduceCodeCache) &&
1764         script_data != NULL) {
1765       // script_data now contains the data that was generated. source will
1766       // take the ownership.
1767       source->cached_data = new CachedData(
1768           script_data->data(), script_data->length(), CachedData::BufferOwned);
1769       script_data->ReleaseDataOwnership();
1770     }
1771     delete script_data;
1772   }
1773   i::Handle<i::SharedFunctionInfo> result(raw_result, isolate);
1774   return ToApiHandle<UnboundScript>(result);
1775 }
1776
1777
1778 Local<Script> ScriptCompiler::Compile(
1779     Isolate* v8_isolate,
1780     Source* source,
1781     CompileOptions options) {
1782   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
1783   ON_BAILOUT(isolate, "v8::ScriptCompiler::Compile()", return Local<Script>());
1784   LOG_API(isolate, "ScriptCompiler::CompiletBound()");
1785   ENTER_V8(isolate);
1786   Local<UnboundScript> generic = CompileUnbound(v8_isolate, source, options);
1787   if (generic.IsEmpty()) return Local<Script>();
1788   return generic->BindToCurrentContext();
1789 }
1790
1791
1792 Local<Script> Script::Compile(v8::Handle<String> source,
1793                               v8::ScriptOrigin* origin) {
1794   i::Handle<i::String> str = Utils::OpenHandle(*source);
1795   if (origin) {
1796     ScriptCompiler::Source script_source(source, *origin);
1797     return ScriptCompiler::Compile(
1798         reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1799         &script_source);
1800   }
1801   ScriptCompiler::Source script_source(source);
1802   return ScriptCompiler::Compile(
1803       reinterpret_cast<v8::Isolate*>(str->GetIsolate()),
1804       &script_source);
1805 }
1806
1807
1808 Local<Script> Script::Compile(v8::Handle<String> source,
1809                               v8::Handle<String> file_name) {
1810   ScriptOrigin origin(file_name);
1811   return Compile(source, &origin);
1812 }
1813
1814
1815 // --- E x c e p t i o n s ---
1816
1817
1818 v8::TryCatch::TryCatch()
1819     : isolate_(i::Isolate::Current()),
1820       next_(isolate_->try_catch_handler()),
1821       is_verbose_(false),
1822       can_continue_(true),
1823       capture_message_(true),
1824       rethrow_(false),
1825       has_terminated_(false) {
1826   ResetInternal();
1827   // Special handling for simulators which have a separate JS stack.
1828   js_stack_comparable_address_ =
1829       reinterpret_cast<void*>(v8::internal::SimulatorStack::RegisterCTryCatch(
1830           GetCurrentStackPosition()));
1831   isolate_->RegisterTryCatchHandler(this);
1832 }
1833
1834
1835 v8::TryCatch::~TryCatch() {
1836   DCHECK(isolate_ == i::Isolate::Current());
1837   if (rethrow_) {
1838     v8::Isolate* isolate = reinterpret_cast<Isolate*>(isolate_);
1839     v8::HandleScope scope(isolate);
1840     v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(isolate, Exception());
1841     if (HasCaught() && capture_message_) {
1842       // If an exception was caught and rethrow_ is indicated, the saved
1843       // message, script, and location need to be restored to Isolate TLS
1844       // for reuse.  capture_message_ needs to be disabled so that DoThrow()
1845       // does not create a new message.
1846       isolate_->thread_local_top()->rethrowing_message_ = true;
1847       isolate_->RestorePendingMessageFromTryCatch(this);
1848     }
1849     isolate_->UnregisterTryCatchHandler(this);
1850     v8::internal::SimulatorStack::UnregisterCTryCatch();
1851     reinterpret_cast<Isolate*>(isolate_)->ThrowException(exc);
1852     DCHECK(!isolate_->thread_local_top()->rethrowing_message_);
1853   } else {
1854     if (HasCaught() && isolate_->has_scheduled_exception()) {
1855       // If an exception was caught but is still scheduled because no API call
1856       // promoted it, then it is canceled to prevent it from being propagated.
1857       // Note that this will not cancel termination exceptions.
1858       isolate_->CancelScheduledExceptionFromTryCatch(this);
1859     }
1860     isolate_->UnregisterTryCatchHandler(this);
1861     v8::internal::SimulatorStack::UnregisterCTryCatch();
1862   }
1863 }
1864
1865
1866 bool v8::TryCatch::HasCaught() const {
1867   return !reinterpret_cast<i::Object*>(exception_)->IsTheHole();
1868 }
1869
1870
1871 bool v8::TryCatch::CanContinue() const {
1872   return can_continue_;
1873 }
1874
1875
1876 bool v8::TryCatch::HasTerminated() const {
1877   return has_terminated_;
1878 }
1879
1880
1881 v8::Handle<v8::Value> v8::TryCatch::ReThrow() {
1882   if (!HasCaught()) return v8::Local<v8::Value>();
1883   rethrow_ = true;
1884   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate_));
1885 }
1886
1887
1888 v8::Local<Value> v8::TryCatch::Exception() const {
1889   DCHECK(isolate_ == i::Isolate::Current());
1890   if (HasCaught()) {
1891     // Check for out of memory exception.
1892     i::Object* exception = reinterpret_cast<i::Object*>(exception_);
1893     return v8::Utils::ToLocal(i::Handle<i::Object>(exception, isolate_));
1894   } else {
1895     return v8::Local<Value>();
1896   }
1897 }
1898
1899
1900 v8::Local<Value> v8::TryCatch::StackTrace() const {
1901   DCHECK(isolate_ == i::Isolate::Current());
1902   if (HasCaught()) {
1903     i::Object* raw_obj = reinterpret_cast<i::Object*>(exception_);
1904     if (!raw_obj->IsJSObject()) return v8::Local<Value>();
1905     i::HandleScope scope(isolate_);
1906     i::Handle<i::JSObject> obj(i::JSObject::cast(raw_obj), isolate_);
1907     i::Handle<i::String> name = isolate_->factory()->stack_string();
1908     EXCEPTION_PREAMBLE(isolate_);
1909     Maybe<bool> maybe = i::JSReceiver::HasProperty(obj, name);
1910     has_pending_exception = !maybe.has_value;
1911     EXCEPTION_BAILOUT_CHECK(isolate_, v8::Local<Value>());
1912     if (!maybe.value) return v8::Local<Value>();
1913     i::Handle<i::Object> value;
1914     if (!i::Object::GetProperty(obj, name).ToHandle(&value)) {
1915       return v8::Local<Value>();
1916     }
1917     return v8::Utils::ToLocal(scope.CloseAndEscape(value));
1918   } else {
1919     return v8::Local<Value>();
1920   }
1921 }
1922
1923
1924 v8::Local<v8::Message> v8::TryCatch::Message() const {
1925   DCHECK(isolate_ == i::Isolate::Current());
1926   i::Object* message = reinterpret_cast<i::Object*>(message_obj_);
1927   DCHECK(message->IsJSMessageObject() || message->IsTheHole());
1928   if (HasCaught() && !message->IsTheHole()) {
1929     return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_));
1930   } else {
1931     return v8::Local<v8::Message>();
1932   }
1933 }
1934
1935
1936 void v8::TryCatch::Reset() {
1937   DCHECK(isolate_ == i::Isolate::Current());
1938   if (!rethrow_ && HasCaught() && isolate_->has_scheduled_exception()) {
1939     // If an exception was caught but is still scheduled because no API call
1940     // promoted it, then it is canceled to prevent it from being propagated.
1941     // Note that this will not cancel termination exceptions.
1942     isolate_->CancelScheduledExceptionFromTryCatch(this);
1943   }
1944   ResetInternal();
1945 }
1946
1947
1948 void v8::TryCatch::ResetInternal() {
1949   i::Object* the_hole = isolate_->heap()->the_hole_value();
1950   exception_ = the_hole;
1951   message_obj_ = the_hole;
1952   message_script_ = the_hole;
1953   message_start_pos_ = 0;
1954   message_end_pos_ = 0;
1955 }
1956
1957
1958 void v8::TryCatch::SetVerbose(bool value) {
1959   is_verbose_ = value;
1960 }
1961
1962
1963 void v8::TryCatch::SetCaptureMessage(bool value) {
1964   capture_message_ = value;
1965 }
1966
1967
1968 // --- M e s s a g e ---
1969
1970
1971 Local<String> Message::Get() const {
1972   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1973   ON_BAILOUT(isolate, "v8::Message::Get()", return Local<String>());
1974   ENTER_V8(isolate);
1975   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
1976   i::Handle<i::Object> obj = Utils::OpenHandle(this);
1977   i::Handle<i::String> raw_result = i::MessageHandler::GetMessage(isolate, obj);
1978   Local<String> result = Utils::ToLocal(raw_result);
1979   return scope.Escape(result);
1980 }
1981
1982
1983 ScriptOrigin Message::GetScriptOrigin() const {
1984   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
1985   i::Handle<i::JSMessageObject> message =
1986       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
1987   i::Handle<i::Object> script_wraper =
1988       i::Handle<i::Object>(message->script(), isolate);
1989   i::Handle<i::JSValue> script_value =
1990       i::Handle<i::JSValue>::cast(script_wraper);
1991   i::Handle<i::Script> script(i::Script::cast(script_value->value()));
1992   i::Handle<i::Object> scriptName(i::Script::GetNameOrSourceURL(script));
1993   v8::Isolate* v8_isolate =
1994       reinterpret_cast<v8::Isolate*>(script->GetIsolate());
1995   v8::ScriptOrigin origin(
1996       Utils::ToLocal(scriptName),
1997       v8::Integer::New(v8_isolate, script->line_offset()->value()),
1998       v8::Integer::New(v8_isolate, script->column_offset()->value()),
1999       Handle<Boolean>(),
2000       v8::Integer::New(v8_isolate, script->id()->value()));
2001   return origin;
2002 }
2003
2004
2005 v8::Handle<Value> Message::GetScriptResourceName() const {
2006   return GetScriptOrigin().ResourceName();
2007 }
2008
2009
2010 v8::Handle<v8::StackTrace> Message::GetStackTrace() const {
2011   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2012   ENTER_V8(isolate);
2013   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2014   i::Handle<i::JSMessageObject> message =
2015       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2016   i::Handle<i::Object> stackFramesObj(message->stack_frames(), isolate);
2017   if (!stackFramesObj->IsJSArray()) return v8::Handle<v8::StackTrace>();
2018   i::Handle<i::JSArray> stackTrace =
2019       i::Handle<i::JSArray>::cast(stackFramesObj);
2020   return scope.Escape(Utils::StackTraceToLocal(stackTrace));
2021 }
2022
2023
2024 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
2025     const char* name,
2026     i::Handle<i::Object> recv,
2027     int argc,
2028     i::Handle<i::Object> argv[]) {
2029   i::Isolate* isolate = i::Isolate::Current();
2030   i::Handle<i::Object> object_fun =
2031       i::Object::GetProperty(
2032           isolate, isolate->js_builtins_object(), name).ToHandleChecked();
2033   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(object_fun);
2034   return i::Execution::Call(isolate, fun, recv, argc, argv);
2035 }
2036
2037
2038 MUST_USE_RESULT static i::MaybeHandle<i::Object> CallV8HeapFunction(
2039     const char* name,
2040     i::Handle<i::Object> data) {
2041   i::Handle<i::Object> argv[] = { data };
2042   return CallV8HeapFunction(name,
2043                             i::Isolate::Current()->js_builtins_object(),
2044                             ARRAY_SIZE(argv),
2045                             argv);
2046 }
2047
2048
2049 int Message::GetLineNumber() const {
2050   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2051   ON_BAILOUT(isolate, "v8::Message::GetLineNumber()", return kNoLineNumberInfo);
2052   ENTER_V8(isolate);
2053   i::HandleScope scope(isolate);
2054
2055   EXCEPTION_PREAMBLE(isolate);
2056   i::Handle<i::Object> result;
2057   has_pending_exception = !CallV8HeapFunction(
2058       "GetLineNumber", Utils::OpenHandle(this)).ToHandle(&result);
2059   EXCEPTION_BAILOUT_CHECK(isolate, 0);
2060   return static_cast<int>(result->Number());
2061 }
2062
2063
2064 int Message::GetStartPosition() const {
2065   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2066   ENTER_V8(isolate);
2067   i::HandleScope scope(isolate);
2068   i::Handle<i::JSMessageObject> message =
2069       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2070   return message->start_position();
2071 }
2072
2073
2074 int Message::GetEndPosition() const {
2075   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2076   ENTER_V8(isolate);
2077   i::HandleScope scope(isolate);
2078   i::Handle<i::JSMessageObject> message =
2079       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2080   return message->end_position();
2081 }
2082
2083
2084 int Message::GetStartColumn() const {
2085   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2086   ON_BAILOUT(isolate, "v8::Message::GetStartColumn()", return kNoColumnInfo);
2087   ENTER_V8(isolate);
2088   i::HandleScope scope(isolate);
2089   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2090   EXCEPTION_PREAMBLE(isolate);
2091   i::Handle<i::Object> start_col_obj;
2092   has_pending_exception = !CallV8HeapFunction(
2093       "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2094   EXCEPTION_BAILOUT_CHECK(isolate, 0);
2095   return static_cast<int>(start_col_obj->Number());
2096 }
2097
2098
2099 int Message::GetEndColumn() const {
2100   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2101   ON_BAILOUT(isolate, "v8::Message::GetEndColumn()", return kNoColumnInfo);
2102   ENTER_V8(isolate);
2103   i::HandleScope scope(isolate);
2104   i::Handle<i::JSObject> data_obj = Utils::OpenHandle(this);
2105   EXCEPTION_PREAMBLE(isolate);
2106   i::Handle<i::Object> start_col_obj;
2107   has_pending_exception = !CallV8HeapFunction(
2108       "GetPositionInLine", data_obj).ToHandle(&start_col_obj);
2109   EXCEPTION_BAILOUT_CHECK(isolate, 0);
2110   i::Handle<i::JSMessageObject> message =
2111       i::Handle<i::JSMessageObject>::cast(data_obj);
2112   int start = message->start_position();
2113   int end = message->end_position();
2114   return static_cast<int>(start_col_obj->Number()) + (end - start);
2115 }
2116
2117
2118 bool Message::IsSharedCrossOrigin() const {
2119   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2120   ENTER_V8(isolate);
2121   i::HandleScope scope(isolate);
2122   i::Handle<i::JSMessageObject> message =
2123       i::Handle<i::JSMessageObject>::cast(Utils::OpenHandle(this));
2124   i::Handle<i::JSValue> script =
2125       i::Handle<i::JSValue>::cast(i::Handle<i::Object>(message->script(),
2126                                                        isolate));
2127   return i::Script::cast(script->value())->is_shared_cross_origin();
2128 }
2129
2130
2131 Local<String> Message::GetSourceLine() const {
2132   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2133   ON_BAILOUT(isolate, "v8::Message::GetSourceLine()", return Local<String>());
2134   ENTER_V8(isolate);
2135   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2136   EXCEPTION_PREAMBLE(isolate);
2137   i::Handle<i::Object> result;
2138   has_pending_exception = !CallV8HeapFunction(
2139       "GetSourceLine", Utils::OpenHandle(this)).ToHandle(&result);
2140   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::String>());
2141   if (result->IsString()) {
2142     return scope.Escape(Utils::ToLocal(i::Handle<i::String>::cast(result)));
2143   } else {
2144     return Local<String>();
2145   }
2146 }
2147
2148
2149 void Message::PrintCurrentStackTrace(Isolate* isolate, FILE* out) {
2150   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2151   ENTER_V8(i_isolate);
2152   i_isolate->PrintCurrentStackTrace(out);
2153 }
2154
2155
2156 // --- S t a c k T r a c e ---
2157
2158 Local<StackFrame> StackTrace::GetFrame(uint32_t index) const {
2159   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2160   ENTER_V8(isolate);
2161   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2162   i::Handle<i::JSArray> self = Utils::OpenHandle(this);
2163   i::Handle<i::Object> obj =
2164       i::Object::GetElement(isolate, self, index).ToHandleChecked();
2165   i::Handle<i::JSObject> jsobj = i::Handle<i::JSObject>::cast(obj);
2166   return scope.Escape(Utils::StackFrameToLocal(jsobj));
2167 }
2168
2169
2170 int StackTrace::GetFrameCount() const {
2171   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2172   ENTER_V8(isolate);
2173   return i::Smi::cast(Utils::OpenHandle(this)->length())->value();
2174 }
2175
2176
2177 Local<Array> StackTrace::AsArray() {
2178   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
2179   ENTER_V8(isolate);
2180   return Utils::ToLocal(Utils::OpenHandle(this));
2181 }
2182
2183
2184 Local<StackTrace> StackTrace::CurrentStackTrace(
2185     Isolate* isolate,
2186     int frame_limit,
2187     StackTraceOptions options) {
2188   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
2189   ENTER_V8(i_isolate);
2190   // TODO(dcarney): remove when ScriptDebugServer is fixed.
2191   options = static_cast<StackTraceOptions>(
2192       static_cast<int>(options) | kExposeFramesAcrossSecurityOrigins);
2193   i::Handle<i::JSArray> stackTrace =
2194       i_isolate->CaptureCurrentStackTrace(frame_limit, options);
2195   return Utils::StackTraceToLocal(stackTrace);
2196 }
2197
2198
2199 // --- S t a c k F r a m e ---
2200
2201 static int getIntProperty(const StackFrame* f, const char* propertyName,
2202                           int defaultValue) {
2203   i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2204   ENTER_V8(isolate);
2205   i::HandleScope scope(isolate);
2206   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2207   i::Handle<i::Object> obj =
2208       i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2209   return obj->IsSmi() ? i::Smi::cast(*obj)->value() : defaultValue;
2210 }
2211
2212
2213 int StackFrame::GetLineNumber() const {
2214   return getIntProperty(this, "lineNumber", Message::kNoLineNumberInfo);
2215 }
2216
2217
2218 int StackFrame::GetColumn() const {
2219   return getIntProperty(this, "column", Message::kNoColumnInfo);
2220 }
2221
2222
2223 int StackFrame::GetScriptId() const {
2224   return getIntProperty(this, "scriptId", Message::kNoScriptIdInfo);
2225 }
2226
2227
2228 static Local<String> getStringProperty(const StackFrame* f,
2229                                        const char* propertyName) {
2230   i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2231   ENTER_V8(isolate);
2232   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
2233   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2234   i::Handle<i::Object> obj =
2235       i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2236   return obj->IsString()
2237              ? scope.Escape(Local<String>::Cast(Utils::ToLocal(obj)))
2238              : Local<String>();
2239 }
2240
2241
2242 Local<String> StackFrame::GetScriptName() const {
2243   return getStringProperty(this, "scriptName");
2244 }
2245
2246
2247 Local<String> StackFrame::GetScriptNameOrSourceURL() const {
2248   return getStringProperty(this, "scriptNameOrSourceURL");
2249 }
2250
2251
2252 Local<String> StackFrame::GetFunctionName() const {
2253   return getStringProperty(this, "functionName");
2254 }
2255
2256
2257 static bool getBoolProperty(const StackFrame* f, const char* propertyName) {
2258   i::Isolate* isolate = Utils::OpenHandle(f)->GetIsolate();
2259   ENTER_V8(isolate);
2260   i::HandleScope scope(isolate);
2261   i::Handle<i::JSObject> self = Utils::OpenHandle(f);
2262   i::Handle<i::Object> obj =
2263       i::Object::GetProperty(isolate, self, propertyName).ToHandleChecked();
2264   return obj->IsTrue();
2265 }
2266
2267 bool StackFrame::IsEval() const { return getBoolProperty(this, "isEval"); }
2268
2269
2270 bool StackFrame::IsConstructor() const {
2271   return getBoolProperty(this, "isConstructor");
2272 }
2273
2274
2275 // --- J S O N ---
2276
2277 Local<Value> JSON::Parse(Local<String> json_string) {
2278   i::Handle<i::String> string = Utils::OpenHandle(*json_string);
2279   i::Isolate* isolate = string->GetIsolate();
2280   EnsureInitializedForIsolate(isolate, "v8::JSON::Parse");
2281   ENTER_V8(isolate);
2282   i::HandleScope scope(isolate);
2283   i::Handle<i::String> source = i::String::Flatten(string);
2284   EXCEPTION_PREAMBLE(isolate);
2285   i::MaybeHandle<i::Object> maybe_result =
2286       source->IsSeqOneByteString() ? i::JsonParser<true>::Parse(source)
2287                                    : i::JsonParser<false>::Parse(source);
2288   i::Handle<i::Object> result;
2289   has_pending_exception = !maybe_result.ToHandle(&result);
2290   EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
2291   return Utils::ToLocal(
2292       i::Handle<i::Object>::cast(scope.CloseAndEscape(result)));
2293 }
2294
2295
2296 // --- D a t a ---
2297
2298 bool Value::FullIsUndefined() const {
2299   bool result = Utils::OpenHandle(this)->IsUndefined();
2300   DCHECK_EQ(result, QuickIsUndefined());
2301   return result;
2302 }
2303
2304
2305 bool Value::FullIsNull() const {
2306   bool result = Utils::OpenHandle(this)->IsNull();
2307   DCHECK_EQ(result, QuickIsNull());
2308   return result;
2309 }
2310
2311
2312 bool Value::IsTrue() const {
2313   return Utils::OpenHandle(this)->IsTrue();
2314 }
2315
2316
2317 bool Value::IsFalse() const {
2318   return Utils::OpenHandle(this)->IsFalse();
2319 }
2320
2321
2322 bool Value::IsFunction() const {
2323   return Utils::OpenHandle(this)->IsJSFunction();
2324 }
2325
2326
2327 bool Value::FullIsString() const {
2328   bool result = Utils::OpenHandle(this)->IsString();
2329   DCHECK_EQ(result, QuickIsString());
2330   return result;
2331 }
2332
2333
2334 bool Value::IsSymbol() const {
2335   return Utils::OpenHandle(this)->IsSymbol();
2336 }
2337
2338
2339 bool Value::IsArray() const {
2340   return Utils::OpenHandle(this)->IsJSArray();
2341 }
2342
2343
2344 bool Value::IsArrayBuffer() const {
2345   return Utils::OpenHandle(this)->IsJSArrayBuffer();
2346 }
2347
2348
2349 bool Value::IsArrayBufferView() const {
2350   return Utils::OpenHandle(this)->IsJSArrayBufferView();
2351 }
2352
2353
2354 bool Value::IsTypedArray() const {
2355   return Utils::OpenHandle(this)->IsJSTypedArray();
2356 }
2357
2358
2359 #define VALUE_IS_TYPED_ARRAY(Type, typeName, TYPE, ctype, size)            \
2360   bool Value::Is##Type##Array() const {                                    \
2361     i::Handle<i::Object> obj = Utils::OpenHandle(this);                    \
2362     return obj->IsJSTypedArray() &&                                        \
2363            i::JSTypedArray::cast(*obj)->type() == kExternal##Type##Array;  \
2364   }
2365
2366 TYPED_ARRAYS(VALUE_IS_TYPED_ARRAY)
2367
2368 #undef VALUE_IS_TYPED_ARRAY
2369
2370
2371 bool Value::IsDataView() const {
2372   return Utils::OpenHandle(this)->IsJSDataView();
2373 }
2374
2375
2376 bool Value::IsObject() const {
2377   return Utils::OpenHandle(this)->IsJSObject();
2378 }
2379
2380
2381 bool Value::IsNumber() const {
2382   return Utils::OpenHandle(this)->IsNumber();
2383 }
2384
2385
2386 bool Value::IsBoolean() const {
2387   return Utils::OpenHandle(this)->IsBoolean();
2388 }
2389
2390
2391 bool Value::IsExternal() const {
2392   return Utils::OpenHandle(this)->IsExternal();
2393 }
2394
2395
2396 bool Value::IsInt32() const {
2397   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2398   if (obj->IsSmi()) return true;
2399   if (obj->IsNumber()) {
2400     return i::IsInt32Double(obj->Number());
2401   }
2402   return false;
2403 }
2404
2405
2406 bool Value::IsUint32() const {
2407   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2408   if (obj->IsSmi()) return i::Smi::cast(*obj)->value() >= 0;
2409   if (obj->IsNumber()) {
2410     double value = obj->Number();
2411     return !i::IsMinusZero(value) &&
2412         value >= 0 &&
2413         value <= i::kMaxUInt32 &&
2414         value == i::FastUI2D(i::FastD2UI(value));
2415   }
2416   return false;
2417 }
2418
2419
2420 bool Value::IsDate() const {
2421   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2422   if (!obj->IsHeapObject()) return false;
2423   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2424   return obj->HasSpecificClassOf(isolate->heap()->Date_string());
2425 }
2426
2427
2428 bool Value::IsStringObject() const {
2429   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2430   if (!obj->IsHeapObject()) return false;
2431   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2432   return obj->HasSpecificClassOf(isolate->heap()->String_string());
2433 }
2434
2435
2436 bool Value::IsSymbolObject() const {
2437   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2438   if (!obj->IsHeapObject()) return false;
2439   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2440   return obj->HasSpecificClassOf(isolate->heap()->Symbol_string());
2441 }
2442
2443
2444 bool Value::IsNumberObject() const {
2445   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2446   if (!obj->IsHeapObject()) return false;
2447   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2448   return obj->HasSpecificClassOf(isolate->heap()->Number_string());
2449 }
2450
2451
2452 static bool CheckConstructor(i::Isolate* isolate,
2453                              i::Handle<i::JSObject> obj,
2454                              const char* class_name) {
2455   i::Handle<i::Object> constr(obj->map()->constructor(), isolate);
2456   if (!constr->IsJSFunction()) return false;
2457   i::Handle<i::JSFunction> func = i::Handle<i::JSFunction>::cast(constr);
2458   return func->shared()->native() && constr.is_identical_to(
2459       i::Object::GetProperty(isolate,
2460                              isolate->js_builtins_object(),
2461                              class_name).ToHandleChecked());
2462 }
2463
2464
2465 bool Value::IsNativeError() const {
2466   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2467   if (obj->IsJSObject()) {
2468     i::Handle<i::JSObject> js_obj(i::JSObject::cast(*obj));
2469     i::Isolate* isolate = js_obj->GetIsolate();
2470     return CheckConstructor(isolate, js_obj, "$Error") ||
2471         CheckConstructor(isolate, js_obj, "$EvalError") ||
2472         CheckConstructor(isolate, js_obj, "$RangeError") ||
2473         CheckConstructor(isolate, js_obj, "$ReferenceError") ||
2474         CheckConstructor(isolate, js_obj, "$SyntaxError") ||
2475         CheckConstructor(isolate, js_obj, "$TypeError") ||
2476         CheckConstructor(isolate, js_obj, "$URIError");
2477   } else {
2478     return false;
2479   }
2480 }
2481
2482
2483 bool Value::IsBooleanObject() const {
2484   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2485   if (!obj->IsHeapObject()) return false;
2486   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2487   return obj->HasSpecificClassOf(isolate->heap()->Boolean_string());
2488 }
2489
2490
2491 bool Value::IsRegExp() const {
2492   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2493   return obj->IsJSRegExp();
2494 }
2495
2496
2497 Local<String> Value::ToString() const {
2498   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2499   i::Handle<i::Object> str;
2500   if (obj->IsString()) {
2501     str = obj;
2502   } else {
2503     i::Isolate* isolate = i::Isolate::Current();
2504     LOG_API(isolate, "ToString");
2505     ENTER_V8(isolate);
2506     EXCEPTION_PREAMBLE(isolate);
2507     has_pending_exception = !i::Execution::ToString(
2508         isolate, obj).ToHandle(&str);
2509     EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2510   }
2511   return ToApiHandle<String>(str);
2512 }
2513
2514
2515 Local<String> Value::ToDetailString() const {
2516   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2517   i::Handle<i::Object> str;
2518   if (obj->IsString()) {
2519     str = obj;
2520   } else {
2521     i::Isolate* isolate = i::Isolate::Current();
2522     LOG_API(isolate, "ToDetailString");
2523     ENTER_V8(isolate);
2524     EXCEPTION_PREAMBLE(isolate);
2525     has_pending_exception = !i::Execution::ToDetailString(
2526         isolate, obj).ToHandle(&str);
2527     EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
2528   }
2529   return ToApiHandle<String>(str);
2530 }
2531
2532
2533 Local<v8::Object> Value::ToObject() const {
2534   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2535   i::Handle<i::Object> val;
2536   if (obj->IsJSObject()) {
2537     val = obj;
2538   } else {
2539     i::Isolate* isolate = i::Isolate::Current();
2540     LOG_API(isolate, "ToObject");
2541     ENTER_V8(isolate);
2542     EXCEPTION_PREAMBLE(isolate);
2543     has_pending_exception = !i::Execution::ToObject(
2544         isolate, obj).ToHandle(&val);
2545     EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
2546   }
2547   return ToApiHandle<Object>(val);
2548 }
2549
2550
2551 Local<Boolean> Value::ToBoolean() const {
2552   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2553   if (obj->IsBoolean()) {
2554     return ToApiHandle<Boolean>(obj);
2555   } else {
2556     i::Isolate* isolate = i::Isolate::Current();
2557     LOG_API(isolate, "ToBoolean");
2558     ENTER_V8(isolate);
2559     i::Handle<i::Object> val =
2560         isolate->factory()->ToBoolean(obj->BooleanValue());
2561     return ToApiHandle<Boolean>(val);
2562   }
2563 }
2564
2565
2566 Local<Number> Value::ToNumber() const {
2567   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2568   i::Handle<i::Object> num;
2569   if (obj->IsNumber()) {
2570     num = obj;
2571   } else {
2572     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2573     LOG_API(isolate, "ToNumber");
2574     ENTER_V8(isolate);
2575     EXCEPTION_PREAMBLE(isolate);
2576     has_pending_exception = !i::Execution::ToNumber(
2577         isolate, obj).ToHandle(&num);
2578     EXCEPTION_BAILOUT_CHECK(isolate, Local<Number>());
2579   }
2580   return ToApiHandle<Number>(num);
2581 }
2582
2583
2584 Local<Integer> Value::ToInteger() const {
2585   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2586   i::Handle<i::Object> num;
2587   if (obj->IsSmi()) {
2588     num = obj;
2589   } else {
2590     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2591     LOG_API(isolate, "ToInteger");
2592     ENTER_V8(isolate);
2593     EXCEPTION_PREAMBLE(isolate);
2594     has_pending_exception = !i::Execution::ToInteger(
2595         isolate, obj).ToHandle(&num);
2596     EXCEPTION_BAILOUT_CHECK(isolate, Local<Integer>());
2597   }
2598   return ToApiHandle<Integer>(num);
2599 }
2600
2601
2602 void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) {
2603   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
2604   Utils::ApiCheck(isolate != NULL &&
2605                   isolate->IsInitialized() &&
2606                   !isolate->IsDead(),
2607                   "v8::internal::Internals::CheckInitialized()",
2608                   "Isolate is not initialized or V8 has died");
2609 }
2610
2611
2612 void External::CheckCast(v8::Value* that) {
2613   Utils::ApiCheck(Utils::OpenHandle(that)->IsExternal(),
2614                   "v8::External::Cast()",
2615                   "Could not convert to external");
2616 }
2617
2618
2619 void v8::Object::CheckCast(Value* that) {
2620   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2621   Utils::ApiCheck(obj->IsJSObject(),
2622                   "v8::Object::Cast()",
2623                   "Could not convert to object");
2624 }
2625
2626
2627 void v8::Function::CheckCast(Value* that) {
2628   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2629   Utils::ApiCheck(obj->IsJSFunction(),
2630                   "v8::Function::Cast()",
2631                   "Could not convert to function");
2632 }
2633
2634
2635 void v8::String::CheckCast(v8::Value* that) {
2636   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2637   Utils::ApiCheck(obj->IsString(),
2638                   "v8::String::Cast()",
2639                   "Could not convert to string");
2640 }
2641
2642
2643 void v8::Symbol::CheckCast(v8::Value* that) {
2644   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2645   Utils::ApiCheck(obj->IsSymbol(),
2646                   "v8::Symbol::Cast()",
2647                   "Could not convert to symbol");
2648 }
2649
2650
2651 void v8::Number::CheckCast(v8::Value* that) {
2652   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2653   Utils::ApiCheck(obj->IsNumber(),
2654                   "v8::Number::Cast()",
2655                   "Could not convert to number");
2656 }
2657
2658
2659 void v8::Integer::CheckCast(v8::Value* that) {
2660   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2661   Utils::ApiCheck(obj->IsNumber(),
2662                   "v8::Integer::Cast()",
2663                   "Could not convert to number");
2664 }
2665
2666
2667 void v8::Array::CheckCast(Value* that) {
2668   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2669   Utils::ApiCheck(obj->IsJSArray(),
2670                   "v8::Array::Cast()",
2671                   "Could not convert to array");
2672 }
2673
2674
2675 void v8::Promise::CheckCast(Value* that) {
2676   Utils::ApiCheck(that->IsPromise(),
2677                   "v8::Promise::Cast()",
2678                   "Could not convert to promise");
2679 }
2680
2681
2682 void v8::Promise::Resolver::CheckCast(Value* that) {
2683   Utils::ApiCheck(that->IsPromise(),
2684                   "v8::Promise::Resolver::Cast()",
2685                   "Could not convert to promise resolver");
2686 }
2687
2688
2689 void v8::ArrayBuffer::CheckCast(Value* that) {
2690   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2691   Utils::ApiCheck(obj->IsJSArrayBuffer(),
2692                   "v8::ArrayBuffer::Cast()",
2693                   "Could not convert to ArrayBuffer");
2694 }
2695
2696
2697 void v8::ArrayBufferView::CheckCast(Value* that) {
2698   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2699   Utils::ApiCheck(obj->IsJSArrayBufferView(),
2700                   "v8::ArrayBufferView::Cast()",
2701                   "Could not convert to ArrayBufferView");
2702 }
2703
2704
2705 void v8::TypedArray::CheckCast(Value* that) {
2706   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2707   Utils::ApiCheck(obj->IsJSTypedArray(),
2708                   "v8::TypedArray::Cast()",
2709                   "Could not convert to TypedArray");
2710 }
2711
2712
2713 #define CHECK_TYPED_ARRAY_CAST(Type, typeName, TYPE, ctype, size)             \
2714   void v8::Type##Array::CheckCast(Value* that) {                              \
2715     i::Handle<i::Object> obj = Utils::OpenHandle(that);                       \
2716     Utils::ApiCheck(obj->IsJSTypedArray() &&                                  \
2717                     i::JSTypedArray::cast(*obj)->type() ==                    \
2718                         kExternal##Type##Array,                               \
2719                     "v8::" #Type "Array::Cast()",                             \
2720                     "Could not convert to " #Type "Array");                   \
2721   }
2722
2723
2724 TYPED_ARRAYS(CHECK_TYPED_ARRAY_CAST)
2725
2726 #undef CHECK_TYPED_ARRAY_CAST
2727
2728
2729 void v8::DataView::CheckCast(Value* that) {
2730   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2731   Utils::ApiCheck(obj->IsJSDataView(),
2732                   "v8::DataView::Cast()",
2733                   "Could not convert to DataView");
2734 }
2735
2736
2737 void v8::Date::CheckCast(v8::Value* that) {
2738   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2739   i::Isolate* isolate = NULL;
2740   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2741   Utils::ApiCheck(isolate != NULL &&
2742                   obj->HasSpecificClassOf(isolate->heap()->Date_string()),
2743                   "v8::Date::Cast()",
2744                   "Could not convert to date");
2745 }
2746
2747
2748 void v8::StringObject::CheckCast(v8::Value* that) {
2749   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2750   i::Isolate* isolate = NULL;
2751   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2752   Utils::ApiCheck(isolate != NULL &&
2753                   obj->HasSpecificClassOf(isolate->heap()->String_string()),
2754                   "v8::StringObject::Cast()",
2755                   "Could not convert to StringObject");
2756 }
2757
2758
2759 void v8::SymbolObject::CheckCast(v8::Value* that) {
2760   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2761   i::Isolate* isolate = NULL;
2762   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2763   Utils::ApiCheck(isolate != NULL &&
2764                   obj->HasSpecificClassOf(isolate->heap()->Symbol_string()),
2765                   "v8::SymbolObject::Cast()",
2766                   "Could not convert to SymbolObject");
2767 }
2768
2769
2770 void v8::NumberObject::CheckCast(v8::Value* that) {
2771   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2772   i::Isolate* isolate = NULL;
2773   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2774   Utils::ApiCheck(isolate != NULL &&
2775                   obj->HasSpecificClassOf(isolate->heap()->Number_string()),
2776                   "v8::NumberObject::Cast()",
2777                   "Could not convert to NumberObject");
2778 }
2779
2780
2781 void v8::BooleanObject::CheckCast(v8::Value* that) {
2782   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2783   i::Isolate* isolate = NULL;
2784   if (obj->IsHeapObject()) isolate = i::HeapObject::cast(*obj)->GetIsolate();
2785   Utils::ApiCheck(isolate != NULL &&
2786                   obj->HasSpecificClassOf(isolate->heap()->Boolean_string()),
2787                   "v8::BooleanObject::Cast()",
2788                   "Could not convert to BooleanObject");
2789 }
2790
2791
2792 void v8::RegExp::CheckCast(v8::Value* that) {
2793   i::Handle<i::Object> obj = Utils::OpenHandle(that);
2794   Utils::ApiCheck(obj->IsJSRegExp(),
2795                   "v8::RegExp::Cast()",
2796                   "Could not convert to regular expression");
2797 }
2798
2799
2800 bool Value::BooleanValue() const {
2801   return Utils::OpenHandle(this)->BooleanValue();
2802 }
2803
2804
2805 double Value::NumberValue() const {
2806   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2807   i::Handle<i::Object> num;
2808   if (obj->IsNumber()) {
2809     num = obj;
2810   } else {
2811     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2812     LOG_API(isolate, "NumberValue");
2813     ENTER_V8(isolate);
2814     EXCEPTION_PREAMBLE(isolate);
2815     has_pending_exception = !i::Execution::ToNumber(
2816         isolate, obj).ToHandle(&num);
2817     EXCEPTION_BAILOUT_CHECK(isolate, base::OS::nan_value());
2818   }
2819   return num->Number();
2820 }
2821
2822
2823 int64_t Value::IntegerValue() const {
2824   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2825   i::Handle<i::Object> num;
2826   if (obj->IsNumber()) {
2827     num = obj;
2828   } else {
2829     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2830     LOG_API(isolate, "IntegerValue");
2831     ENTER_V8(isolate);
2832     EXCEPTION_PREAMBLE(isolate);
2833     has_pending_exception = !i::Execution::ToInteger(
2834         isolate, obj).ToHandle(&num);
2835     EXCEPTION_BAILOUT_CHECK(isolate, 0);
2836   }
2837   if (num->IsSmi()) {
2838     return i::Smi::cast(*num)->value();
2839   } else {
2840     return static_cast<int64_t>(num->Number());
2841   }
2842 }
2843
2844
2845 Local<Int32> Value::ToInt32() const {
2846   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2847   i::Handle<i::Object> num;
2848   if (obj->IsSmi()) {
2849     num = obj;
2850   } else {
2851     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2852     LOG_API(isolate, "ToInt32");
2853     ENTER_V8(isolate);
2854     EXCEPTION_PREAMBLE(isolate);
2855     has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2856     EXCEPTION_BAILOUT_CHECK(isolate, Local<Int32>());
2857   }
2858   return ToApiHandle<Int32>(num);
2859 }
2860
2861
2862 Local<Uint32> Value::ToUint32() const {
2863   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2864   i::Handle<i::Object> num;
2865   if (obj->IsSmi()) {
2866     num = obj;
2867   } else {
2868     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2869     LOG_API(isolate, "ToUInt32");
2870     ENTER_V8(isolate);
2871     EXCEPTION_PREAMBLE(isolate);
2872     has_pending_exception = !i::Execution::ToUint32(
2873         isolate, obj).ToHandle(&num);
2874     EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2875   }
2876   return ToApiHandle<Uint32>(num);
2877 }
2878
2879
2880 Local<Uint32> Value::ToArrayIndex() const {
2881   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2882   if (obj->IsSmi()) {
2883     if (i::Smi::cast(*obj)->value() >= 0) return Utils::Uint32ToLocal(obj);
2884     return Local<Uint32>();
2885   }
2886   i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2887   LOG_API(isolate, "ToArrayIndex");
2888   ENTER_V8(isolate);
2889   EXCEPTION_PREAMBLE(isolate);
2890   i::Handle<i::Object> string_obj;
2891   has_pending_exception = !i::Execution::ToString(
2892       isolate, obj).ToHandle(&string_obj);
2893   EXCEPTION_BAILOUT_CHECK(isolate, Local<Uint32>());
2894   i::Handle<i::String> str = i::Handle<i::String>::cast(string_obj);
2895   uint32_t index;
2896   if (str->AsArrayIndex(&index)) {
2897     i::Handle<i::Object> value;
2898     if (index <= static_cast<uint32_t>(i::Smi::kMaxValue)) {
2899       value = i::Handle<i::Object>(i::Smi::FromInt(index), isolate);
2900     } else {
2901       value = isolate->factory()->NewNumber(index);
2902     }
2903     return Utils::Uint32ToLocal(value);
2904   }
2905   return Local<Uint32>();
2906 }
2907
2908
2909 int32_t Value::Int32Value() const {
2910   i::Handle<i::Object> obj = Utils::OpenHandle(this);
2911   if (obj->IsSmi()) {
2912     return i::Smi::cast(*obj)->value();
2913   } else {
2914     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
2915     LOG_API(isolate, "Int32Value (slow)");
2916     ENTER_V8(isolate);
2917     EXCEPTION_PREAMBLE(isolate);
2918     i::Handle<i::Object> num;
2919     has_pending_exception = !i::Execution::ToInt32(isolate, obj).ToHandle(&num);
2920     EXCEPTION_BAILOUT_CHECK(isolate, 0);
2921     if (num->IsSmi()) {
2922       return i::Smi::cast(*num)->value();
2923     } else {
2924       return static_cast<int32_t>(num->Number());
2925     }
2926   }
2927 }
2928
2929
2930 bool Value::Equals(Handle<Value> that) const {
2931   i::Isolate* isolate = i::Isolate::Current();
2932   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2933   if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2934                        "v8::Value::Equals()",
2935                        "Reading from empty handle")) {
2936     return false;
2937   }
2938   LOG_API(isolate, "Equals");
2939   ENTER_V8(isolate);
2940   i::Handle<i::Object> other = Utils::OpenHandle(*that);
2941   // If both obj and other are JSObjects, we'd better compare by identity
2942   // immediately when going into JS builtin.  The reason is Invoke
2943   // would overwrite global object receiver with global proxy.
2944   if (obj->IsJSObject() && other->IsJSObject()) {
2945     return *obj == *other;
2946   }
2947   i::Handle<i::Object> args[] = { other };
2948   EXCEPTION_PREAMBLE(isolate);
2949   i::Handle<i::Object> result;
2950   has_pending_exception = !CallV8HeapFunction(
2951       "EQUALS", obj, ARRAY_SIZE(args), args).ToHandle(&result);
2952   EXCEPTION_BAILOUT_CHECK(isolate, false);
2953   return *result == i::Smi::FromInt(i::EQUAL);
2954 }
2955
2956
2957 bool Value::StrictEquals(Handle<Value> that) const {
2958   i::Isolate* isolate = i::Isolate::Current();
2959   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2960   if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2961                        "v8::Value::StrictEquals()",
2962                        "Reading from empty handle")) {
2963     return false;
2964   }
2965   LOG_API(isolate, "StrictEquals");
2966   i::Handle<i::Object> other = Utils::OpenHandle(*that);
2967   // Must check HeapNumber first, since NaN !== NaN.
2968   if (obj->IsHeapNumber()) {
2969     if (!other->IsNumber()) return false;
2970     double x = obj->Number();
2971     double y = other->Number();
2972     // Must check explicitly for NaN:s on Windows, but -0 works fine.
2973     return x == y && !std::isnan(x) && !std::isnan(y);
2974   } else if (*obj == *other) {  // Also covers Booleans.
2975     return true;
2976   } else if (obj->IsSmi()) {
2977     return other->IsNumber() && obj->Number() == other->Number();
2978   } else if (obj->IsString()) {
2979     return other->IsString() &&
2980         i::String::Equals(i::Handle<i::String>::cast(obj),
2981                           i::Handle<i::String>::cast(other));
2982   } else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
2983     return other->IsUndefined() || other->IsUndetectableObject();
2984   } else {
2985     return false;
2986   }
2987 }
2988
2989
2990 bool Value::SameValue(Handle<Value> that) const {
2991   i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
2992   if (!Utils::ApiCheck(!obj.is_null() && !that.IsEmpty(),
2993                        "v8::Value::SameValue()",
2994                        "Reading from empty handle")) {
2995     return false;
2996   }
2997   i::Handle<i::Object> other = Utils::OpenHandle(*that);
2998   return obj->SameValue(*other);
2999 }
3000
3001
3002 uint32_t Value::Uint32Value() const {
3003   i::Handle<i::Object> obj = Utils::OpenHandle(this);
3004   if (obj->IsSmi()) {
3005     return i::Smi::cast(*obj)->value();
3006   } else {
3007     i::Isolate* isolate = i::HeapObject::cast(*obj)->GetIsolate();
3008     LOG_API(isolate, "Uint32Value");
3009     ENTER_V8(isolate);
3010     EXCEPTION_PREAMBLE(isolate);
3011     i::Handle<i::Object> num;
3012     has_pending_exception = !i::Execution::ToUint32(
3013         isolate, obj).ToHandle(&num);
3014     EXCEPTION_BAILOUT_CHECK(isolate, 0);
3015     if (num->IsSmi()) {
3016       return i::Smi::cast(*num)->value();
3017     } else {
3018       return static_cast<uint32_t>(num->Number());
3019     }
3020   }
3021 }
3022
3023
3024 bool v8::Object::Set(v8::Handle<Value> key, v8::Handle<Value> value) {
3025   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3026   ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3027   ENTER_V8(isolate);
3028   i::HandleScope scope(isolate);
3029   i::Handle<i::Object> self = Utils::OpenHandle(this);
3030   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3031   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3032   EXCEPTION_PREAMBLE(isolate);
3033   has_pending_exception =
3034       i::Runtime::SetObjectProperty(isolate, self, key_obj, value_obj,
3035                                     i::SLOPPY).is_null();
3036   EXCEPTION_BAILOUT_CHECK(isolate, false);
3037   return true;
3038 }
3039
3040
3041 bool v8::Object::Set(uint32_t index, v8::Handle<Value> value) {
3042   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3043   ON_BAILOUT(isolate, "v8::Object::Set()", return false);
3044   ENTER_V8(isolate);
3045   i::HandleScope scope(isolate);
3046   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3047   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3048   EXCEPTION_PREAMBLE(isolate);
3049   has_pending_exception = i::JSObject::SetElement(
3050       self, index, value_obj, NONE, i::SLOPPY).is_null();
3051   EXCEPTION_BAILOUT_CHECK(isolate, false);
3052   return true;
3053 }
3054
3055
3056 bool v8::Object::ForceSet(v8::Handle<Value> key,
3057                           v8::Handle<Value> value,
3058                           v8::PropertyAttribute attribs) {
3059   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3060   ON_BAILOUT(isolate, "v8::Object::ForceSet()", return false);
3061   ENTER_V8(isolate);
3062   i::HandleScope scope(isolate);
3063   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3064   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3065   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3066   EXCEPTION_PREAMBLE(isolate);
3067   has_pending_exception = i::Runtime::DefineObjectProperty(
3068       self,
3069       key_obj,
3070       value_obj,
3071       static_cast<PropertyAttributes>(attribs)).is_null();
3072   EXCEPTION_BAILOUT_CHECK(isolate, false);
3073   return true;
3074 }
3075
3076
3077 bool v8::Object::SetPrivate(v8::Handle<Private> key, v8::Handle<Value> value) {
3078   return ForceSet(v8::Handle<Value>(reinterpret_cast<Value*>(*key)),
3079                   value, DontEnum);
3080 }
3081
3082
3083 bool v8::Object::ForceDelete(v8::Handle<Value> key) {
3084   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3085   ON_BAILOUT(isolate, "v8::Object::ForceDelete()", return false);
3086   ENTER_V8(isolate);
3087   i::HandleScope scope(isolate);
3088   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3089   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3090
3091   // When deleting a property on the global object using ForceDelete
3092   // deoptimize all functions as optimized code does not check for the hole
3093   // value with DontDelete properties.  We have to deoptimize all contexts
3094   // because of possible cross-context inlined functions.
3095   if (self->IsJSGlobalProxy() || self->IsGlobalObject()) {
3096     i::Deoptimizer::DeoptimizeAll(isolate);
3097   }
3098
3099   EXCEPTION_PREAMBLE(isolate);
3100   i::Handle<i::Object> obj;
3101   has_pending_exception = !i::Runtime::DeleteObjectProperty(
3102       isolate, self, key_obj, i::JSReceiver::FORCE_DELETION).ToHandle(&obj);
3103   EXCEPTION_BAILOUT_CHECK(isolate, false);
3104   return obj->IsTrue();
3105 }
3106
3107
3108 Local<Value> v8::Object::Get(v8::Handle<Value> key) {
3109   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3110   ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3111   ENTER_V8(isolate);
3112   i::Handle<i::Object> self = Utils::OpenHandle(this);
3113   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3114   EXCEPTION_PREAMBLE(isolate);
3115   i::Handle<i::Object> result;
3116   has_pending_exception =
3117       !i::Runtime::GetObjectProperty(isolate, self, key_obj).ToHandle(&result);
3118   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3119   return Utils::ToLocal(result);
3120 }
3121
3122
3123 Local<Value> v8::Object::Get(uint32_t index) {
3124   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3125   ON_BAILOUT(isolate, "v8::Object::Get()", return Local<v8::Value>());
3126   ENTER_V8(isolate);
3127   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3128   EXCEPTION_PREAMBLE(isolate);
3129   i::Handle<i::Object> result;
3130   has_pending_exception =
3131       !i::Object::GetElement(isolate, self, index).ToHandle(&result);
3132   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3133   return Utils::ToLocal(result);
3134 }
3135
3136
3137 Local<Value> v8::Object::GetPrivate(v8::Handle<Private> key) {
3138   return Get(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3139 }
3140
3141
3142 PropertyAttribute v8::Object::GetPropertyAttributes(v8::Handle<Value> key) {
3143   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3144   ON_BAILOUT(isolate, "v8::Object::GetPropertyAttributes()",
3145              return static_cast<PropertyAttribute>(NONE));
3146   ENTER_V8(isolate);
3147   i::HandleScope scope(isolate);
3148   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3149   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3150   if (!key_obj->IsName()) {
3151     EXCEPTION_PREAMBLE(isolate);
3152     has_pending_exception = !i::Execution::ToString(
3153         isolate, key_obj).ToHandle(&key_obj);
3154     EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3155   }
3156   i::Handle<i::Name> key_name = i::Handle<i::Name>::cast(key_obj);
3157   EXCEPTION_PREAMBLE(isolate);
3158   Maybe<PropertyAttributes> result =
3159       i::JSReceiver::GetPropertyAttributes(self, key_name);
3160   has_pending_exception = !result.has_value;
3161   EXCEPTION_BAILOUT_CHECK(isolate, static_cast<PropertyAttribute>(NONE));
3162   if (result.value == ABSENT) return static_cast<PropertyAttribute>(NONE);
3163   return static_cast<PropertyAttribute>(result.value);
3164 }
3165
3166
3167 Local<Value> v8::Object::GetOwnPropertyDescriptor(Local<String> key) {
3168   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3169   ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyDescriptor()",
3170              return Local<Value>());
3171   ENTER_V8(isolate);
3172   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3173   i::Handle<i::Name> key_name = Utils::OpenHandle(*key);
3174   i::Handle<i::Object> args[] = { obj, key_name };
3175   EXCEPTION_PREAMBLE(isolate);
3176   i::Handle<i::Object> result;
3177   has_pending_exception = !CallV8HeapFunction(
3178       "ObjectGetOwnPropertyDescriptor",
3179       isolate->factory()->undefined_value(),
3180       ARRAY_SIZE(args),
3181       args).ToHandle(&result);
3182   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3183   return Utils::ToLocal(result);
3184 }
3185
3186
3187 Local<Value> v8::Object::GetPrototype() {
3188   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3189   ON_BAILOUT(isolate, "v8::Object::GetPrototype()", return Local<v8::Value>());
3190   ENTER_V8(isolate);
3191   i::Handle<i::Object> self = Utils::OpenHandle(this);
3192   i::PrototypeIterator iter(isolate, self);
3193   return Utils::ToLocal(i::PrototypeIterator::GetCurrent(iter));
3194 }
3195
3196
3197 bool v8::Object::SetPrototype(Handle<Value> value) {
3198   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3199   ON_BAILOUT(isolate, "v8::Object::SetPrototype()", return false);
3200   ENTER_V8(isolate);
3201   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3202   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3203   // We do not allow exceptions thrown while setting the prototype
3204   // to propagate outside.
3205   TryCatch try_catch;
3206   EXCEPTION_PREAMBLE(isolate);
3207   i::MaybeHandle<i::Object> result =
3208       i::JSObject::SetPrototype(self, value_obj, false);
3209   has_pending_exception = result.is_null();
3210   EXCEPTION_BAILOUT_CHECK(isolate, false);
3211   return true;
3212 }
3213
3214
3215 Local<Object> v8::Object::FindInstanceInPrototypeChain(
3216     v8::Handle<FunctionTemplate> tmpl) {
3217   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3218   ON_BAILOUT(isolate,
3219              "v8::Object::FindInstanceInPrototypeChain()",
3220              return Local<v8::Object>());
3221   ENTER_V8(isolate);
3222   i::PrototypeIterator iter(isolate, *Utils::OpenHandle(this),
3223                             i::PrototypeIterator::START_AT_RECEIVER);
3224   i::FunctionTemplateInfo* tmpl_info = *Utils::OpenHandle(*tmpl);
3225   while (!tmpl_info->IsTemplateFor(iter.GetCurrent())) {
3226     iter.Advance();
3227     if (iter.IsAtEnd()) {
3228       return Local<Object>();
3229     }
3230   }
3231   return Utils::ToLocal(
3232       i::handle(i::JSObject::cast(iter.GetCurrent()), isolate));
3233 }
3234
3235
3236 Local<Array> v8::Object::GetPropertyNames() {
3237   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3238   ON_BAILOUT(isolate, "v8::Object::GetPropertyNames()",
3239              return Local<v8::Array>());
3240   ENTER_V8(isolate);
3241   i::HandleScope scope(isolate);
3242   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3243   EXCEPTION_PREAMBLE(isolate);
3244   i::Handle<i::FixedArray> value;
3245   has_pending_exception = !i::JSReceiver::GetKeys(
3246       self, i::JSReceiver::INCLUDE_PROTOS).ToHandle(&value);
3247   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3248   // Because we use caching to speed up enumeration it is important
3249   // to never change the result of the basic enumeration function so
3250   // we clone the result.
3251   i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3252   i::Handle<i::JSArray> result =
3253       isolate->factory()->NewJSArrayWithElements(elms);
3254   return Utils::ToLocal(scope.CloseAndEscape(result));
3255 }
3256
3257
3258 Local<Array> v8::Object::GetOwnPropertyNames() {
3259   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3260   ON_BAILOUT(isolate, "v8::Object::GetOwnPropertyNames()",
3261              return Local<v8::Array>());
3262   ENTER_V8(isolate);
3263   i::HandleScope scope(isolate);
3264   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3265   EXCEPTION_PREAMBLE(isolate);
3266   i::Handle<i::FixedArray> value;
3267   has_pending_exception = !i::JSReceiver::GetKeys(
3268       self, i::JSReceiver::OWN_ONLY).ToHandle(&value);
3269   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Array>());
3270   // Because we use caching to speed up enumeration it is important
3271   // to never change the result of the basic enumeration function so
3272   // we clone the result.
3273   i::Handle<i::FixedArray> elms = isolate->factory()->CopyFixedArray(value);
3274   i::Handle<i::JSArray> result =
3275       isolate->factory()->NewJSArrayWithElements(elms);
3276   return Utils::ToLocal(scope.CloseAndEscape(result));
3277 }
3278
3279
3280 Local<String> v8::Object::ObjectProtoToString() {
3281   i::Isolate* i_isolate = Utils::OpenHandle(this)->GetIsolate();
3282   Isolate* isolate = reinterpret_cast<Isolate*>(i_isolate);
3283   ON_BAILOUT(i_isolate, "v8::Object::ObjectProtoToString()",
3284              return Local<v8::String>());
3285   ENTER_V8(i_isolate);
3286   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3287
3288   i::Handle<i::Object> name(self->class_name(), i_isolate);
3289
3290   // Native implementation of Object.prototype.toString (v8natives.js):
3291   //   var c = %_ClassOf(this);
3292   //   if (c === 'Arguments') c  = 'Object';
3293   //   return "[object " + c + "]";
3294
3295   if (!name->IsString()) {
3296     return v8::String::NewFromUtf8(isolate, "[object ]");
3297   } else {
3298     i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
3299     if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) {
3300       return v8::String::NewFromUtf8(isolate, "[object Object]");
3301     } else {
3302       const char* prefix = "[object ";
3303       Local<String> str = Utils::ToLocal(class_name);
3304       const char* postfix = "]";
3305
3306       int prefix_len = i::StrLength(prefix);
3307       int str_len = str->Utf8Length();
3308       int postfix_len = i::StrLength(postfix);
3309
3310       int buf_len = prefix_len + str_len + postfix_len;
3311       i::ScopedVector<char> buf(buf_len);
3312
3313       // Write prefix.
3314       char* ptr = buf.start();
3315       i::MemCopy(ptr, prefix, prefix_len * v8::internal::kCharSize);
3316       ptr += prefix_len;
3317
3318       // Write real content.
3319       str->WriteUtf8(ptr, str_len);
3320       ptr += str_len;
3321
3322       // Write postfix.
3323       i::MemCopy(ptr, postfix, postfix_len * v8::internal::kCharSize);
3324
3325       // Copy the buffer into a heap-allocated string and return it.
3326       Local<String> result = v8::String::NewFromUtf8(
3327           isolate, buf.start(), String::kNormalString, buf_len);
3328       return result;
3329     }
3330   }
3331 }
3332
3333
3334 Local<String> v8::Object::GetConstructorName() {
3335   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3336   ON_BAILOUT(isolate, "v8::Object::GetConstructorName()",
3337              return Local<v8::String>());
3338   ENTER_V8(isolate);
3339   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3340   i::Handle<i::String> name(self->constructor_name());
3341   return Utils::ToLocal(name);
3342 }
3343
3344
3345 bool v8::Object::Delete(v8::Handle<Value> key) {
3346   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3347   ON_BAILOUT(isolate, "v8::Object::Delete()", return false);
3348   ENTER_V8(isolate);
3349   i::HandleScope scope(isolate);
3350   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3351   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3352   EXCEPTION_PREAMBLE(isolate);
3353   i::Handle<i::Object> obj;
3354   has_pending_exception = !i::Runtime::DeleteObjectProperty(
3355       isolate, self, key_obj, i::JSReceiver::NORMAL_DELETION).ToHandle(&obj);
3356   EXCEPTION_BAILOUT_CHECK(isolate, false);
3357   return obj->IsTrue();
3358 }
3359
3360
3361 bool v8::Object::DeletePrivate(v8::Handle<Private> key) {
3362   return Delete(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3363 }
3364
3365
3366 bool v8::Object::Has(v8::Handle<Value> key) {
3367   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3368   ON_BAILOUT(isolate, "v8::Object::Has()", return false);
3369   ENTER_V8(isolate);
3370   i::Handle<i::JSReceiver> self = Utils::OpenHandle(this);
3371   i::Handle<i::Object> key_obj = Utils::OpenHandle(*key);
3372   EXCEPTION_PREAMBLE(isolate);
3373   i::Handle<i::Object> obj;
3374   has_pending_exception = !i::Runtime::HasObjectProperty(
3375       isolate, self, key_obj).ToHandle(&obj);
3376   EXCEPTION_BAILOUT_CHECK(isolate, false);
3377   return obj->IsTrue();
3378 }
3379
3380
3381 bool v8::Object::HasPrivate(v8::Handle<Private> key) {
3382   // TODO(rossberg): this should use HasOwnProperty, but we'd need to
3383   // generalise that to a (noy yet existant) Name argument first.
3384   return Has(v8::Handle<Value>(reinterpret_cast<Value*>(*key)));
3385 }
3386
3387
3388 bool v8::Object::Delete(uint32_t index) {
3389   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3390   ON_BAILOUT(isolate, "v8::Object::DeleteProperty()",
3391              return false);
3392   ENTER_V8(isolate);
3393   HandleScope scope(reinterpret_cast<Isolate*>(isolate));
3394   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3395
3396   EXCEPTION_PREAMBLE(isolate);
3397   i::Handle<i::Object> obj;
3398   has_pending_exception =
3399       !i::JSReceiver::DeleteElement(self, index).ToHandle(&obj);
3400   EXCEPTION_BAILOUT_CHECK(isolate, false);
3401   return obj->IsTrue();
3402 }
3403
3404
3405 bool v8::Object::Has(uint32_t index) {
3406   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3407   ON_BAILOUT(isolate, "v8::Object::HasProperty()", return false);
3408   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3409   EXCEPTION_PREAMBLE(isolate);
3410   Maybe<bool> maybe = i::JSReceiver::HasElement(self, index);
3411   has_pending_exception = !maybe.has_value;
3412   EXCEPTION_BAILOUT_CHECK(isolate, false);
3413   return maybe.value;
3414 }
3415
3416
3417 template<typename Setter, typename Getter, typename Data>
3418 static inline bool ObjectSetAccessor(Object* obj,
3419                                      Handle<String> name,
3420                                      Setter getter,
3421                                      Getter setter,
3422                                      Data data,
3423                                      AccessControl settings,
3424                                      PropertyAttribute attributes) {
3425   i::Isolate* isolate = Utils::OpenHandle(obj)->GetIsolate();
3426   ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false);
3427   ENTER_V8(isolate);
3428   i::HandleScope scope(isolate);
3429   v8::Handle<AccessorSignature> signature;
3430   i::Handle<i::AccessorInfo> info = MakeAccessorInfo(
3431       name, getter, setter, data, settings, attributes, signature);
3432   if (info.is_null()) return false;
3433   bool fast = Utils::OpenHandle(obj)->HasFastProperties();
3434   i::Handle<i::Object> result;
3435   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
3436       isolate, result,
3437       i::JSObject::SetAccessor(Utils::OpenHandle(obj), info),
3438       false);
3439   if (result->IsUndefined()) return false;
3440   if (fast) i::JSObject::MigrateSlowToFast(Utils::OpenHandle(obj), 0);
3441   return true;
3442 }
3443
3444
3445 bool Object::SetAccessor(Handle<String> name,
3446                          AccessorGetterCallback getter,
3447                          AccessorSetterCallback setter,
3448                          v8::Handle<Value> data,
3449                          AccessControl settings,
3450                          PropertyAttribute attributes) {
3451   return ObjectSetAccessor(
3452       this, name, getter, setter, data, settings, attributes);
3453 }
3454
3455
3456 bool Object::SetDeclaredAccessor(Local<String> name,
3457                                  Local<DeclaredAccessorDescriptor> descriptor,
3458                                  PropertyAttribute attributes,
3459                                  AccessControl settings) {
3460   void* null = NULL;
3461   return ObjectSetAccessor(
3462       this, name, descriptor, null, null, settings, attributes);
3463 }
3464
3465
3466 void Object::SetAccessorProperty(Local<String> name,
3467                                  Local<Function> getter,
3468                                  Handle<Function> setter,
3469                                  PropertyAttribute attribute,
3470                                  AccessControl settings) {
3471   // TODO(verwaest): Remove |settings|.
3472   DCHECK_EQ(v8::DEFAULT, settings);
3473   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3474   ON_BAILOUT(isolate, "v8::Object::SetAccessorProperty()", return);
3475   ENTER_V8(isolate);
3476   i::HandleScope scope(isolate);
3477   i::Handle<i::Object> getter_i = v8::Utils::OpenHandle(*getter);
3478   i::Handle<i::Object> setter_i = v8::Utils::OpenHandle(*setter, true);
3479   if (setter_i.is_null()) setter_i = isolate->factory()->null_value();
3480   i::JSObject::DefineAccessor(v8::Utils::OpenHandle(this),
3481                               v8::Utils::OpenHandle(*name),
3482                               getter_i,
3483                               setter_i,
3484                               static_cast<PropertyAttributes>(attribute));
3485 }
3486
3487
3488 bool v8::Object::HasOwnProperty(Handle<String> key) {
3489   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3490   ON_BAILOUT(isolate, "v8::Object::HasOwnProperty()",
3491              return false);
3492   EXCEPTION_PREAMBLE(isolate);
3493   Maybe<bool> maybe = i::JSReceiver::HasOwnProperty(Utils::OpenHandle(this),
3494                                                     Utils::OpenHandle(*key));
3495   has_pending_exception = !maybe.has_value;
3496   EXCEPTION_BAILOUT_CHECK(isolate, false);
3497   return maybe.value;
3498 }
3499
3500
3501 bool v8::Object::HasRealNamedProperty(Handle<String> key) {
3502   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3503   ON_BAILOUT(isolate, "v8::Object::HasRealNamedProperty()",
3504              return false);
3505   EXCEPTION_PREAMBLE(isolate);
3506   Maybe<bool> maybe = i::JSObject::HasRealNamedProperty(
3507       Utils::OpenHandle(this), Utils::OpenHandle(*key));
3508   has_pending_exception = !maybe.has_value;
3509   EXCEPTION_BAILOUT_CHECK(isolate, false);
3510   return maybe.value;
3511 }
3512
3513
3514 bool v8::Object::HasRealIndexedProperty(uint32_t index) {
3515   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3516   ON_BAILOUT(isolate, "v8::Object::HasRealIndexedProperty()",
3517              return false);
3518   EXCEPTION_PREAMBLE(isolate);
3519   Maybe<bool> maybe =
3520       i::JSObject::HasRealElementProperty(Utils::OpenHandle(this), index);
3521   has_pending_exception = !maybe.has_value;
3522   EXCEPTION_BAILOUT_CHECK(isolate, false);
3523   return maybe.value;
3524 }
3525
3526
3527 bool v8::Object::HasRealNamedCallbackProperty(Handle<String> key) {
3528   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3529   ON_BAILOUT(isolate,
3530              "v8::Object::HasRealNamedCallbackProperty()",
3531              return false);
3532   ENTER_V8(isolate);
3533   EXCEPTION_PREAMBLE(isolate);
3534   Maybe<bool> maybe = i::JSObject::HasRealNamedCallbackProperty(
3535       Utils::OpenHandle(this), Utils::OpenHandle(*key));
3536   has_pending_exception = !maybe.has_value;
3537   EXCEPTION_BAILOUT_CHECK(isolate, false);
3538   return maybe.value;
3539 }
3540
3541
3542 bool v8::Object::HasNamedLookupInterceptor() {
3543   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3544   ON_BAILOUT(isolate, "v8::Object::HasNamedLookupInterceptor()",
3545              return false);
3546   return Utils::OpenHandle(this)->HasNamedInterceptor();
3547 }
3548
3549
3550 bool v8::Object::HasIndexedLookupInterceptor() {
3551   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3552   ON_BAILOUT(isolate, "v8::Object::HasIndexedLookupInterceptor()",
3553              return false);
3554   return Utils::OpenHandle(this)->HasIndexedInterceptor();
3555 }
3556
3557
3558 static Local<Value> GetPropertyByLookup(i::Isolate* isolate,
3559                                         i::Handle<i::JSObject> receiver,
3560                                         i::Handle<i::String> name,
3561                                         i::LookupResult* lookup) {
3562   if (!lookup->IsProperty()) {
3563     // No real property was found.
3564     return Local<Value>();
3565   }
3566
3567   // If the property being looked up is a callback, it can throw
3568   // an exception.
3569   EXCEPTION_PREAMBLE(isolate);
3570   i::LookupIterator it(
3571       receiver, name, i::Handle<i::JSReceiver>(lookup->holder(), isolate),
3572       i::LookupIterator::SKIP_INTERCEPTOR);
3573   i::Handle<i::Object> result;
3574   has_pending_exception = !i::Object::GetProperty(&it).ToHandle(&result);
3575   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3576
3577   return Utils::ToLocal(result);
3578 }
3579
3580
3581 Local<Value> v8::Object::GetRealNamedPropertyInPrototypeChain(
3582     Handle<String> key) {
3583   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3584   ON_BAILOUT(isolate,
3585              "v8::Object::GetRealNamedPropertyInPrototypeChain()",
3586              return Local<Value>());
3587   ENTER_V8(isolate);
3588   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3589   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3590   i::LookupResult lookup(isolate);
3591   self_obj->LookupRealNamedPropertyInPrototypes(key_obj, &lookup);
3592   return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3593 }
3594
3595
3596 Local<Value> v8::Object::GetRealNamedProperty(Handle<String> key) {
3597   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3598   ON_BAILOUT(isolate, "v8::Object::GetRealNamedProperty()",
3599              return Local<Value>());
3600   ENTER_V8(isolate);
3601   i::Handle<i::JSObject> self_obj = Utils::OpenHandle(this);
3602   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3603   i::LookupResult lookup(isolate);
3604   self_obj->LookupRealNamedProperty(key_obj, &lookup);
3605   return GetPropertyByLookup(isolate, self_obj, key_obj, &lookup);
3606 }
3607
3608
3609 // Turns on access checks by copying the map and setting the check flag.
3610 // Because the object gets a new map, existing inline cache caching
3611 // the old map of this object will fail.
3612 void v8::Object::TurnOnAccessCheck() {
3613   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3614   ON_BAILOUT(isolate, "v8::Object::TurnOnAccessCheck()", return);
3615   ENTER_V8(isolate);
3616   i::HandleScope scope(isolate);
3617   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3618
3619   // When turning on access checks for a global object deoptimize all functions
3620   // as optimized code does not always handle access checks.
3621   i::Deoptimizer::DeoptimizeGlobalObject(*obj);
3622
3623   i::Handle<i::Map> new_map = i::Map::Copy(i::Handle<i::Map>(obj->map()));
3624   new_map->set_is_access_check_needed(true);
3625   i::JSObject::MigrateToMap(obj, new_map);
3626 }
3627
3628
3629 bool v8::Object::IsDirty() {
3630   return Utils::OpenHandle(this)->IsDirty();
3631 }
3632
3633
3634 Local<v8::Object> v8::Object::Clone() {
3635   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3636   ON_BAILOUT(isolate, "v8::Object::Clone()", return Local<Object>());
3637   ENTER_V8(isolate);
3638   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3639   EXCEPTION_PREAMBLE(isolate);
3640   i::Handle<i::JSObject> result = isolate->factory()->CopyJSObject(self);
3641   has_pending_exception = result.is_null();
3642   EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
3643   return Utils::ToLocal(result);
3644 }
3645
3646
3647 Local<v8::Context> v8::Object::CreationContext() {
3648   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3649   ON_BAILOUT(isolate,
3650              "v8::Object::CreationContext()", return Local<v8::Context>());
3651   ENTER_V8(isolate);
3652   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3653   i::Context* context = self->GetCreationContext();
3654   return Utils::ToLocal(i::Handle<i::Context>(context));
3655 }
3656
3657
3658 int v8::Object::GetIdentityHash() {
3659   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3660   ON_BAILOUT(isolate, "v8::Object::GetIdentityHash()", return 0);
3661   ENTER_V8(isolate);
3662   i::HandleScope scope(isolate);
3663   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3664   return i::JSReceiver::GetOrCreateIdentityHash(self)->value();
3665 }
3666
3667
3668 bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key,
3669                                 v8::Handle<v8::Value> value) {
3670   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3671   ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false);
3672   if (value.IsEmpty()) return DeleteHiddenValue(key);
3673   ENTER_V8(isolate);
3674   i::HandleScope scope(isolate);
3675   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3676   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3677   i::Handle<i::String> key_string =
3678       isolate->factory()->InternalizeString(key_obj);
3679   i::Handle<i::Object> value_obj = Utils::OpenHandle(*value);
3680   i::Handle<i::Object> result =
3681       i::JSObject::SetHiddenProperty(self, key_string, value_obj);
3682   return *result == *self;
3683 }
3684
3685
3686 v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) {
3687   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3688   ON_BAILOUT(isolate, "v8::Object::GetHiddenValue()",
3689              return Local<v8::Value>());
3690   ENTER_V8(isolate);
3691   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3692   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3693   i::Handle<i::String> key_string =
3694       isolate->factory()->InternalizeString(key_obj);
3695   i::Handle<i::Object> result(self->GetHiddenProperty(key_string), isolate);
3696   if (result->IsTheHole()) return v8::Local<v8::Value>();
3697   return Utils::ToLocal(result);
3698 }
3699
3700
3701 bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) {
3702   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3703   ON_BAILOUT(isolate, "v8::DeleteHiddenValue()", return false);
3704   ENTER_V8(isolate);
3705   i::HandleScope scope(isolate);
3706   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3707   i::Handle<i::String> key_obj = Utils::OpenHandle(*key);
3708   i::Handle<i::String> key_string =
3709       isolate->factory()->InternalizeString(key_obj);
3710   i::JSObject::DeleteHiddenProperty(self, key_string);
3711   return true;
3712 }
3713
3714
3715 namespace {
3716
3717 static i::ElementsKind GetElementsKindFromExternalArrayType(
3718     ExternalArrayType array_type) {
3719   switch (array_type) {
3720 #define ARRAY_TYPE_TO_ELEMENTS_KIND(Type, type, TYPE, ctype, size)            \
3721     case kExternal##Type##Array:                                              \
3722       return i::EXTERNAL_##TYPE##_ELEMENTS;
3723
3724     TYPED_ARRAYS(ARRAY_TYPE_TO_ELEMENTS_KIND)
3725 #undef ARRAY_TYPE_TO_ELEMENTS_KIND
3726   }
3727   UNREACHABLE();
3728   return i::DICTIONARY_ELEMENTS;
3729 }
3730
3731
3732 void PrepareExternalArrayElements(i::Handle<i::JSObject> object,
3733                                   void* data,
3734                                   ExternalArrayType array_type,
3735                                   int length) {
3736   i::Isolate* isolate = object->GetIsolate();
3737   i::Handle<i::ExternalArray> array =
3738       isolate->factory()->NewExternalArray(length, array_type, data);
3739
3740   i::Handle<i::Map> external_array_map =
3741       i::JSObject::GetElementsTransitionMap(
3742           object,
3743           GetElementsKindFromExternalArrayType(array_type));
3744
3745   i::JSObject::SetMapAndElements(object, external_array_map, array);
3746 }
3747
3748 }  // namespace
3749
3750
3751 void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) {
3752   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3753   ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return);
3754   ENTER_V8(isolate);
3755   i::HandleScope scope(isolate);
3756   if (!Utils::ApiCheck(length >= 0 &&
3757                        length <= i::ExternalUint8ClampedArray::kMaxLength,
3758                        "v8::Object::SetIndexedPropertiesToPixelData()",
3759                        "length exceeds max acceptable value")) {
3760     return;
3761   }
3762   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3763   if (!Utils::ApiCheck(!self->IsJSArray(),
3764                        "v8::Object::SetIndexedPropertiesToPixelData()",
3765                        "JSArray is not supported")) {
3766     return;
3767   }
3768   PrepareExternalArrayElements(self, data, kExternalUint8ClampedArray, length);
3769 }
3770
3771
3772 bool v8::Object::HasIndexedPropertiesInPixelData() {
3773   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3774   ON_BAILOUT(self->GetIsolate(), "v8::HasIndexedPropertiesInPixelData()",
3775              return false);
3776   return self->HasExternalUint8ClampedElements();
3777 }
3778
3779
3780 uint8_t* v8::Object::GetIndexedPropertiesPixelData() {
3781   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3782   ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelData()",
3783              return NULL);
3784   if (self->HasExternalUint8ClampedElements()) {
3785     return i::ExternalUint8ClampedArray::cast(self->elements())->
3786         external_uint8_clamped_pointer();
3787   } else {
3788     return NULL;
3789   }
3790 }
3791
3792
3793 int v8::Object::GetIndexedPropertiesPixelDataLength() {
3794   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3795   ON_BAILOUT(self->GetIsolate(), "v8::GetIndexedPropertiesPixelDataLength()",
3796              return -1);
3797   if (self->HasExternalUint8ClampedElements()) {
3798     return i::ExternalUint8ClampedArray::cast(self->elements())->length();
3799   } else {
3800     return -1;
3801   }
3802 }
3803
3804
3805 void v8::Object::SetIndexedPropertiesToExternalArrayData(
3806     void* data,
3807     ExternalArrayType array_type,
3808     int length) {
3809   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3810   ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return);
3811   ENTER_V8(isolate);
3812   i::HandleScope scope(isolate);
3813   if (!Utils::ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength,
3814                        "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3815                        "length exceeds max acceptable value")) {
3816     return;
3817   }
3818   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3819   if (!Utils::ApiCheck(!self->IsJSArray(),
3820                        "v8::Object::SetIndexedPropertiesToExternalArrayData()",
3821                        "JSArray is not supported")) {
3822     return;
3823   }
3824   PrepareExternalArrayElements(self, data, array_type, length);
3825 }
3826
3827
3828 bool v8::Object::HasIndexedPropertiesInExternalArrayData() {
3829   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3830   ON_BAILOUT(self->GetIsolate(),
3831              "v8::HasIndexedPropertiesInExternalArrayData()",
3832              return false);
3833   return self->HasExternalArrayElements();
3834 }
3835
3836
3837 void* v8::Object::GetIndexedPropertiesExternalArrayData() {
3838   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3839   ON_BAILOUT(self->GetIsolate(),
3840              "v8::GetIndexedPropertiesExternalArrayData()",
3841              return NULL);
3842   if (self->HasExternalArrayElements()) {
3843     return i::ExternalArray::cast(self->elements())->external_pointer();
3844   } else {
3845     return NULL;
3846   }
3847 }
3848
3849
3850 ExternalArrayType v8::Object::GetIndexedPropertiesExternalArrayDataType() {
3851   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3852   ON_BAILOUT(self->GetIsolate(),
3853              "v8::GetIndexedPropertiesExternalArrayDataType()",
3854              return static_cast<ExternalArrayType>(-1));
3855   switch (self->elements()->map()->instance_type()) {
3856 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
3857     case i::EXTERNAL_##TYPE##_ARRAY_TYPE:                                     \
3858       return kExternal##Type##Array;
3859     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
3860 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
3861     default:
3862       return static_cast<ExternalArrayType>(-1);
3863   }
3864 }
3865
3866
3867 int v8::Object::GetIndexedPropertiesExternalArrayDataLength() {
3868   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
3869   ON_BAILOUT(self->GetIsolate(),
3870              "v8::GetIndexedPropertiesExternalArrayDataLength()",
3871              return 0);
3872   if (self->HasExternalArrayElements()) {
3873     return i::ExternalArray::cast(self->elements())->length();
3874   } else {
3875     return -1;
3876   }
3877 }
3878
3879
3880 bool v8::Object::IsCallable() {
3881   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3882   ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false);
3883   ENTER_V8(isolate);
3884   i::HandleScope scope(isolate);
3885   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3886   return obj->IsCallable();
3887 }
3888
3889
3890 Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Value> recv,
3891                                         int argc,
3892                                         v8::Handle<v8::Value> argv[]) {
3893   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3894   ON_BAILOUT(isolate, "v8::Object::CallAsFunction()",
3895              return Local<v8::Value>());
3896   LOG_API(isolate, "Object::CallAsFunction");
3897   ENTER_V8(isolate);
3898   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3899   i::HandleScope scope(isolate);
3900   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3901   i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
3902   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3903   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3904   i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>();
3905   if (obj->IsJSFunction()) {
3906     fun = i::Handle<i::JSFunction>::cast(obj);
3907   } else {
3908     EXCEPTION_PREAMBLE(isolate);
3909     i::Handle<i::Object> delegate;
3910     has_pending_exception = !i::Execution::TryGetFunctionDelegate(
3911         isolate, obj).ToHandle(&delegate);
3912     EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
3913     fun = i::Handle<i::JSFunction>::cast(delegate);
3914     recv_obj = obj;
3915   }
3916   EXCEPTION_PREAMBLE(isolate);
3917   i::Handle<i::Object> returned;
3918   has_pending_exception = !i::Execution::Call(
3919       isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
3920   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Value>());
3921   return Utils::ToLocal(scope.CloseAndEscape(returned));
3922 }
3923
3924
3925 Local<v8::Value> Object::CallAsConstructor(int argc,
3926                                            v8::Handle<v8::Value> argv[]) {
3927   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3928   ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()",
3929              return Local<v8::Object>());
3930   LOG_API(isolate, "Object::CallAsConstructor");
3931   ENTER_V8(isolate);
3932   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3933   i::HandleScope scope(isolate);
3934   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
3935   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3936   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3937   if (obj->IsJSFunction()) {
3938     i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj);
3939     EXCEPTION_PREAMBLE(isolate);
3940     i::Handle<i::Object> returned;
3941     has_pending_exception = !i::Execution::New(
3942         fun, argc, args).ToHandle(&returned);
3943     EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3944     return Utils::ToLocal(scope.CloseAndEscape(
3945         i::Handle<i::JSObject>::cast(returned)));
3946   }
3947   EXCEPTION_PREAMBLE(isolate);
3948   i::Handle<i::Object> delegate;
3949   has_pending_exception = !i::Execution::TryGetConstructorDelegate(
3950       isolate, obj).ToHandle(&delegate);
3951   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
3952   if (!delegate->IsUndefined()) {
3953     i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate);
3954     EXCEPTION_PREAMBLE(isolate);
3955     i::Handle<i::Object> returned;
3956     has_pending_exception = !i::Execution::Call(
3957         isolate, fun, obj, argc, args).ToHandle(&returned);
3958     EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
3959     DCHECK(!delegate->IsUndefined());
3960     return Utils::ToLocal(scope.CloseAndEscape(returned));
3961   }
3962   return Local<v8::Object>();
3963 }
3964
3965
3966 Local<Function> Function::New(Isolate* v8_isolate,
3967                               FunctionCallback callback,
3968                               Local<Value> data,
3969                               int length) {
3970   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
3971   LOG_API(isolate, "Function::New");
3972   ENTER_V8(isolate);
3973   return FunctionTemplateNew(
3974       isolate, callback, data, Local<Signature>(), length, true)->
3975       GetFunction();
3976 }
3977
3978
3979 Local<v8::Object> Function::NewInstance() const {
3980   return NewInstance(0, NULL);
3981 }
3982
3983
3984 Local<v8::Object> Function::NewInstance(int argc,
3985                                         v8::Handle<v8::Value> argv[]) const {
3986   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
3987   ON_BAILOUT(isolate, "v8::Function::NewInstance()",
3988              return Local<v8::Object>());
3989   LOG_API(isolate, "Function::NewInstance");
3990   ENTER_V8(isolate);
3991   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
3992   EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
3993   i::Handle<i::JSFunction> function = Utils::OpenHandle(this);
3994   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
3995   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
3996   EXCEPTION_PREAMBLE(isolate);
3997   i::Handle<i::Object> returned;
3998   has_pending_exception = !i::Execution::New(
3999       function, argc, args).ToHandle(&returned);
4000   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<v8::Object>());
4001   return scope.Escape(Utils::ToLocal(i::Handle<i::JSObject>::cast(returned)));
4002 }
4003
4004
4005 Local<v8::Value> Function::Call(v8::Handle<v8::Value> recv, int argc,
4006                                 v8::Handle<v8::Value> argv[]) {
4007   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4008   ON_BAILOUT(isolate, "v8::Function::Call()", return Local<v8::Value>());
4009   LOG_API(isolate, "Function::Call");
4010   ENTER_V8(isolate);
4011   i::TimerEventScope<i::TimerEventExecute> timer_scope(isolate);
4012   i::HandleScope scope(isolate);
4013   i::Handle<i::JSFunction> fun = Utils::OpenHandle(this);
4014   i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv);
4015   STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**));
4016   i::Handle<i::Object>* args = reinterpret_cast<i::Handle<i::Object>*>(argv);
4017   EXCEPTION_PREAMBLE(isolate);
4018   i::Handle<i::Object> returned;
4019   has_pending_exception = !i::Execution::Call(
4020       isolate, fun, recv_obj, argc, args, true).ToHandle(&returned);
4021   EXCEPTION_BAILOUT_CHECK_DO_CALLBACK(isolate, Local<Object>());
4022   return Utils::ToLocal(scope.CloseAndEscape(returned));
4023 }
4024
4025
4026 void Function::SetName(v8::Handle<v8::String> name) {
4027   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4028   ENTER_V8(isolate);
4029   USE(isolate);
4030   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4031   func->shared()->set_name(*Utils::OpenHandle(*name));
4032 }
4033
4034
4035 Handle<Value> Function::GetName() const {
4036   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4037   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->name(),
4038                                              func->GetIsolate()));
4039 }
4040
4041
4042 Handle<Value> Function::GetInferredName() const {
4043   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4044   return Utils::ToLocal(i::Handle<i::Object>(func->shared()->inferred_name(),
4045                                              func->GetIsolate()));
4046 }
4047
4048
4049 Handle<Value> Function::GetDisplayName() const {
4050   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4051   ON_BAILOUT(isolate, "v8::Function::GetDisplayName()",
4052              return ToApiHandle<Primitive>(
4053                  isolate->factory()->undefined_value()));
4054   ENTER_V8(isolate);
4055   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4056   i::Handle<i::String> property_name =
4057       isolate->factory()->InternalizeOneByteString(
4058           STATIC_ASCII_VECTOR("displayName"));
4059   i::LookupResult lookup(isolate);
4060   func->LookupRealNamedProperty(property_name, &lookup);
4061   if (lookup.IsFound()) {
4062     i::Object* value = lookup.GetLazyValue();
4063     if (value && value->IsString()) {
4064       i::String* name = i::String::cast(value);
4065       if (name->length() > 0) return Utils::ToLocal(i::Handle<i::String>(name));
4066     }
4067   }
4068   return ToApiHandle<Primitive>(isolate->factory()->undefined_value());
4069 }
4070
4071
4072 ScriptOrigin Function::GetScriptOrigin() const {
4073   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4074   if (func->shared()->script()->IsScript()) {
4075     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4076     i::Handle<i::Object> scriptName = i::Script::GetNameOrSourceURL(script);
4077     v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(func->GetIsolate());
4078     v8::ScriptOrigin origin(
4079         Utils::ToLocal(scriptName),
4080         v8::Integer::New(isolate, script->line_offset()->value()),
4081         v8::Integer::New(isolate, script->column_offset()->value()));
4082     return origin;
4083   }
4084   return v8::ScriptOrigin(Handle<Value>());
4085 }
4086
4087
4088 const int Function::kLineOffsetNotFound = -1;
4089
4090
4091 int Function::GetScriptLineNumber() const {
4092   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4093   if (func->shared()->script()->IsScript()) {
4094     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4095     return i::Script::GetLineNumber(script, func->shared()->start_position());
4096   }
4097   return kLineOffsetNotFound;
4098 }
4099
4100
4101 int Function::GetScriptColumnNumber() const {
4102   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4103   if (func->shared()->script()->IsScript()) {
4104     i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4105     return i::Script::GetColumnNumber(script, func->shared()->start_position());
4106   }
4107   return kLineOffsetNotFound;
4108 }
4109
4110
4111 bool Function::IsBuiltin() const {
4112   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4113   return func->IsBuiltin();
4114 }
4115
4116
4117 int Function::ScriptId() const {
4118   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4119   if (!func->shared()->script()->IsScript()) {
4120     return v8::UnboundScript::kNoScriptId;
4121   }
4122   i::Handle<i::Script> script(i::Script::cast(func->shared()->script()));
4123   return script->id()->value();
4124 }
4125
4126
4127 Local<v8::Value> Function::GetBoundFunction() const {
4128   i::Handle<i::JSFunction> func = Utils::OpenHandle(this);
4129   if (!func->shared()->bound()) {
4130     return v8::Undefined(reinterpret_cast<v8::Isolate*>(func->GetIsolate()));
4131   }
4132   i::Handle<i::FixedArray> bound_args = i::Handle<i::FixedArray>(
4133       i::FixedArray::cast(func->function_bindings()));
4134   i::Handle<i::Object> original(
4135       bound_args->get(i::JSFunction::kBoundFunctionIndex),
4136       func->GetIsolate());
4137   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(original));
4138 }
4139
4140
4141 int String::Length() const {
4142   i::Handle<i::String> str = Utils::OpenHandle(this);
4143   return str->length();
4144 }
4145
4146
4147 bool String::IsOneByte() const {
4148   i::Handle<i::String> str = Utils::OpenHandle(this);
4149   return str->HasOnlyOneByteChars();
4150 }
4151
4152
4153 // Helpers for ContainsOnlyOneByteHelper
4154 template<size_t size> struct OneByteMask;
4155 template<> struct OneByteMask<4> {
4156   static const uint32_t value = 0xFF00FF00;
4157 };
4158 template<> struct OneByteMask<8> {
4159   static const uint64_t value = V8_2PART_UINT64_C(0xFF00FF00, FF00FF00);
4160 };
4161 static const uintptr_t kOneByteMask = OneByteMask<sizeof(uintptr_t)>::value;
4162 static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1;
4163 static inline bool Unaligned(const uint16_t* chars) {
4164   return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask;
4165 }
4166
4167
4168 static inline const uint16_t* Align(const uint16_t* chars) {
4169   return reinterpret_cast<uint16_t*>(
4170       reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask);
4171 }
4172
4173 class ContainsOnlyOneByteHelper {
4174  public:
4175   ContainsOnlyOneByteHelper() : is_one_byte_(true) {}
4176   bool Check(i::String* string) {
4177     i::ConsString* cons_string = i::String::VisitFlat(this, string, 0);
4178     if (cons_string == NULL) return is_one_byte_;
4179     return CheckCons(cons_string);
4180   }
4181   void VisitOneByteString(const uint8_t* chars, int length) {
4182     // Nothing to do.
4183   }
4184   void VisitTwoByteString(const uint16_t* chars, int length) {
4185     // Accumulated bits.
4186     uintptr_t acc = 0;
4187     // Align to uintptr_t.
4188     const uint16_t* end = chars + length;
4189     while (Unaligned(chars) && chars != end) {
4190       acc |= *chars++;
4191     }
4192     // Read word aligned in blocks,
4193     // checking the return value at the end of each block.
4194     const uint16_t* aligned_end = Align(end);
4195     const int increment = sizeof(uintptr_t)/sizeof(uint16_t);
4196     const int inner_loops = 16;
4197     while (chars + inner_loops*increment < aligned_end) {
4198       for (int i = 0; i < inner_loops; i++) {
4199         acc |= *reinterpret_cast<const uintptr_t*>(chars);
4200         chars += increment;
4201       }
4202       // Check for early return.
4203       if ((acc & kOneByteMask) != 0) {
4204         is_one_byte_ = false;
4205         return;
4206       }
4207     }
4208     // Read the rest.
4209     while (chars != end) {
4210       acc |= *chars++;
4211     }
4212     // Check result.
4213     if ((acc & kOneByteMask) != 0) is_one_byte_ = false;
4214   }
4215
4216  private:
4217   bool CheckCons(i::ConsString* cons_string) {
4218     while (true) {
4219       // Check left side if flat.
4220       i::String* left = cons_string->first();
4221       i::ConsString* left_as_cons =
4222           i::String::VisitFlat(this, left, 0);
4223       if (!is_one_byte_) return false;
4224       // Check right side if flat.
4225       i::String* right = cons_string->second();
4226       i::ConsString* right_as_cons =
4227           i::String::VisitFlat(this, right, 0);
4228       if (!is_one_byte_) return false;
4229       // Standard recurse/iterate trick.
4230       if (left_as_cons != NULL && right_as_cons != NULL) {
4231         if (left->length() < right->length()) {
4232           CheckCons(left_as_cons);
4233           cons_string = right_as_cons;
4234         } else {
4235           CheckCons(right_as_cons);
4236           cons_string = left_as_cons;
4237         }
4238         // Check fast return.
4239         if (!is_one_byte_) return false;
4240         continue;
4241       }
4242       // Descend left in place.
4243       if (left_as_cons != NULL) {
4244         cons_string = left_as_cons;
4245         continue;
4246       }
4247       // Descend right in place.
4248       if (right_as_cons != NULL) {
4249         cons_string = right_as_cons;
4250         continue;
4251       }
4252       // Terminate.
4253       break;
4254     }
4255     return is_one_byte_;
4256   }
4257   bool is_one_byte_;
4258   DISALLOW_COPY_AND_ASSIGN(ContainsOnlyOneByteHelper);
4259 };
4260
4261
4262 bool String::ContainsOnlyOneByte() const {
4263   i::Handle<i::String> str = Utils::OpenHandle(this);
4264   if (str->HasOnlyOneByteChars()) return true;
4265   ContainsOnlyOneByteHelper helper;
4266   return helper.Check(*str);
4267 }
4268
4269
4270 class Utf8LengthHelper : public i::AllStatic {
4271  public:
4272   enum State {
4273     kEndsWithLeadingSurrogate = 1 << 0,
4274     kStartsWithTrailingSurrogate = 1 << 1,
4275     kLeftmostEdgeIsCalculated = 1 << 2,
4276     kRightmostEdgeIsCalculated = 1 << 3,
4277     kLeftmostEdgeIsSurrogate = 1 << 4,
4278     kRightmostEdgeIsSurrogate = 1 << 5
4279   };
4280
4281   static const uint8_t kInitialState = 0;
4282
4283   static inline bool EndsWithSurrogate(uint8_t state) {
4284     return state & kEndsWithLeadingSurrogate;
4285   }
4286
4287   static inline bool StartsWithSurrogate(uint8_t state) {
4288     return state & kStartsWithTrailingSurrogate;
4289   }
4290
4291   class Visitor {
4292    public:
4293     Visitor() : utf8_length_(0), state_(kInitialState) {}
4294
4295     void VisitOneByteString(const uint8_t* chars, int length) {
4296       int utf8_length = 0;
4297       // Add in length 1 for each non-ASCII character.
4298       for (int i = 0; i < length; i++) {
4299         utf8_length += *chars++ >> 7;
4300       }
4301       // Add in length 1 for each character.
4302       utf8_length_ = utf8_length + length;
4303       state_ = kInitialState;
4304     }
4305
4306     void VisitTwoByteString(const uint16_t* chars, int length) {
4307       int utf8_length = 0;
4308       int last_character = unibrow::Utf16::kNoPreviousCharacter;
4309       for (int i = 0; i < length; i++) {
4310         uint16_t c = chars[i];
4311         utf8_length += unibrow::Utf8::Length(c, last_character);
4312         last_character = c;
4313       }
4314       utf8_length_ = utf8_length;
4315       uint8_t state = 0;
4316       if (unibrow::Utf16::IsTrailSurrogate(chars[0])) {
4317         state |= kStartsWithTrailingSurrogate;
4318       }
4319       if (unibrow::Utf16::IsLeadSurrogate(chars[length-1])) {
4320         state |= kEndsWithLeadingSurrogate;
4321       }
4322       state_ = state;
4323     }
4324
4325     static i::ConsString* VisitFlat(i::String* string,
4326                                     int* length,
4327                                     uint8_t* state) {
4328       Visitor visitor;
4329       i::ConsString* cons_string = i::String::VisitFlat(&visitor, string);
4330       *length = visitor.utf8_length_;
4331       *state = visitor.state_;
4332       return cons_string;
4333     }
4334
4335    private:
4336     int utf8_length_;
4337     uint8_t state_;
4338     DISALLOW_COPY_AND_ASSIGN(Visitor);
4339   };
4340
4341   static inline void MergeLeafLeft(int* length,
4342                                    uint8_t* state,
4343                                    uint8_t leaf_state) {
4344     bool edge_surrogate = StartsWithSurrogate(leaf_state);
4345     if (!(*state & kLeftmostEdgeIsCalculated)) {
4346       DCHECK(!(*state & kLeftmostEdgeIsSurrogate));
4347       *state |= kLeftmostEdgeIsCalculated
4348           | (edge_surrogate ? kLeftmostEdgeIsSurrogate : 0);
4349     } else if (EndsWithSurrogate(*state) && edge_surrogate) {
4350       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4351     }
4352     if (EndsWithSurrogate(leaf_state)) {
4353       *state |= kEndsWithLeadingSurrogate;
4354     } else {
4355       *state &= ~kEndsWithLeadingSurrogate;
4356     }
4357   }
4358
4359   static inline void MergeLeafRight(int* length,
4360                                     uint8_t* state,
4361                                     uint8_t leaf_state) {
4362     bool edge_surrogate = EndsWithSurrogate(leaf_state);
4363     if (!(*state & kRightmostEdgeIsCalculated)) {
4364       DCHECK(!(*state & kRightmostEdgeIsSurrogate));
4365       *state |= (kRightmostEdgeIsCalculated
4366                  | (edge_surrogate ? kRightmostEdgeIsSurrogate : 0));
4367     } else if (edge_surrogate && StartsWithSurrogate(*state)) {
4368       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4369     }
4370     if (StartsWithSurrogate(leaf_state)) {
4371       *state |= kStartsWithTrailingSurrogate;
4372     } else {
4373       *state &= ~kStartsWithTrailingSurrogate;
4374     }
4375   }
4376
4377   static inline void MergeTerminal(int* length,
4378                                    uint8_t state,
4379                                    uint8_t* state_out) {
4380     DCHECK((state & kLeftmostEdgeIsCalculated) &&
4381            (state & kRightmostEdgeIsCalculated));
4382     if (EndsWithSurrogate(state) && StartsWithSurrogate(state)) {
4383       *length -= unibrow::Utf8::kBytesSavedByCombiningSurrogates;
4384     }
4385     *state_out = kInitialState |
4386         (state & kLeftmostEdgeIsSurrogate ? kStartsWithTrailingSurrogate : 0) |
4387         (state & kRightmostEdgeIsSurrogate ? kEndsWithLeadingSurrogate : 0);
4388   }
4389
4390   static int Calculate(i::ConsString* current, uint8_t* state_out) {
4391     using namespace internal;
4392     int total_length = 0;
4393     uint8_t state = kInitialState;
4394     while (true) {
4395       i::String* left = current->first();
4396       i::String* right = current->second();
4397       uint8_t right_leaf_state;
4398       uint8_t left_leaf_state;
4399       int leaf_length;
4400       ConsString* left_as_cons =
4401           Visitor::VisitFlat(left, &leaf_length, &left_leaf_state);
4402       if (left_as_cons == NULL) {
4403         total_length += leaf_length;
4404         MergeLeafLeft(&total_length, &state, left_leaf_state);
4405       }
4406       ConsString* right_as_cons =
4407           Visitor::VisitFlat(right, &leaf_length, &right_leaf_state);
4408       if (right_as_cons == NULL) {
4409         total_length += leaf_length;
4410         MergeLeafRight(&total_length, &state, right_leaf_state);
4411         if (left_as_cons != NULL) {
4412           // 1 Leaf node. Descend in place.
4413           current = left_as_cons;
4414           continue;
4415         } else {
4416           // Terminal node.
4417           MergeTerminal(&total_length, state, state_out);
4418           return total_length;
4419         }
4420       } else if (left_as_cons == NULL) {
4421         // 1 Leaf node. Descend in place.
4422         current = right_as_cons;
4423         continue;
4424       }
4425       // Both strings are ConsStrings.
4426       // Recurse on smallest.
4427       if (left->length() < right->length()) {
4428         total_length += Calculate(left_as_cons, &left_leaf_state);
4429         MergeLeafLeft(&total_length, &state, left_leaf_state);
4430         current = right_as_cons;
4431       } else {
4432         total_length += Calculate(right_as_cons, &right_leaf_state);
4433         MergeLeafRight(&total_length, &state, right_leaf_state);
4434         current = left_as_cons;
4435       }
4436     }
4437     UNREACHABLE();
4438     return 0;
4439   }
4440
4441   static inline int Calculate(i::ConsString* current) {
4442     uint8_t state = kInitialState;
4443     return Calculate(current, &state);
4444   }
4445
4446  private:
4447   DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8LengthHelper);
4448 };
4449
4450
4451 static int Utf8Length(i::String* str, i::Isolate* isolate) {
4452   int length = str->length();
4453   if (length == 0) return 0;
4454   uint8_t state;
4455   i::ConsString* cons_string =
4456       Utf8LengthHelper::Visitor::VisitFlat(str, &length, &state);
4457   if (cons_string == NULL) return length;
4458   return Utf8LengthHelper::Calculate(cons_string);
4459 }
4460
4461
4462 int String::Utf8Length() const {
4463   i::Handle<i::String> str = Utils::OpenHandle(this);
4464   i::Isolate* isolate = str->GetIsolate();
4465   return v8::Utf8Length(*str, isolate);
4466 }
4467
4468
4469 class Utf8WriterVisitor {
4470  public:
4471   Utf8WriterVisitor(
4472       char* buffer,
4473       int capacity,
4474       bool skip_capacity_check,
4475       bool replace_invalid_utf8)
4476     : early_termination_(false),
4477       last_character_(unibrow::Utf16::kNoPreviousCharacter),
4478       buffer_(buffer),
4479       start_(buffer),
4480       capacity_(capacity),
4481       skip_capacity_check_(capacity == -1 || skip_capacity_check),
4482       replace_invalid_utf8_(replace_invalid_utf8),
4483       utf16_chars_read_(0) {
4484   }
4485
4486   static int WriteEndCharacter(uint16_t character,
4487                                int last_character,
4488                                int remaining,
4489                                char* const buffer,
4490                                bool replace_invalid_utf8) {
4491     using namespace unibrow;
4492     DCHECK(remaining > 0);
4493     // We can't use a local buffer here because Encode needs to modify
4494     // previous characters in the stream.  We know, however, that
4495     // exactly one character will be advanced.
4496     if (Utf16::IsSurrogatePair(last_character, character)) {
4497       int written = Utf8::Encode(buffer,
4498                                  character,
4499                                  last_character,
4500                                  replace_invalid_utf8);
4501       DCHECK(written == 1);
4502       return written;
4503     }
4504     // Use a scratch buffer to check the required characters.
4505     char temp_buffer[Utf8::kMaxEncodedSize];
4506     // Can't encode using last_character as gcc has array bounds issues.
4507     int written = Utf8::Encode(temp_buffer,
4508                                character,
4509                                Utf16::kNoPreviousCharacter,
4510                                replace_invalid_utf8);
4511     // Won't fit.
4512     if (written > remaining) return 0;
4513     // Copy over the character from temp_buffer.
4514     for (int j = 0; j < written; j++) {
4515       buffer[j] = temp_buffer[j];
4516     }
4517     return written;
4518   }
4519
4520   // Visit writes out a group of code units (chars) of a v8::String to the
4521   // internal buffer_. This is done in two phases. The first phase calculates a
4522   // pesimistic estimate (writable_length) on how many code units can be safely
4523   // written without exceeding the buffer capacity and without writing the last
4524   // code unit (it could be a lead surrogate). The estimated number of code
4525   // units is then written out in one go, and the reported byte usage is used
4526   // to correct the estimate. This is repeated until the estimate becomes <= 0
4527   // or all code units have been written out. The second phase writes out code
4528   // units until the buffer capacity is reached, would be exceeded by the next
4529   // unit, or all units have been written out.
4530   template<typename Char>
4531   void Visit(const Char* chars, const int length) {
4532     using namespace unibrow;
4533     DCHECK(!early_termination_);
4534     if (length == 0) return;
4535     // Copy state to stack.
4536     char* buffer = buffer_;
4537     int last_character =
4538         sizeof(Char) == 1 ? Utf16::kNoPreviousCharacter : last_character_;
4539     int i = 0;
4540     // Do a fast loop where there is no exit capacity check.
4541     while (true) {
4542       int fast_length;
4543       if (skip_capacity_check_) {
4544         fast_length = length;
4545       } else {
4546         int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4547         // Need enough space to write everything but one character.
4548         STATIC_ASSERT(Utf16::kMaxExtraUtf8BytesForOneUtf16CodeUnit == 3);
4549         int max_size_per_char =  sizeof(Char) == 1 ? 2 : 3;
4550         int writable_length =
4551             (remaining_capacity - max_size_per_char)/max_size_per_char;
4552         // Need to drop into slow loop.
4553         if (writable_length <= 0) break;
4554         fast_length = i + writable_length;
4555         if (fast_length > length) fast_length = length;
4556       }
4557       // Write the characters to the stream.
4558       if (sizeof(Char) == 1) {
4559         for (; i < fast_length; i++) {
4560           buffer +=
4561               Utf8::EncodeOneByte(buffer, static_cast<uint8_t>(*chars++));
4562           DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
4563         }
4564       } else {
4565         for (; i < fast_length; i++) {
4566           uint16_t character = *chars++;
4567           buffer += Utf8::Encode(buffer,
4568                                  character,
4569                                  last_character,
4570                                  replace_invalid_utf8_);
4571           last_character = character;
4572           DCHECK(capacity_ == -1 || (buffer - start_) <= capacity_);
4573         }
4574       }
4575       // Array is fully written. Exit.
4576       if (fast_length == length) {
4577         // Write state back out to object.
4578         last_character_ = last_character;
4579         buffer_ = buffer;
4580         utf16_chars_read_ += length;
4581         return;
4582       }
4583     }
4584     DCHECK(!skip_capacity_check_);
4585     // Slow loop. Must check capacity on each iteration.
4586     int remaining_capacity = capacity_ - static_cast<int>(buffer - start_);
4587     DCHECK(remaining_capacity >= 0);
4588     for (; i < length && remaining_capacity > 0; i++) {
4589       uint16_t character = *chars++;
4590       // remaining_capacity is <= 3 bytes at this point, so we do not write out
4591       // an umatched lead surrogate.
4592       if (replace_invalid_utf8_ && Utf16::IsLeadSurrogate(character)) {
4593         early_termination_ = true;
4594         break;
4595       }
4596       int written = WriteEndCharacter(character,
4597                                       last_character,
4598                                       remaining_capacity,
4599                                       buffer,
4600                                       replace_invalid_utf8_);
4601       if (written == 0) {
4602         early_termination_ = true;
4603         break;
4604       }
4605       buffer += written;
4606       remaining_capacity -= written;
4607       last_character = character;
4608     }
4609     // Write state back out to object.
4610     last_character_ = last_character;
4611     buffer_ = buffer;
4612     utf16_chars_read_ += i;
4613   }
4614
4615   inline bool IsDone() {
4616     return early_termination_;
4617   }
4618
4619   inline void VisitOneByteString(const uint8_t* chars, int length) {
4620     Visit(chars, length);
4621   }
4622
4623   inline void VisitTwoByteString(const uint16_t* chars, int length) {
4624     Visit(chars, length);
4625   }
4626
4627   int CompleteWrite(bool write_null, int* utf16_chars_read_out) {
4628     // Write out number of utf16 characters written to the stream.
4629     if (utf16_chars_read_out != NULL) {
4630       *utf16_chars_read_out = utf16_chars_read_;
4631     }
4632     // Only null terminate if all of the string was written and there's space.
4633     if (write_null &&
4634         !early_termination_ &&
4635         (capacity_ == -1 || (buffer_ - start_) < capacity_)) {
4636       *buffer_++ = '\0';
4637     }
4638     return static_cast<int>(buffer_ - start_);
4639   }
4640
4641  private:
4642   bool early_termination_;
4643   int last_character_;
4644   char* buffer_;
4645   char* const start_;
4646   int capacity_;
4647   bool const skip_capacity_check_;
4648   bool const replace_invalid_utf8_;
4649   int utf16_chars_read_;
4650   DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8WriterVisitor);
4651 };
4652
4653
4654 static bool RecursivelySerializeToUtf8(i::String* current,
4655                                        Utf8WriterVisitor* writer,
4656                                        int recursion_budget) {
4657   while (!writer->IsDone()) {
4658     i::ConsString* cons_string = i::String::VisitFlat(writer, current);
4659     if (cons_string == NULL) return true;  // Leaf node.
4660     if (recursion_budget <= 0) return false;
4661     // Must write the left branch first.
4662     i::String* first = cons_string->first();
4663     bool success = RecursivelySerializeToUtf8(first,
4664                                               writer,
4665                                               recursion_budget - 1);
4666     if (!success) return false;
4667     // Inline tail recurse for right branch.
4668     current = cons_string->second();
4669   }
4670   return true;
4671 }
4672
4673
4674 int String::WriteUtf8(char* buffer,
4675                       int capacity,
4676                       int* nchars_ref,
4677                       int options) const {
4678   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
4679   LOG_API(isolate, "String::WriteUtf8");
4680   ENTER_V8(isolate);
4681   i::Handle<i::String> str = Utils::OpenHandle(this);
4682   if (options & HINT_MANY_WRITES_EXPECTED) {
4683     str = i::String::Flatten(str);  // Flatten the string for efficiency.
4684   }
4685   const int string_length = str->length();
4686   bool write_null = !(options & NO_NULL_TERMINATION);
4687   bool replace_invalid_utf8 = (options & REPLACE_INVALID_UTF8);
4688   int max16BitCodeUnitSize = unibrow::Utf8::kMax16BitCodeUnitSize;
4689   // First check if we can just write the string without checking capacity.
4690   if (capacity == -1 || capacity / max16BitCodeUnitSize >= string_length) {
4691     Utf8WriterVisitor writer(buffer, capacity, true, replace_invalid_utf8);
4692     const int kMaxRecursion = 100;
4693     bool success = RecursivelySerializeToUtf8(*str, &writer, kMaxRecursion);
4694     if (success) return writer.CompleteWrite(write_null, nchars_ref);
4695   } else if (capacity >= string_length) {
4696     // First check that the buffer is large enough.
4697     int utf8_bytes = v8::Utf8Length(*str, str->GetIsolate());
4698     if (utf8_bytes <= capacity) {
4699       // ASCII fast path.
4700       if (utf8_bytes == string_length) {
4701         WriteOneByte(reinterpret_cast<uint8_t*>(buffer), 0, capacity, options);
4702         if (nchars_ref != NULL) *nchars_ref = string_length;
4703         if (write_null && (utf8_bytes+1 <= capacity)) {
4704           return string_length + 1;
4705         }
4706         return string_length;
4707       }
4708       if (write_null && (utf8_bytes+1 > capacity)) {
4709         options |= NO_NULL_TERMINATION;
4710       }
4711       // Recurse once without a capacity limit.
4712       // This will get into the first branch above.
4713       // TODO(dcarney) Check max left rec. in Utf8Length and fall through.
4714       return WriteUtf8(buffer, -1, nchars_ref, options);
4715     }
4716   }
4717   // Recursive slow path can potentially be unreasonable slow. Flatten.
4718   str = i::String::Flatten(str);
4719   Utf8WriterVisitor writer(buffer, capacity, false, replace_invalid_utf8);
4720   i::String::VisitFlat(&writer, *str);
4721   return writer.CompleteWrite(write_null, nchars_ref);
4722 }
4723
4724
4725 template<typename CharType>
4726 static inline int WriteHelper(const String* string,
4727                               CharType* buffer,
4728                               int start,
4729                               int length,
4730                               int options) {
4731   i::Isolate* isolate = Utils::OpenHandle(string)->GetIsolate();
4732   LOG_API(isolate, "String::Write");
4733   ENTER_V8(isolate);
4734   DCHECK(start >= 0 && length >= -1);
4735   i::Handle<i::String> str = Utils::OpenHandle(string);
4736   isolate->string_tracker()->RecordWrite(str);
4737   if (options & String::HINT_MANY_WRITES_EXPECTED) {
4738     // Flatten the string for efficiency.  This applies whether we are
4739     // using StringCharacterStream or Get(i) to access the characters.
4740     str = i::String::Flatten(str);
4741   }
4742   int end = start + length;
4743   if ((length == -1) || (length > str->length() - start) )
4744     end = str->length();
4745   if (end < 0) return 0;
4746   i::String::WriteToFlat(*str, buffer, start, end);
4747   if (!(options & String::NO_NULL_TERMINATION) &&
4748       (length == -1 || end - start < length)) {
4749     buffer[end - start] = '\0';
4750   }
4751   return end - start;
4752 }
4753
4754
4755 int String::WriteOneByte(uint8_t* buffer,
4756                          int start,
4757                          int length,
4758                          int options) const {
4759   return WriteHelper(this, buffer, start, length, options);
4760 }
4761
4762
4763 int String::Write(uint16_t* buffer,
4764                   int start,
4765                   int length,
4766                   int options) const {
4767   return WriteHelper(this, buffer, start, length, options);
4768 }
4769
4770
4771 bool v8::String::IsExternal() const {
4772   i::Handle<i::String> str = Utils::OpenHandle(this);
4773   EnsureInitializedForIsolate(str->GetIsolate(), "v8::String::IsExternal()");
4774   return i::StringShape(*str).IsExternalTwoByte();
4775 }
4776
4777
4778 bool v8::String::IsExternalAscii() const {
4779   i::Handle<i::String> str = Utils::OpenHandle(this);
4780   return i::StringShape(*str).IsExternalAscii();
4781 }
4782
4783
4784 void v8::String::VerifyExternalStringResource(
4785     v8::String::ExternalStringResource* value) const {
4786   i::Handle<i::String> str = Utils::OpenHandle(this);
4787   const v8::String::ExternalStringResource* expected;
4788   if (i::StringShape(*str).IsExternalTwoByte()) {
4789     const void* resource =
4790         i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4791     expected = reinterpret_cast<const ExternalStringResource*>(resource);
4792   } else {
4793     expected = NULL;
4794   }
4795   CHECK_EQ(expected, value);
4796 }
4797
4798 void v8::String::VerifyExternalStringResourceBase(
4799     v8::String::ExternalStringResourceBase* value, Encoding encoding) const {
4800   i::Handle<i::String> str = Utils::OpenHandle(this);
4801   const v8::String::ExternalStringResourceBase* expected;
4802   Encoding expectedEncoding;
4803   if (i::StringShape(*str).IsExternalAscii()) {
4804     const void* resource =
4805         i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4806     expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4807     expectedEncoding = ASCII_ENCODING;
4808   } else if (i::StringShape(*str).IsExternalTwoByte()) {
4809     const void* resource =
4810         i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
4811     expected = reinterpret_cast<const ExternalStringResourceBase*>(resource);
4812     expectedEncoding = TWO_BYTE_ENCODING;
4813   } else {
4814     expected = NULL;
4815     expectedEncoding = str->IsOneByteRepresentation() ? ASCII_ENCODING
4816         : TWO_BYTE_ENCODING;
4817   }
4818   CHECK_EQ(expected, value);
4819   CHECK_EQ(expectedEncoding, encoding);
4820 }
4821
4822 const v8::String::ExternalAsciiStringResource*
4823 v8::String::GetExternalAsciiStringResource() const {
4824   i::Handle<i::String> str = Utils::OpenHandle(this);
4825   if (i::StringShape(*str).IsExternalAscii()) {
4826     const void* resource =
4827         i::Handle<i::ExternalAsciiString>::cast(str)->resource();
4828     return reinterpret_cast<const ExternalAsciiStringResource*>(resource);
4829   } else {
4830     return NULL;
4831   }
4832 }
4833
4834
4835 Local<Value> Symbol::Name() const {
4836   i::Handle<i::Symbol> sym = Utils::OpenHandle(this);
4837   i::Handle<i::Object> name(sym->name(), sym->GetIsolate());
4838   return Utils::ToLocal(name);
4839 }
4840
4841
4842 Local<Value> Private::Name() const {
4843   return reinterpret_cast<const Symbol*>(this)->Name();
4844 }
4845
4846
4847 double Number::Value() const {
4848   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4849   return obj->Number();
4850 }
4851
4852
4853 bool Boolean::Value() const {
4854   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4855   return obj->IsTrue();
4856 }
4857
4858
4859 int64_t Integer::Value() const {
4860   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4861   if (obj->IsSmi()) {
4862     return i::Smi::cast(*obj)->value();
4863   } else {
4864     return static_cast<int64_t>(obj->Number());
4865   }
4866 }
4867
4868
4869 int32_t Int32::Value() const {
4870   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4871   if (obj->IsSmi()) {
4872     return i::Smi::cast(*obj)->value();
4873   } else {
4874     return static_cast<int32_t>(obj->Number());
4875   }
4876 }
4877
4878
4879 uint32_t Uint32::Value() const {
4880   i::Handle<i::Object> obj = Utils::OpenHandle(this);
4881   if (obj->IsSmi()) {
4882     return i::Smi::cast(*obj)->value();
4883   } else {
4884     return static_cast<uint32_t>(obj->Number());
4885   }
4886 }
4887
4888
4889 int v8::Object::InternalFieldCount() {
4890   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4891   return obj->GetInternalFieldCount();
4892 }
4893
4894
4895 static bool InternalFieldOK(i::Handle<i::JSObject> obj,
4896                             int index,
4897                             const char* location) {
4898   return Utils::ApiCheck(index < obj->GetInternalFieldCount(),
4899                          location,
4900                          "Internal field out of bounds");
4901 }
4902
4903
4904 Local<Value> v8::Object::SlowGetInternalField(int index) {
4905   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4906   const char* location = "v8::Object::GetInternalField()";
4907   if (!InternalFieldOK(obj, index, location)) return Local<Value>();
4908   i::Handle<i::Object> value(obj->GetInternalField(index), obj->GetIsolate());
4909   return Utils::ToLocal(value);
4910 }
4911
4912
4913 void v8::Object::SetInternalField(int index, v8::Handle<Value> value) {
4914   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4915   const char* location = "v8::Object::SetInternalField()";
4916   if (!InternalFieldOK(obj, index, location)) return;
4917   i::Handle<i::Object> val = Utils::OpenHandle(*value);
4918   obj->SetInternalField(index, *val);
4919   DCHECK_EQ(value, GetInternalField(index));
4920 }
4921
4922
4923 void* v8::Object::SlowGetAlignedPointerFromInternalField(int index) {
4924   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4925   const char* location = "v8::Object::GetAlignedPointerFromInternalField()";
4926   if (!InternalFieldOK(obj, index, location)) return NULL;
4927   return DecodeSmiToAligned(obj->GetInternalField(index), location);
4928 }
4929
4930
4931 void v8::Object::SetAlignedPointerInInternalField(int index, void* value) {
4932   i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
4933   const char* location = "v8::Object::SetAlignedPointerInInternalField()";
4934   if (!InternalFieldOK(obj, index, location)) return;
4935   obj->SetInternalField(index, EncodeAlignedAsSmi(value, location));
4936   DCHECK_EQ(value, GetAlignedPointerFromInternalField(index));
4937 }
4938
4939
4940 static void* ExternalValue(i::Object* obj) {
4941   // Obscure semantics for undefined, but somehow checked in our unit tests...
4942   if (obj->IsUndefined()) return NULL;
4943   i::Object* foreign = i::JSObject::cast(obj)->GetInternalField(0);
4944   return i::Foreign::cast(foreign)->foreign_address();
4945 }
4946
4947
4948 // --- E n v i r o n m e n t ---
4949
4950
4951 void v8::V8::InitializePlatform(Platform* platform) {
4952   i::V8::InitializePlatform(platform);
4953 }
4954
4955
4956 void v8::V8::ShutdownPlatform() {
4957   i::V8::ShutdownPlatform();
4958 }
4959
4960
4961 bool v8::V8::Initialize() {
4962   i::Isolate* isolate = i::Isolate::UncheckedCurrent();
4963   if (isolate != NULL && isolate->IsInitialized()) {
4964     return true;
4965   }
4966   return InitializeHelper(isolate);
4967 }
4968
4969
4970 void v8::V8::SetEntropySource(EntropySource entropy_source) {
4971   base::RandomNumberGenerator::SetEntropySource(entropy_source);
4972 }
4973
4974
4975 void v8::V8::SetReturnAddressLocationResolver(
4976     ReturnAddressLocationResolver return_address_resolver) {
4977   i::V8::SetReturnAddressLocationResolver(return_address_resolver);
4978 }
4979
4980
4981 bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate,
4982                                   FunctionEntryHook entry_hook) {
4983   DCHECK(ext_isolate != NULL);
4984   DCHECK(entry_hook != NULL);
4985
4986   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(ext_isolate);
4987
4988   // The entry hook can only be set before the Isolate is initialized, as
4989   // otherwise the Isolate's code stubs generated at initialization won't
4990   // contain entry hooks.
4991   if (isolate->IsInitialized())
4992     return false;
4993
4994   // Setting an entry hook is a one-way operation, once set, it cannot be
4995   // changed or unset.
4996   if (isolate->function_entry_hook() != NULL)
4997     return false;
4998
4999   isolate->set_function_entry_hook(entry_hook);
5000   return true;
5001 }
5002
5003
5004 void v8::V8::SetJitCodeEventHandler(
5005     JitCodeEventOptions options, JitCodeEventHandler event_handler) {
5006   i::Isolate* isolate = i::Isolate::Current();
5007   // Ensure that logging is initialized for our isolate.
5008   isolate->InitializeLoggingAndCounters();
5009   isolate->logger()->SetCodeEventHandler(options, event_handler);
5010 }
5011
5012 void v8::V8::SetArrayBufferAllocator(
5013     ArrayBuffer::Allocator* allocator) {
5014   if (!Utils::ApiCheck(i::V8::ArrayBufferAllocator() == NULL,
5015                        "v8::V8::SetArrayBufferAllocator",
5016                        "ArrayBufferAllocator might only be set once"))
5017     return;
5018   i::V8::SetArrayBufferAllocator(allocator);
5019 }
5020
5021
5022 bool v8::V8::Dispose() {
5023   i::V8::TearDown();
5024   return true;
5025 }
5026
5027
5028 HeapStatistics::HeapStatistics(): total_heap_size_(0),
5029                                   total_heap_size_executable_(0),
5030                                   total_physical_size_(0),
5031                                   used_heap_size_(0),
5032                                   heap_size_limit_(0) { }
5033
5034
5035 void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) {
5036   i::Isolate* isolate = i::Isolate::Current();
5037   isolate->heap()->VisitExternalResources(visitor);
5038 }
5039
5040
5041 class VisitorAdapter : public i::ObjectVisitor {
5042  public:
5043   explicit VisitorAdapter(PersistentHandleVisitor* visitor)
5044       : visitor_(visitor) {}
5045   virtual void VisitPointers(i::Object** start, i::Object** end) {
5046     UNREACHABLE();
5047   }
5048   virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) {
5049     Value* value = ToApi<Value>(i::Handle<i::Object>(p));
5050     visitor_->VisitPersistentHandle(
5051         reinterpret_cast<Persistent<Value>*>(&value), class_id);
5052   }
5053  private:
5054   PersistentHandleVisitor* visitor_;
5055 };
5056
5057
5058 void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) {
5059   i::Isolate* isolate = i::Isolate::Current();
5060   i::DisallowHeapAllocation no_allocation;
5061
5062   VisitorAdapter visitor_adapter(visitor);
5063   isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter);
5064 }
5065
5066
5067 void v8::V8::VisitHandlesForPartialDependence(
5068     Isolate* exported_isolate, PersistentHandleVisitor* visitor) {
5069   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(exported_isolate);
5070   DCHECK(isolate == i::Isolate::Current());
5071   i::DisallowHeapAllocation no_allocation;
5072
5073   VisitorAdapter visitor_adapter(visitor);
5074   isolate->global_handles()->IterateAllRootsInNewSpaceWithClassIds(
5075       &visitor_adapter);
5076 }
5077
5078
5079 bool v8::V8::InitializeICU(const char* icu_data_file) {
5080   return i::InitializeICU(icu_data_file);
5081 }
5082
5083
5084 const char* v8::V8::GetVersion() {
5085   return i::Version::GetVersion();
5086 }
5087
5088
5089 static i::Handle<i::Context> CreateEnvironment(
5090     i::Isolate* isolate,
5091     v8::ExtensionConfiguration* extensions,
5092     v8::Handle<ObjectTemplate> global_template,
5093     v8::Handle<Value> maybe_global_proxy) {
5094   i::Handle<i::Context> env;
5095
5096   // Enter V8 via an ENTER_V8 scope.
5097   {
5098     ENTER_V8(isolate);
5099     v8::Handle<ObjectTemplate> proxy_template = global_template;
5100     i::Handle<i::FunctionTemplateInfo> proxy_constructor;
5101     i::Handle<i::FunctionTemplateInfo> global_constructor;
5102
5103     if (!global_template.IsEmpty()) {
5104       // Make sure that the global_template has a constructor.
5105       global_constructor = EnsureConstructor(isolate, *global_template);
5106
5107       // Create a fresh template for the global proxy object.
5108       proxy_template = ObjectTemplate::New(
5109           reinterpret_cast<v8::Isolate*>(isolate));
5110       proxy_constructor = EnsureConstructor(isolate, *proxy_template);
5111
5112       // Set the global template to be the prototype template of
5113       // global proxy template.
5114       proxy_constructor->set_prototype_template(
5115           *Utils::OpenHandle(*global_template));
5116
5117       // Migrate security handlers from global_template to
5118       // proxy_template.  Temporarily removing access check
5119       // information from the global template.
5120       if (!global_constructor->access_check_info()->IsUndefined()) {
5121         proxy_constructor->set_access_check_info(
5122             global_constructor->access_check_info());
5123         proxy_constructor->set_needs_access_check(
5124             global_constructor->needs_access_check());
5125         global_constructor->set_needs_access_check(false);
5126         global_constructor->set_access_check_info(
5127             isolate->heap()->undefined_value());
5128       }
5129     }
5130
5131     i::Handle<i::Object> proxy = Utils::OpenHandle(*maybe_global_proxy, true);
5132     i::MaybeHandle<i::JSGlobalProxy> maybe_proxy;
5133     if (!proxy.is_null()) {
5134       maybe_proxy = i::Handle<i::JSGlobalProxy>::cast(proxy);
5135     }
5136     // Create the environment.
5137     env = isolate->bootstrapper()->CreateEnvironment(
5138         maybe_proxy, proxy_template, extensions);
5139
5140     // Restore the access check info on the global template.
5141     if (!global_template.IsEmpty()) {
5142       DCHECK(!global_constructor.is_null());
5143       DCHECK(!proxy_constructor.is_null());
5144       global_constructor->set_access_check_info(
5145           proxy_constructor->access_check_info());
5146       global_constructor->set_needs_access_check(
5147           proxy_constructor->needs_access_check());
5148     }
5149   }
5150   // Leave V8.
5151
5152   return env;
5153 }
5154
5155 Local<Context> v8::Context::New(
5156     v8::Isolate* external_isolate,
5157     v8::ExtensionConfiguration* extensions,
5158     v8::Handle<ObjectTemplate> global_template,
5159     v8::Handle<Value> global_object) {
5160   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate);
5161   EnsureInitializedForIsolate(isolate, "v8::Context::New()");
5162   LOG_API(isolate, "Context::New");
5163   ON_BAILOUT(isolate, "v8::Context::New()", return Local<Context>());
5164   i::HandleScope scope(isolate);
5165   ExtensionConfiguration no_extensions;
5166   if (extensions == NULL) extensions = &no_extensions;
5167   i::Handle<i::Context> env =
5168       CreateEnvironment(isolate, extensions, global_template, global_object);
5169   if (env.is_null()) return Local<Context>();
5170   return Utils::ToLocal(scope.CloseAndEscape(env));
5171 }
5172
5173
5174 void v8::Context::SetSecurityToken(Handle<Value> token) {
5175   i::Isolate* isolate = i::Isolate::Current();
5176   ENTER_V8(isolate);
5177   i::Handle<i::Context> env = Utils::OpenHandle(this);
5178   i::Handle<i::Object> token_handle = Utils::OpenHandle(*token);
5179   env->set_security_token(*token_handle);
5180 }
5181
5182
5183 void v8::Context::UseDefaultSecurityToken() {
5184   i::Isolate* isolate = i::Isolate::Current();
5185   ENTER_V8(isolate);
5186   i::Handle<i::Context> env = Utils::OpenHandle(this);
5187   env->set_security_token(env->global_object());
5188 }
5189
5190
5191 Handle<Value> v8::Context::GetSecurityToken() {
5192   i::Isolate* isolate = i::Isolate::Current();
5193   i::Handle<i::Context> env = Utils::OpenHandle(this);
5194   i::Object* security_token = env->security_token();
5195   i::Handle<i::Object> token_handle(security_token, isolate);
5196   return Utils::ToLocal(token_handle);
5197 }
5198
5199
5200 v8::Isolate* Context::GetIsolate() {
5201   i::Handle<i::Context> env = Utils::OpenHandle(this);
5202   return reinterpret_cast<Isolate*>(env->GetIsolate());
5203 }
5204
5205
5206 v8::Local<v8::Object> Context::Global() {
5207   i::Handle<i::Context> context = Utils::OpenHandle(this);
5208   i::Isolate* isolate = context->GetIsolate();
5209   i::Handle<i::Object> global(context->global_proxy(), isolate);
5210   // TODO(dcarney): This should always return the global proxy
5211   // but can't presently as calls to GetProtoype will return the wrong result.
5212   if (i::Handle<i::JSGlobalProxy>::cast(
5213           global)->IsDetachedFrom(context->global_object())) {
5214     global = i::Handle<i::Object>(context->global_object(), isolate);
5215   }
5216   return Utils::ToLocal(i::Handle<i::JSObject>::cast(global));
5217 }
5218
5219
5220 void Context::DetachGlobal() {
5221   i::Handle<i::Context> context = Utils::OpenHandle(this);
5222   i::Isolate* isolate = context->GetIsolate();
5223   ENTER_V8(isolate);
5224   isolate->bootstrapper()->DetachGlobal(context);
5225 }
5226
5227
5228 void Context::AllowCodeGenerationFromStrings(bool allow) {
5229   i::Handle<i::Context> context = Utils::OpenHandle(this);
5230   i::Isolate* isolate = context->GetIsolate();
5231   ENTER_V8(isolate);
5232   context->set_allow_code_gen_from_strings(
5233       allow ? isolate->heap()->true_value() : isolate->heap()->false_value());
5234 }
5235
5236
5237 bool Context::IsCodeGenerationFromStringsAllowed() {
5238   i::Handle<i::Context> context = Utils::OpenHandle(this);
5239   return !context->allow_code_gen_from_strings()->IsFalse();
5240 }
5241
5242
5243 void Context::SetErrorMessageForCodeGenerationFromStrings(
5244     Handle<String> error) {
5245   i::Handle<i::Context> context = Utils::OpenHandle(this);
5246   i::Handle<i::String> error_handle = Utils::OpenHandle(*error);
5247   context->set_error_message_for_code_gen_from_strings(*error_handle);
5248 }
5249
5250
5251 Local<v8::Object> ObjectTemplate::NewInstance() {
5252   i::Isolate* isolate = i::Isolate::Current();
5253   ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()",
5254              return Local<v8::Object>());
5255   LOG_API(isolate, "ObjectTemplate::NewInstance");
5256   ENTER_V8(isolate);
5257   EXCEPTION_PREAMBLE(isolate);
5258   i::Handle<i::Object> obj;
5259   has_pending_exception = !i::Execution::InstantiateObject(
5260       Utils::OpenHandle(this)).ToHandle(&obj);
5261   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>());
5262   return Utils::ToLocal(i::Handle<i::JSObject>::cast(obj));
5263 }
5264
5265
5266 Local<v8::Function> FunctionTemplate::GetFunction() {
5267   i::Isolate* isolate = i::Isolate::Current();
5268   ON_BAILOUT(isolate, "v8::FunctionTemplate::GetFunction()",
5269              return Local<v8::Function>());
5270   LOG_API(isolate, "FunctionTemplate::GetFunction");
5271   ENTER_V8(isolate);
5272   EXCEPTION_PREAMBLE(isolate);
5273   i::Handle<i::Object> obj;
5274   has_pending_exception = !i::Execution::InstantiateFunction(
5275       Utils::OpenHandle(this)).ToHandle(&obj);
5276   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Function>());
5277   return Utils::ToLocal(i::Handle<i::JSFunction>::cast(obj));
5278 }
5279
5280
5281 bool FunctionTemplate::HasInstance(v8::Handle<v8::Value> value) {
5282   ON_BAILOUT(i::Isolate::Current(), "v8::FunctionTemplate::HasInstanceOf()",
5283              return false);
5284   i::Object* obj = *Utils::OpenHandle(*value);
5285   return Utils::OpenHandle(this)->IsTemplateFor(obj);
5286 }
5287
5288
5289 Local<External> v8::External::New(Isolate* isolate, void* value) {
5290   STATIC_ASSERT(sizeof(value) == sizeof(i::Address));
5291   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5292   EnsureInitializedForIsolate(i_isolate, "v8::External::New()");
5293   LOG_API(i_isolate, "External::New");
5294   ENTER_V8(i_isolate);
5295   i::Handle<i::JSObject> external = i_isolate->factory()->NewExternal(value);
5296   return Utils::ExternalToLocal(external);
5297 }
5298
5299
5300 void* External::Value() const {
5301   return ExternalValue(*Utils::OpenHandle(this));
5302 }
5303
5304
5305 // anonymous namespace for string creation helper functions
5306 namespace {
5307
5308 inline int StringLength(const char* string) {
5309   return i::StrLength(string);
5310 }
5311
5312
5313 inline int StringLength(const uint8_t* string) {
5314   return i::StrLength(reinterpret_cast<const char*>(string));
5315 }
5316
5317
5318 inline int StringLength(const uint16_t* string) {
5319   int length = 0;
5320   while (string[length] != '\0')
5321     length++;
5322   return length;
5323 }
5324
5325
5326 MUST_USE_RESULT
5327 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5328                                            String::NewStringType type,
5329                                            i::Vector<const char> string) {
5330   if (type == String::kInternalizedString) {
5331     return factory->InternalizeUtf8String(string);
5332   }
5333   return factory->NewStringFromUtf8(string);
5334 }
5335
5336
5337 MUST_USE_RESULT
5338 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5339                                            String::NewStringType type,
5340                                            i::Vector<const uint8_t> string) {
5341   if (type == String::kInternalizedString) {
5342     return factory->InternalizeOneByteString(string);
5343   }
5344   return factory->NewStringFromOneByte(string);
5345 }
5346
5347
5348 MUST_USE_RESULT
5349 inline i::MaybeHandle<i::String> NewString(i::Factory* factory,
5350                                            String::NewStringType type,
5351                                            i::Vector<const uint16_t> string) {
5352   if (type == String::kInternalizedString) {
5353     return factory->InternalizeTwoByteString(string);
5354   }
5355   return factory->NewStringFromTwoByte(string);
5356 }
5357
5358
5359 template<typename Char>
5360 inline Local<String> NewString(Isolate* v8_isolate,
5361                                const char* location,
5362                                const char* env,
5363                                const Char* data,
5364                                String::NewStringType type,
5365                                int length) {
5366   i::Isolate* isolate = reinterpret_cast<internal::Isolate*>(v8_isolate);
5367   EnsureInitializedForIsolate(isolate, location);
5368   LOG_API(isolate, env);
5369   if (length == 0 && type != String::kUndetectableString) {
5370     return String::Empty(v8_isolate);
5371   }
5372   ENTER_V8(isolate);
5373   if (length == -1) length = StringLength(data);
5374   // We do not expect this to fail. Change this if it does.
5375   i::Handle<i::String> result = NewString(
5376       isolate->factory(),
5377       type,
5378       i::Vector<const Char>(data, length)).ToHandleChecked();
5379   if (type == String::kUndetectableString) {
5380     result->MarkAsUndetectable();
5381   }
5382   return Utils::ToLocal(result);
5383 }
5384
5385 }  // anonymous namespace
5386
5387
5388 Local<String> String::NewFromUtf8(Isolate* isolate,
5389                                   const char* data,
5390                                   NewStringType type,
5391                                   int length) {
5392   return NewString(isolate,
5393                    "v8::String::NewFromUtf8()",
5394                    "String::NewFromUtf8",
5395                    data,
5396                    type,
5397                    length);
5398 }
5399
5400
5401 Local<String> String::NewFromOneByte(Isolate* isolate,
5402                                      const uint8_t* data,
5403                                      NewStringType type,
5404                                      int length) {
5405   return NewString(isolate,
5406                    "v8::String::NewFromOneByte()",
5407                    "String::NewFromOneByte",
5408                    data,
5409                    type,
5410                    length);
5411 }
5412
5413
5414 Local<String> String::NewFromTwoByte(Isolate* isolate,
5415                                      const uint16_t* data,
5416                                      NewStringType type,
5417                                      int length) {
5418   return NewString(isolate,
5419                    "v8::String::NewFromTwoByte()",
5420                    "String::NewFromTwoByte",
5421                    data,
5422                    type,
5423                    length);
5424 }
5425
5426
5427 Local<String> v8::String::Concat(Handle<String> left, Handle<String> right) {
5428   i::Handle<i::String> left_string = Utils::OpenHandle(*left);
5429   i::Isolate* isolate = left_string->GetIsolate();
5430   EnsureInitializedForIsolate(isolate, "v8::String::New()");
5431   LOG_API(isolate, "String::New(char)");
5432   ENTER_V8(isolate);
5433   i::Handle<i::String> right_string = Utils::OpenHandle(*right);
5434   // We do not expect this to fail. Change this if it does.
5435   i::Handle<i::String> result = isolate->factory()->NewConsString(
5436       left_string, right_string).ToHandleChecked();
5437   return Utils::ToLocal(result);
5438 }
5439
5440
5441 static i::Handle<i::String> NewExternalStringHandle(
5442     i::Isolate* isolate,
5443     v8::String::ExternalStringResource* resource) {
5444   // We do not expect this to fail. Change this if it does.
5445   return isolate->factory()->NewExternalStringFromTwoByte(
5446       resource).ToHandleChecked();
5447 }
5448
5449
5450 static i::Handle<i::String> NewExternalAsciiStringHandle(
5451     i::Isolate* isolate,
5452     v8::String::ExternalAsciiStringResource* resource) {
5453   // We do not expect this to fail. Change this if it does.
5454   return isolate->factory()->NewExternalStringFromAscii(
5455       resource).ToHandleChecked();
5456 }
5457
5458
5459 Local<String> v8::String::NewExternal(
5460     Isolate* isolate,
5461     v8::String::ExternalStringResource* resource) {
5462   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5463   EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
5464   LOG_API(i_isolate, "String::NewExternal");
5465   ENTER_V8(i_isolate);
5466   CHECK(resource && resource->data());
5467   i::Handle<i::String> result = NewExternalStringHandle(i_isolate, resource);
5468   i_isolate->heap()->external_string_table()->AddString(*result);
5469   return Utils::ToLocal(result);
5470 }
5471
5472
5473 bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
5474   i::Handle<i::String> obj = Utils::OpenHandle(this);
5475   i::Isolate* isolate = obj->GetIsolate();
5476   if (i::StringShape(*obj).IsExternal()) {
5477     return false;  // Already an external string.
5478   }
5479   ENTER_V8(isolate);
5480   if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5481     return false;
5482   }
5483   if (isolate->heap()->IsInGCPostProcessing()) {
5484     return false;
5485   }
5486   CHECK(resource && resource->data());
5487
5488   bool result = obj->MakeExternal(resource);
5489   // Assert that if CanMakeExternal(), then externalizing actually succeeds.
5490   DCHECK(!CanMakeExternal() || result);
5491   if (result) {
5492     DCHECK(obj->IsExternalString());
5493     isolate->heap()->external_string_table()->AddString(*obj);
5494   }
5495   return result;
5496 }
5497
5498
5499 Local<String> v8::String::NewExternal(
5500     Isolate* isolate,
5501     v8::String::ExternalAsciiStringResource* resource) {
5502   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5503   EnsureInitializedForIsolate(i_isolate, "v8::String::NewExternal()");
5504   LOG_API(i_isolate, "String::NewExternal");
5505   ENTER_V8(i_isolate);
5506   CHECK(resource && resource->data());
5507   i::Handle<i::String> result =
5508       NewExternalAsciiStringHandle(i_isolate, resource);
5509   i_isolate->heap()->external_string_table()->AddString(*result);
5510   return Utils::ToLocal(result);
5511 }
5512
5513
5514 bool v8::String::MakeExternal(
5515     v8::String::ExternalAsciiStringResource* resource) {
5516   i::Handle<i::String> obj = Utils::OpenHandle(this);
5517   i::Isolate* isolate = obj->GetIsolate();
5518   if (i::StringShape(*obj).IsExternal()) {
5519     return false;  // Already an external string.
5520   }
5521   ENTER_V8(isolate);
5522   if (isolate->string_tracker()->IsFreshUnusedString(obj)) {
5523     return false;
5524   }
5525   if (isolate->heap()->IsInGCPostProcessing()) {
5526     return false;
5527   }
5528   CHECK(resource && resource->data());
5529
5530   bool result = obj->MakeExternal(resource);
5531   // Assert that if CanMakeExternal(), then externalizing actually succeeds.
5532   DCHECK(!CanMakeExternal() || result);
5533   if (result) {
5534     DCHECK(obj->IsExternalString());
5535     isolate->heap()->external_string_table()->AddString(*obj);
5536   }
5537   return result;
5538 }
5539
5540
5541 bool v8::String::CanMakeExternal() {
5542   if (!internal::FLAG_clever_optimizations) return false;
5543   i::Handle<i::String> obj = Utils::OpenHandle(this);
5544   i::Isolate* isolate = obj->GetIsolate();
5545
5546   // TODO(yangguo): Externalizing sliced/cons strings allocates.
5547   // This rule can be removed when all code that can
5548   // trigger an access check is handlified and therefore GC safe.
5549   if (isolate->heap()->old_pointer_space()->Contains(*obj)) return false;
5550
5551   if (isolate->string_tracker()->IsFreshUnusedString(obj)) return false;
5552   int size = obj->Size();  // Byte size of the original string.
5553   if (size < i::ExternalString::kShortSize) return false;
5554   i::StringShape shape(*obj);
5555   return !shape.IsExternal();
5556 }
5557
5558
5559 Local<v8::Object> v8::Object::New(Isolate* isolate) {
5560   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5561   EnsureInitializedForIsolate(i_isolate, "v8::Object::New()");
5562   LOG_API(i_isolate, "Object::New");
5563   ENTER_V8(i_isolate);
5564   i::Handle<i::JSObject> obj =
5565       i_isolate->factory()->NewJSObject(i_isolate->object_function());
5566   return Utils::ToLocal(obj);
5567 }
5568
5569
5570 Local<v8::Value> v8::NumberObject::New(Isolate* isolate, double value) {
5571   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5572   EnsureInitializedForIsolate(i_isolate, "v8::NumberObject::New()");
5573   LOG_API(i_isolate, "NumberObject::New");
5574   ENTER_V8(i_isolate);
5575   i::Handle<i::Object> number = i_isolate->factory()->NewNumber(value);
5576   i::Handle<i::Object> obj =
5577       i::Object::ToObject(i_isolate, number).ToHandleChecked();
5578   return Utils::ToLocal(obj);
5579 }
5580
5581
5582 double v8::NumberObject::ValueOf() const {
5583   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5584   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5585   i::Isolate* isolate = jsvalue->GetIsolate();
5586   LOG_API(isolate, "NumberObject::NumberValue");
5587   return jsvalue->value()->Number();
5588 }
5589
5590
5591 Local<v8::Value> v8::BooleanObject::New(bool value) {
5592   i::Isolate* isolate = i::Isolate::Current();
5593   EnsureInitializedForIsolate(isolate, "v8::BooleanObject::New()");
5594   LOG_API(isolate, "BooleanObject::New");
5595   ENTER_V8(isolate);
5596   i::Handle<i::Object> boolean(value
5597                                ? isolate->heap()->true_value()
5598                                : isolate->heap()->false_value(),
5599                                isolate);
5600   i::Handle<i::Object> obj =
5601       i::Object::ToObject(isolate, boolean).ToHandleChecked();
5602   return Utils::ToLocal(obj);
5603 }
5604
5605
5606 bool v8::BooleanObject::ValueOf() const {
5607   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5608   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5609   i::Isolate* isolate = jsvalue->GetIsolate();
5610   LOG_API(isolate, "BooleanObject::BooleanValue");
5611   return jsvalue->value()->IsTrue();
5612 }
5613
5614
5615 Local<v8::Value> v8::StringObject::New(Handle<String> value) {
5616   i::Handle<i::String> string = Utils::OpenHandle(*value);
5617   i::Isolate* isolate = string->GetIsolate();
5618   EnsureInitializedForIsolate(isolate, "v8::StringObject::New()");
5619   LOG_API(isolate, "StringObject::New");
5620   ENTER_V8(isolate);
5621   i::Handle<i::Object> obj =
5622       i::Object::ToObject(isolate, string).ToHandleChecked();
5623   return Utils::ToLocal(obj);
5624 }
5625
5626
5627 Local<v8::String> v8::StringObject::ValueOf() const {
5628   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5629   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5630   i::Isolate* isolate = jsvalue->GetIsolate();
5631   LOG_API(isolate, "StringObject::StringValue");
5632   return Utils::ToLocal(
5633       i::Handle<i::String>(i::String::cast(jsvalue->value())));
5634 }
5635
5636
5637 Local<v8::Value> v8::SymbolObject::New(Isolate* isolate, Handle<Symbol> value) {
5638   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5639   EnsureInitializedForIsolate(i_isolate, "v8::SymbolObject::New()");
5640   LOG_API(i_isolate, "SymbolObject::New");
5641   ENTER_V8(i_isolate);
5642   i::Handle<i::Object> obj = i::Object::ToObject(
5643       i_isolate, Utils::OpenHandle(*value)).ToHandleChecked();
5644   return Utils::ToLocal(obj);
5645 }
5646
5647
5648 Local<v8::Symbol> v8::SymbolObject::ValueOf() const {
5649   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5650   i::Handle<i::JSValue> jsvalue = i::Handle<i::JSValue>::cast(obj);
5651   i::Isolate* isolate = jsvalue->GetIsolate();
5652   LOG_API(isolate, "SymbolObject::SymbolValue");
5653   return Utils::ToLocal(
5654       i::Handle<i::Symbol>(i::Symbol::cast(jsvalue->value())));
5655 }
5656
5657
5658 Local<v8::Value> v8::Date::New(Isolate* isolate, double time) {
5659   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5660   EnsureInitializedForIsolate(i_isolate, "v8::Date::New()");
5661   LOG_API(i_isolate, "Date::New");
5662   if (std::isnan(time)) {
5663     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
5664     time = base::OS::nan_value();
5665   }
5666   ENTER_V8(i_isolate);
5667   EXCEPTION_PREAMBLE(i_isolate);
5668   i::Handle<i::Object> obj;
5669   has_pending_exception = !i::Execution::NewDate(
5670       i_isolate, time).ToHandle(&obj);
5671   EXCEPTION_BAILOUT_CHECK(i_isolate, Local<v8::Value>());
5672   return Utils::ToLocal(obj);
5673 }
5674
5675
5676 double v8::Date::ValueOf() const {
5677   i::Handle<i::Object> obj = Utils::OpenHandle(this);
5678   i::Handle<i::JSDate> jsdate = i::Handle<i::JSDate>::cast(obj);
5679   i::Isolate* isolate = jsdate->GetIsolate();
5680   LOG_API(isolate, "Date::NumberValue");
5681   return jsdate->value()->Number();
5682 }
5683
5684
5685 void v8::Date::DateTimeConfigurationChangeNotification(Isolate* isolate) {
5686   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5687   if (!i_isolate->IsInitialized()) return;
5688   ON_BAILOUT(i_isolate, "v8::Date::DateTimeConfigurationChangeNotification()",
5689              return);
5690   LOG_API(i_isolate, "Date::DateTimeConfigurationChangeNotification");
5691   ENTER_V8(i_isolate);
5692
5693   i_isolate->date_cache()->ResetDateCache();
5694
5695   if (!i_isolate->eternal_handles()->Exists(
5696           i::EternalHandles::DATE_CACHE_VERSION)) {
5697     return;
5698   }
5699   i::Handle<i::FixedArray> date_cache_version =
5700       i::Handle<i::FixedArray>::cast(i_isolate->eternal_handles()->GetSingleton(
5701           i::EternalHandles::DATE_CACHE_VERSION));
5702   DCHECK_EQ(1, date_cache_version->length());
5703   CHECK(date_cache_version->get(0)->IsSmi());
5704   date_cache_version->set(
5705       0,
5706       i::Smi::FromInt(i::Smi::cast(date_cache_version->get(0))->value() + 1));
5707 }
5708
5709
5710 static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
5711   i::Isolate* isolate = i::Isolate::Current();
5712   uint8_t flags_buf[3];
5713   int num_flags = 0;
5714   if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
5715   if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
5716   if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
5717   DCHECK(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
5718   return isolate->factory()->InternalizeOneByteString(
5719       i::Vector<const uint8_t>(flags_buf, num_flags));
5720 }
5721
5722
5723 Local<v8::RegExp> v8::RegExp::New(Handle<String> pattern,
5724                                   Flags flags) {
5725   i::Isolate* isolate = Utils::OpenHandle(*pattern)->GetIsolate();
5726   EnsureInitializedForIsolate(isolate, "v8::RegExp::New()");
5727   LOG_API(isolate, "RegExp::New");
5728   ENTER_V8(isolate);
5729   EXCEPTION_PREAMBLE(isolate);
5730   i::Handle<i::JSRegExp> obj;
5731   has_pending_exception = !i::Execution::NewJSRegExp(
5732       Utils::OpenHandle(*pattern),
5733       RegExpFlagsToString(flags)).ToHandle(&obj);
5734   EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::RegExp>());
5735   return Utils::ToLocal(i::Handle<i::JSRegExp>::cast(obj));
5736 }
5737
5738
5739 Local<v8::String> v8::RegExp::GetSource() const {
5740   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5741   return Utils::ToLocal(i::Handle<i::String>(obj->Pattern()));
5742 }
5743
5744
5745 // Assert that the static flags cast in GetFlags is valid.
5746 #define REGEXP_FLAG_ASSERT_EQ(api_flag, internal_flag)          \
5747   STATIC_ASSERT(static_cast<int>(v8::RegExp::api_flag) ==       \
5748                 static_cast<int>(i::JSRegExp::internal_flag))
5749 REGEXP_FLAG_ASSERT_EQ(kNone, NONE);
5750 REGEXP_FLAG_ASSERT_EQ(kGlobal, GLOBAL);
5751 REGEXP_FLAG_ASSERT_EQ(kIgnoreCase, IGNORE_CASE);
5752 REGEXP_FLAG_ASSERT_EQ(kMultiline, MULTILINE);
5753 #undef REGEXP_FLAG_ASSERT_EQ
5754
5755 v8::RegExp::Flags v8::RegExp::GetFlags() const {
5756   i::Handle<i::JSRegExp> obj = Utils::OpenHandle(this);
5757   return static_cast<RegExp::Flags>(obj->GetFlags().value());
5758 }
5759
5760
5761 Local<v8::Array> v8::Array::New(Isolate* isolate, int length) {
5762   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5763   EnsureInitializedForIsolate(i_isolate, "v8::Array::New()");
5764   LOG_API(i_isolate, "Array::New");
5765   ENTER_V8(i_isolate);
5766   int real_length = length > 0 ? length : 0;
5767   i::Handle<i::JSArray> obj = i_isolate->factory()->NewJSArray(real_length);
5768   i::Handle<i::Object> length_obj =
5769       i_isolate->factory()->NewNumberFromInt(real_length);
5770   obj->set_length(*length_obj);
5771   return Utils::ToLocal(obj);
5772 }
5773
5774
5775 uint32_t v8::Array::Length() const {
5776   i::Handle<i::JSArray> obj = Utils::OpenHandle(this);
5777   i::Object* length = obj->length();
5778   if (length->IsSmi()) {
5779     return i::Smi::cast(length)->value();
5780   } else {
5781     return static_cast<uint32_t>(length->Number());
5782   }
5783 }
5784
5785
5786 Local<Object> Array::CloneElementAt(uint32_t index) {
5787   i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
5788   ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>());
5789   i::Handle<i::JSObject> self = Utils::OpenHandle(this);
5790   if (!self->HasFastObjectElements()) {
5791     return Local<Object>();
5792   }
5793   i::FixedArray* elms = i::FixedArray::cast(self->elements());
5794   i::Object* paragon = elms->get(index);
5795   if (!paragon->IsJSObject()) {
5796     return Local<Object>();
5797   }
5798   i::Handle<i::JSObject> paragon_handle(i::JSObject::cast(paragon));
5799   EXCEPTION_PREAMBLE(isolate);
5800   ENTER_V8(isolate);
5801   i::Handle<i::JSObject> result =
5802       isolate->factory()->CopyJSObject(paragon_handle);
5803   has_pending_exception = result.is_null();
5804   EXCEPTION_BAILOUT_CHECK(isolate, Local<Object>());
5805   return Utils::ToLocal(result);
5806 }
5807
5808
5809 bool Value::IsPromise() const {
5810   i::Handle<i::Object> val = Utils::OpenHandle(this);
5811   if (!val->IsJSObject()) return false;
5812   i::Handle<i::JSObject> obj = i::Handle<i::JSObject>::cast(val);
5813   i::Isolate* isolate = obj->GetIsolate();
5814   LOG_API(isolate, "IsPromise");
5815   ENTER_V8(isolate);
5816   EXCEPTION_PREAMBLE(isolate);
5817   i::Handle<i::Object> argv[] = { obj };
5818   i::Handle<i::Object> b;
5819   has_pending_exception = !i::Execution::Call(
5820       isolate,
5821       isolate->is_promise(),
5822       isolate->factory()->undefined_value(),
5823       ARRAY_SIZE(argv), argv,
5824       false).ToHandle(&b);
5825   EXCEPTION_BAILOUT_CHECK(isolate, false);
5826   return b->BooleanValue();
5827 }
5828
5829
5830 Local<Promise::Resolver> Promise::Resolver::New(Isolate* v8_isolate) {
5831   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate);
5832   LOG_API(isolate, "Promise::Resolver::New");
5833   ENTER_V8(isolate);
5834   EXCEPTION_PREAMBLE(isolate);
5835   i::Handle<i::Object> result;
5836   has_pending_exception = !i::Execution::Call(
5837       isolate,
5838       isolate->promise_create(),
5839       isolate->factory()->undefined_value(),
5840       0, NULL,
5841       false).ToHandle(&result);
5842   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise::Resolver>());
5843   return Local<Promise::Resolver>::Cast(Utils::ToLocal(result));
5844 }
5845
5846
5847 Local<Promise> Promise::Resolver::GetPromise() {
5848   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5849   return Local<Promise>::Cast(Utils::ToLocal(promise));
5850 }
5851
5852
5853 void Promise::Resolver::Resolve(Handle<Value> value) {
5854   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5855   i::Isolate* isolate = promise->GetIsolate();
5856   LOG_API(isolate, "Promise::Resolver::Resolve");
5857   ENTER_V8(isolate);
5858   EXCEPTION_PREAMBLE(isolate);
5859   i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5860   has_pending_exception = i::Execution::Call(
5861       isolate,
5862       isolate->promise_resolve(),
5863       isolate->factory()->undefined_value(),
5864       ARRAY_SIZE(argv), argv,
5865       false).is_null();
5866   EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5867 }
5868
5869
5870 void Promise::Resolver::Reject(Handle<Value> value) {
5871   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5872   i::Isolate* isolate = promise->GetIsolate();
5873   LOG_API(isolate, "Promise::Resolver::Reject");
5874   ENTER_V8(isolate);
5875   EXCEPTION_PREAMBLE(isolate);
5876   i::Handle<i::Object> argv[] = { promise, Utils::OpenHandle(*value) };
5877   has_pending_exception = i::Execution::Call(
5878       isolate,
5879       isolate->promise_reject(),
5880       isolate->factory()->undefined_value(),
5881       ARRAY_SIZE(argv), argv,
5882       false).is_null();
5883   EXCEPTION_BAILOUT_CHECK(isolate, /* void */ ;);
5884 }
5885
5886
5887 Local<Promise> Promise::Chain(Handle<Function> handler) {
5888   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5889   i::Isolate* isolate = promise->GetIsolate();
5890   LOG_API(isolate, "Promise::Chain");
5891   ENTER_V8(isolate);
5892   EXCEPTION_PREAMBLE(isolate);
5893   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5894   i::Handle<i::Object> result;
5895   has_pending_exception = !i::Execution::Call(
5896       isolate,
5897       isolate->promise_chain(),
5898       promise,
5899       ARRAY_SIZE(argv), argv,
5900       false).ToHandle(&result);
5901   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5902   return Local<Promise>::Cast(Utils::ToLocal(result));
5903 }
5904
5905
5906 Local<Promise> Promise::Catch(Handle<Function> handler) {
5907   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5908   i::Isolate* isolate = promise->GetIsolate();
5909   LOG_API(isolate, "Promise::Catch");
5910   ENTER_V8(isolate);
5911   EXCEPTION_PREAMBLE(isolate);
5912   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5913   i::Handle<i::Object> result;
5914   has_pending_exception = !i::Execution::Call(
5915       isolate,
5916       isolate->promise_catch(),
5917       promise,
5918       ARRAY_SIZE(argv), argv,
5919       false).ToHandle(&result);
5920   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5921   return Local<Promise>::Cast(Utils::ToLocal(result));
5922 }
5923
5924
5925 Local<Promise> Promise::Then(Handle<Function> handler) {
5926   i::Handle<i::JSObject> promise = Utils::OpenHandle(this);
5927   i::Isolate* isolate = promise->GetIsolate();
5928   LOG_API(isolate, "Promise::Then");
5929   ENTER_V8(isolate);
5930   EXCEPTION_PREAMBLE(isolate);
5931   i::Handle<i::Object> argv[] = { Utils::OpenHandle(*handler) };
5932   i::Handle<i::Object> result;
5933   has_pending_exception = !i::Execution::Call(
5934       isolate,
5935       isolate->promise_then(),
5936       promise,
5937       ARRAY_SIZE(argv), argv,
5938       false).ToHandle(&result);
5939   EXCEPTION_BAILOUT_CHECK(isolate, Local<Promise>());
5940   return Local<Promise>::Cast(Utils::ToLocal(result));
5941 }
5942
5943
5944 bool v8::ArrayBuffer::IsExternal() const {
5945   return Utils::OpenHandle(this)->is_external();
5946 }
5947
5948
5949 v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
5950   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5951   Utils::ApiCheck(!obj->is_external(),
5952                   "v8::ArrayBuffer::Externalize",
5953                   "ArrayBuffer already externalized");
5954   obj->set_is_external(true);
5955   size_t byte_length = static_cast<size_t>(obj->byte_length()->Number());
5956   Contents contents;
5957   contents.data_ = obj->backing_store();
5958   contents.byte_length_ = byte_length;
5959   return contents;
5960 }
5961
5962
5963 void v8::ArrayBuffer::Neuter() {
5964   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5965   i::Isolate* isolate = obj->GetIsolate();
5966   Utils::ApiCheck(obj->is_external(),
5967                   "v8::ArrayBuffer::Neuter",
5968                   "Only externalized ArrayBuffers can be neutered");
5969   LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
5970   ENTER_V8(isolate);
5971   i::Runtime::NeuterArrayBuffer(obj);
5972 }
5973
5974
5975 size_t v8::ArrayBuffer::ByteLength() const {
5976   i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this);
5977   return static_cast<size_t>(obj->byte_length()->Number());
5978 }
5979
5980
5981 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, size_t byte_length) {
5982   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5983   EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(size_t)");
5984   LOG_API(i_isolate, "v8::ArrayBuffer::New(size_t)");
5985   ENTER_V8(i_isolate);
5986   i::Handle<i::JSArrayBuffer> obj =
5987       i_isolate->factory()->NewJSArrayBuffer();
5988   i::Runtime::SetupArrayBufferAllocatingData(i_isolate, obj, byte_length);
5989   return Utils::ToLocal(obj);
5990 }
5991
5992
5993 Local<ArrayBuffer> v8::ArrayBuffer::New(Isolate* isolate, void* data,
5994                                         size_t byte_length) {
5995   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
5996   EnsureInitializedForIsolate(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
5997   LOG_API(i_isolate, "v8::ArrayBuffer::New(void*, size_t)");
5998   ENTER_V8(i_isolate);
5999   i::Handle<i::JSArrayBuffer> obj =
6000       i_isolate->factory()->NewJSArrayBuffer();
6001   i::Runtime::SetupArrayBuffer(i_isolate, obj, true, data, byte_length);
6002   return Utils::ToLocal(obj);
6003 }
6004
6005
6006 Local<ArrayBuffer> v8::ArrayBufferView::Buffer() {
6007   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6008   i::Handle<i::JSArrayBuffer> buffer;
6009   if (obj->IsJSDataView()) {
6010     i::Handle<i::JSDataView> data_view(i::JSDataView::cast(*obj));
6011     DCHECK(data_view->buffer()->IsJSArrayBuffer());
6012     buffer = i::handle(i::JSArrayBuffer::cast(data_view->buffer()));
6013   } else {
6014     DCHECK(obj->IsJSTypedArray());
6015     buffer = i::JSTypedArray::cast(*obj)->GetBuffer();
6016   }
6017   return Utils::ToLocal(buffer);
6018 }
6019
6020
6021 size_t v8::ArrayBufferView::ByteOffset() {
6022   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6023   return static_cast<size_t>(obj->byte_offset()->Number());
6024 }
6025
6026
6027 size_t v8::ArrayBufferView::ByteLength() {
6028   i::Handle<i::JSArrayBufferView> obj = Utils::OpenHandle(this);
6029   return static_cast<size_t>(obj->byte_length()->Number());
6030 }
6031
6032
6033 size_t v8::TypedArray::Length() {
6034   i::Handle<i::JSTypedArray> obj = Utils::OpenHandle(this);
6035   return static_cast<size_t>(obj->length()->Number());
6036 }
6037
6038
6039 static inline void SetupArrayBufferView(
6040     i::Isolate* isolate,
6041     i::Handle<i::JSArrayBufferView> obj,
6042     i::Handle<i::JSArrayBuffer> buffer,
6043     size_t byte_offset,
6044     size_t byte_length) {
6045   DCHECK(byte_offset + byte_length <=
6046          static_cast<size_t>(buffer->byte_length()->Number()));
6047
6048   obj->set_buffer(*buffer);
6049
6050   obj->set_weak_next(buffer->weak_first_view());
6051   buffer->set_weak_first_view(*obj);
6052
6053   i::Handle<i::Object> byte_offset_object =
6054       isolate->factory()->NewNumberFromSize(byte_offset);
6055   obj->set_byte_offset(*byte_offset_object);
6056
6057   i::Handle<i::Object> byte_length_object =
6058       isolate->factory()->NewNumberFromSize(byte_length);
6059   obj->set_byte_length(*byte_length_object);
6060 }
6061
6062 template<typename ElementType,
6063          ExternalArrayType array_type,
6064          i::ElementsKind elements_kind>
6065 i::Handle<i::JSTypedArray> NewTypedArray(
6066     i::Isolate* isolate,
6067     Handle<ArrayBuffer> array_buffer, size_t byte_offset, size_t length) {
6068   i::Handle<i::JSTypedArray> obj =
6069       isolate->factory()->NewJSTypedArray(array_type);
6070   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6071
6072   DCHECK(byte_offset % sizeof(ElementType) == 0);
6073
6074   CHECK(length <= (std::numeric_limits<size_t>::max() / sizeof(ElementType)));
6075   CHECK(length <= static_cast<size_t>(i::Smi::kMaxValue));
6076   size_t byte_length = length * sizeof(ElementType);
6077   SetupArrayBufferView(
6078       isolate, obj, buffer, byte_offset, byte_length);
6079
6080   i::Handle<i::Object> length_object =
6081       isolate->factory()->NewNumberFromSize(length);
6082   obj->set_length(*length_object);
6083
6084   i::Handle<i::ExternalArray> elements =
6085       isolate->factory()->NewExternalArray(
6086           static_cast<int>(length), array_type,
6087           static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
6088   i::Handle<i::Map> map =
6089       i::JSObject::GetElementsTransitionMap(obj, elements_kind);
6090   i::JSObject::SetMapAndElements(obj, map, elements);
6091   return obj;
6092 }
6093
6094
6095 #define TYPED_ARRAY_NEW(Type, type, TYPE, ctype, size)                       \
6096   Local<Type##Array> Type##Array::New(Handle<ArrayBuffer> array_buffer,      \
6097                                     size_t byte_offset, size_t length) {     \
6098     i::Isolate* isolate = Utils::OpenHandle(*array_buffer)->GetIsolate();    \
6099     EnsureInitializedForIsolate(isolate,                                     \
6100         "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)");     \
6101     LOG_API(isolate,                                                         \
6102         "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)");     \
6103     ENTER_V8(isolate);                                                       \
6104     if (!Utils::ApiCheck(length <= static_cast<size_t>(i::Smi::kMaxValue),   \
6105             "v8::" #Type "Array::New(Handle<ArrayBuffer>, size_t, size_t)",  \
6106             "length exceeds max allowed value")) {                           \
6107       return Local<Type##Array>();                                          \
6108     }                                                                        \
6109     i::Handle<i::JSTypedArray> obj =                                         \
6110         NewTypedArray<ctype, v8::kExternal##Type##Array,                     \
6111                       i::EXTERNAL_##TYPE##_ELEMENTS>(                        \
6112             isolate, array_buffer, byte_offset, length);                     \
6113     return Utils::ToLocal##Type##Array(obj);                                 \
6114   }
6115
6116
6117 TYPED_ARRAYS(TYPED_ARRAY_NEW)
6118 #undef TYPED_ARRAY_NEW
6119
6120 Local<DataView> DataView::New(Handle<ArrayBuffer> array_buffer,
6121                               size_t byte_offset, size_t byte_length) {
6122   i::Handle<i::JSArrayBuffer> buffer = Utils::OpenHandle(*array_buffer);
6123   i::Isolate* isolate = buffer->GetIsolate();
6124   EnsureInitializedForIsolate(
6125       isolate, "v8::DataView::New(void*, size_t, size_t)");
6126   LOG_API(isolate, "v8::DataView::New(void*, size_t, size_t)");
6127   ENTER_V8(isolate);
6128   i::Handle<i::JSDataView> obj = isolate->factory()->NewJSDataView();
6129   SetupArrayBufferView(
6130       isolate, obj, buffer, byte_offset, byte_length);
6131   return Utils::ToLocal(obj);
6132 }
6133
6134
6135 Local<Symbol> v8::Symbol::New(Isolate* isolate, Local<String> name) {
6136   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6137   EnsureInitializedForIsolate(i_isolate, "v8::Symbol::New()");
6138   LOG_API(i_isolate, "Symbol::New()");
6139   ENTER_V8(i_isolate);
6140   i::Handle<i::Symbol> result = i_isolate->factory()->NewSymbol();
6141   if (!name.IsEmpty()) result->set_name(*Utils::OpenHandle(*name));
6142   return Utils::ToLocal(result);
6143 }
6144
6145
6146 Local<Symbol> v8::Symbol::For(Isolate* isolate, Local<String> name) {
6147   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6148   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6149   i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6150   i::Handle<i::String> part = i_isolate->factory()->for_string();
6151   i::Handle<i::JSObject> symbols =
6152       i::Handle<i::JSObject>::cast(
6153           i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6154   i::Handle<i::Object> symbol =
6155       i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
6156   if (!symbol->IsSymbol()) {
6157     DCHECK(symbol->IsUndefined());
6158     symbol = i_isolate->factory()->NewSymbol();
6159     i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6160     i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert();
6161   }
6162   return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6163 }
6164
6165
6166 Local<Symbol> v8::Symbol::ForApi(Isolate* isolate, Local<String> name) {
6167   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6168   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6169   i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6170   i::Handle<i::String> part = i_isolate->factory()->for_api_string();
6171   i::Handle<i::JSObject> symbols =
6172       i::Handle<i::JSObject>::cast(
6173           i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6174   i::Handle<i::Object> symbol =
6175       i::Object::GetPropertyOrElement(symbols, i_name).ToHandleChecked();
6176   if (!symbol->IsSymbol()) {
6177     DCHECK(symbol->IsUndefined());
6178     symbol = i_isolate->factory()->NewSymbol();
6179     i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6180     i::JSObject::SetProperty(symbols, i_name, symbol, i::STRICT).Assert();
6181   }
6182   return Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6183 }
6184
6185
6186 Local<Private> v8::Private::New(Isolate* isolate, Local<String> name) {
6187   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6188   EnsureInitializedForIsolate(i_isolate, "v8::Private::New()");
6189   LOG_API(i_isolate, "Private::New()");
6190   ENTER_V8(i_isolate);
6191   i::Handle<i::Symbol> symbol = i_isolate->factory()->NewPrivateSymbol();
6192   if (!name.IsEmpty()) symbol->set_name(*Utils::OpenHandle(*name));
6193   Local<Symbol> result = Utils::ToLocal(symbol);
6194   return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6195 }
6196
6197
6198 Local<Private> v8::Private::ForApi(Isolate* isolate, Local<String> name) {
6199   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6200   i::Handle<i::String> i_name = Utils::OpenHandle(*name);
6201   i::Handle<i::JSObject> registry = i_isolate->GetSymbolRegistry();
6202   i::Handle<i::String> part = i_isolate->factory()->private_api_string();
6203   i::Handle<i::JSObject> privates =
6204       i::Handle<i::JSObject>::cast(
6205           i::Object::GetPropertyOrElement(registry, part).ToHandleChecked());
6206   i::Handle<i::Object> symbol =
6207       i::Object::GetPropertyOrElement(privates, i_name).ToHandleChecked();
6208   if (!symbol->IsSymbol()) {
6209     DCHECK(symbol->IsUndefined());
6210     symbol = i_isolate->factory()->NewPrivateSymbol();
6211     i::Handle<i::Symbol>::cast(symbol)->set_name(*i_name);
6212     i::JSObject::SetProperty(privates, i_name, symbol, i::STRICT).Assert();
6213   }
6214   Local<Symbol> result = Utils::ToLocal(i::Handle<i::Symbol>::cast(symbol));
6215   return v8::Handle<Private>(reinterpret_cast<Private*>(*result));
6216 }
6217
6218
6219 Local<Number> v8::Number::New(Isolate* isolate, double value) {
6220   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6221   DCHECK(internal_isolate->IsInitialized());
6222   if (std::isnan(value)) {
6223     // Introduce only canonical NaN value into the VM, to avoid signaling NaNs.
6224     value = base::OS::nan_value();
6225   }
6226   ENTER_V8(internal_isolate);
6227   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6228   return Utils::NumberToLocal(result);
6229 }
6230
6231
6232 Local<Integer> v8::Integer::New(Isolate* isolate, int32_t value) {
6233   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6234   DCHECK(internal_isolate->IsInitialized());
6235   if (i::Smi::IsValid(value)) {
6236     return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value),
6237                                                       internal_isolate));
6238   }
6239   ENTER_V8(internal_isolate);
6240   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6241   return Utils::IntegerToLocal(result);
6242 }
6243
6244
6245 Local<Integer> v8::Integer::NewFromUnsigned(Isolate* isolate, uint32_t value) {
6246   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6247   DCHECK(internal_isolate->IsInitialized());
6248   bool fits_into_int32_t = (value & (1 << 31)) == 0;
6249   if (fits_into_int32_t) {
6250     return Integer::New(isolate, static_cast<int32_t>(value));
6251   }
6252   ENTER_V8(internal_isolate);
6253   i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value);
6254   return Utils::IntegerToLocal(result);
6255 }
6256
6257
6258 bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) {
6259   i::Isolate* isolate = i::Isolate::Current();
6260   EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()");
6261   ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false);
6262   ENTER_V8(isolate);
6263   i::HandleScope scope(isolate);
6264   NeanderArray listeners(isolate->factory()->message_listeners());
6265   NeanderObject obj(isolate, 2);
6266   obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that)));
6267   obj.set(1, data.IsEmpty() ? isolate->heap()->undefined_value()
6268           : *Utils::OpenHandle(*data));
6269   listeners.add(obj.value());
6270   return true;
6271 }
6272
6273
6274 void V8::RemoveMessageListeners(MessageCallback that) {
6275   i::Isolate* isolate = i::Isolate::Current();
6276   EnsureInitializedForIsolate(isolate, "v8::V8::RemoveMessageListener()");
6277   ON_BAILOUT(isolate, "v8::V8::RemoveMessageListeners()", return);
6278   ENTER_V8(isolate);
6279   i::HandleScope scope(isolate);
6280   NeanderArray listeners(isolate->factory()->message_listeners());
6281   for (int i = 0; i < listeners.length(); i++) {
6282     if (listeners.get(i)->IsUndefined()) continue;  // skip deleted ones
6283
6284     NeanderObject listener(i::JSObject::cast(listeners.get(i)));
6285     i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0)));
6286     if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) {
6287       listeners.set(i, isolate->heap()->undefined_value());
6288     }
6289   }
6290 }
6291
6292
6293 void V8::SetCaptureStackTraceForUncaughtExceptions(
6294     bool capture,
6295     int frame_limit,
6296     StackTrace::StackTraceOptions options) {
6297   i::Isolate::Current()->SetCaptureStackTraceForUncaughtExceptions(
6298       capture,
6299       frame_limit,
6300       options);
6301 }
6302
6303
6304 void V8::SetFailedAccessCheckCallbackFunction(
6305     FailedAccessCheckCallback callback) {
6306   i::Isolate* isolate = i::Isolate::Current();
6307   isolate->SetFailedAccessCheckCallback(callback);
6308 }
6309
6310
6311 void Isolate::CollectAllGarbage(const char* gc_reason) {
6312   reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6313       i::Heap::kNoGCFlags, gc_reason);
6314 }
6315
6316
6317 HeapProfiler* Isolate::GetHeapProfiler() {
6318   i::HeapProfiler* heap_profiler =
6319       reinterpret_cast<i::Isolate*>(this)->heap_profiler();
6320   return reinterpret_cast<HeapProfiler*>(heap_profiler);
6321 }
6322
6323
6324 CpuProfiler* Isolate::GetCpuProfiler() {
6325   i::CpuProfiler* cpu_profiler =
6326       reinterpret_cast<i::Isolate*>(this)->cpu_profiler();
6327   return reinterpret_cast<CpuProfiler*>(cpu_profiler);
6328 }
6329
6330
6331 bool Isolate::InContext() {
6332   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6333   return isolate->context() != NULL;
6334 }
6335
6336
6337 v8::Local<v8::Context> Isolate::GetCurrentContext() {
6338   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6339   i::Context* context = isolate->context();
6340   if (context == NULL) return Local<Context>();
6341   i::Context* native_context = context->native_context();
6342   if (native_context == NULL) return Local<Context>();
6343   return Utils::ToLocal(i::Handle<i::Context>(native_context));
6344 }
6345
6346
6347 v8::Local<v8::Context> Isolate::GetCallingContext() {
6348   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6349   i::Handle<i::Object> calling = isolate->GetCallingNativeContext();
6350   if (calling.is_null()) return Local<Context>();
6351   return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
6352 }
6353
6354
6355 v8::Local<v8::Context> Isolate::GetEnteredContext() {
6356   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6357   i::Handle<i::Object> last =
6358       isolate->handle_scope_implementer()->LastEnteredContext();
6359   if (last.is_null()) return Local<Context>();
6360   return Utils::ToLocal(i::Handle<i::Context>::cast(last));
6361 }
6362
6363
6364 v8::Local<Value> Isolate::ThrowException(v8::Local<v8::Value> value) {
6365   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6366   ENTER_V8(isolate);
6367   // If we're passed an empty handle, we throw an undefined exception
6368   // to deal more gracefully with out of memory situations.
6369   if (value.IsEmpty()) {
6370     isolate->ScheduleThrow(isolate->heap()->undefined_value());
6371   } else {
6372     isolate->ScheduleThrow(*Utils::OpenHandle(*value));
6373   }
6374   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
6375 }
6376
6377
6378 void Isolate::SetObjectGroupId(internal::Object** object, UniqueId id) {
6379   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6380   internal_isolate->global_handles()->SetObjectGroupId(
6381       v8::internal::Handle<v8::internal::Object>(object).location(),
6382       id);
6383 }
6384
6385
6386 void Isolate::SetReferenceFromGroup(UniqueId id, internal::Object** object) {
6387   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6388   internal_isolate->global_handles()->SetReferenceFromGroup(
6389       id,
6390       v8::internal::Handle<v8::internal::Object>(object).location());
6391 }
6392
6393
6394 void Isolate::SetReference(internal::Object** parent,
6395                            internal::Object** child) {
6396   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(this);
6397   i::Object** parent_location =
6398       v8::internal::Handle<v8::internal::Object>(parent).location();
6399   internal_isolate->global_handles()->SetReference(
6400       reinterpret_cast<i::HeapObject**>(parent_location),
6401       v8::internal::Handle<v8::internal::Object>(child).location());
6402 }
6403
6404
6405 void Isolate::AddGCPrologueCallback(GCPrologueCallback callback,
6406                                     GCType gc_type) {
6407   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6408   isolate->heap()->AddGCPrologueCallback(callback, gc_type);
6409 }
6410
6411
6412 void Isolate::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6413   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6414   isolate->heap()->RemoveGCPrologueCallback(callback);
6415 }
6416
6417
6418 void Isolate::AddGCEpilogueCallback(GCEpilogueCallback callback,
6419                                     GCType gc_type) {
6420   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6421   isolate->heap()->AddGCEpilogueCallback(callback, gc_type);
6422 }
6423
6424
6425 void Isolate::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6426   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6427   isolate->heap()->RemoveGCEpilogueCallback(callback);
6428 }
6429
6430
6431 void V8::AddGCPrologueCallback(GCPrologueCallback callback, GCType gc_type) {
6432   i::Isolate* isolate = i::Isolate::Current();
6433   isolate->heap()->AddGCPrologueCallback(
6434       reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback),
6435       gc_type,
6436       false);
6437 }
6438
6439
6440 void V8::RemoveGCPrologueCallback(GCPrologueCallback callback) {
6441   i::Isolate* isolate = i::Isolate::Current();
6442   isolate->heap()->RemoveGCPrologueCallback(
6443       reinterpret_cast<v8::Isolate::GCPrologueCallback>(callback));
6444 }
6445
6446
6447 void V8::AddGCEpilogueCallback(GCEpilogueCallback callback, GCType gc_type) {
6448   i::Isolate* isolate = i::Isolate::Current();
6449   isolate->heap()->AddGCEpilogueCallback(
6450       reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback),
6451       gc_type,
6452       false);
6453 }
6454
6455
6456 void V8::RemoveGCEpilogueCallback(GCEpilogueCallback callback) {
6457   i::Isolate* isolate = i::Isolate::Current();
6458   isolate->heap()->RemoveGCEpilogueCallback(
6459       reinterpret_cast<v8::Isolate::GCEpilogueCallback>(callback));
6460 }
6461
6462
6463 void V8::AddMemoryAllocationCallback(MemoryAllocationCallback callback,
6464                                      ObjectSpace space,
6465                                      AllocationAction action) {
6466   i::Isolate* isolate = i::Isolate::Current();
6467   isolate->memory_allocator()->AddMemoryAllocationCallback(
6468       callback, space, action);
6469 }
6470
6471
6472 void V8::RemoveMemoryAllocationCallback(MemoryAllocationCallback callback) {
6473   i::Isolate* isolate = i::Isolate::Current();
6474   isolate->memory_allocator()->RemoveMemoryAllocationCallback(
6475       callback);
6476 }
6477
6478
6479 void V8::TerminateExecution(Isolate* isolate) {
6480   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6481   i_isolate->stack_guard()->RequestTerminateExecution();
6482 }
6483
6484
6485 bool V8::IsExecutionTerminating(Isolate* isolate) {
6486   i::Isolate* i_isolate = isolate != NULL ?
6487       reinterpret_cast<i::Isolate*>(isolate) : i::Isolate::Current();
6488   return IsExecutionTerminatingCheck(i_isolate);
6489 }
6490
6491
6492 void V8::CancelTerminateExecution(Isolate* isolate) {
6493   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6494   i_isolate->stack_guard()->ClearTerminateExecution();
6495   i_isolate->CancelTerminateExecution();
6496 }
6497
6498
6499 void Isolate::RequestInterrupt(InterruptCallback callback, void* data) {
6500   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6501   i_isolate->set_api_interrupt_callback(callback);
6502   i_isolate->set_api_interrupt_callback_data(data);
6503   i_isolate->stack_guard()->RequestApiInterrupt();
6504 }
6505
6506
6507 void Isolate::ClearInterrupt() {
6508   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(this);
6509   i_isolate->stack_guard()->ClearApiInterrupt();
6510   i_isolate->set_api_interrupt_callback(NULL);
6511   i_isolate->set_api_interrupt_callback_data(NULL);
6512 }
6513
6514
6515 void Isolate::RequestGarbageCollectionForTesting(GarbageCollectionType type) {
6516   CHECK(i::FLAG_expose_gc);
6517   if (type == kMinorGarbageCollection) {
6518     reinterpret_cast<i::Isolate*>(this)->heap()->CollectGarbage(
6519         i::NEW_SPACE, "Isolate::RequestGarbageCollection",
6520         kGCCallbackFlagForced);
6521   } else {
6522     DCHECK_EQ(kFullGarbageCollection, type);
6523     reinterpret_cast<i::Isolate*>(this)->heap()->CollectAllGarbage(
6524         i::Heap::kAbortIncrementalMarkingMask,
6525         "Isolate::RequestGarbageCollection", kGCCallbackFlagForced);
6526   }
6527 }
6528
6529
6530 Isolate* Isolate::GetCurrent() {
6531   i::Isolate* isolate = i::Isolate::Current();
6532   return reinterpret_cast<Isolate*>(isolate);
6533 }
6534
6535
6536 Isolate* Isolate::New() {
6537   i::Isolate* isolate = new i::Isolate();
6538   return reinterpret_cast<Isolate*>(isolate);
6539 }
6540
6541
6542 void Isolate::Dispose() {
6543   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6544   if (!Utils::ApiCheck(!isolate->IsInUse(),
6545                        "v8::Isolate::Dispose()",
6546                        "Disposing the isolate that is entered by a thread.")) {
6547     return;
6548   }
6549   isolate->TearDown();
6550 }
6551
6552
6553 void Isolate::Enter() {
6554   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6555   isolate->Enter();
6556 }
6557
6558
6559 void Isolate::Exit() {
6560   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6561   isolate->Exit();
6562 }
6563
6564
6565 Isolate::DisallowJavascriptExecutionScope::DisallowJavascriptExecutionScope(
6566     Isolate* isolate,
6567     Isolate::DisallowJavascriptExecutionScope::OnFailure on_failure)
6568     : on_failure_(on_failure) {
6569   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6570   if (on_failure_ == CRASH_ON_FAILURE) {
6571     internal_ = reinterpret_cast<void*>(
6572         new i::DisallowJavascriptExecution(i_isolate));
6573   } else {
6574     DCHECK_EQ(THROW_ON_FAILURE, on_failure);
6575     internal_ = reinterpret_cast<void*>(
6576         new i::ThrowOnJavascriptExecution(i_isolate));
6577   }
6578 }
6579
6580
6581 Isolate::DisallowJavascriptExecutionScope::~DisallowJavascriptExecutionScope() {
6582   if (on_failure_ == CRASH_ON_FAILURE) {
6583     delete reinterpret_cast<i::DisallowJavascriptExecution*>(internal_);
6584   } else {
6585     delete reinterpret_cast<i::ThrowOnJavascriptExecution*>(internal_);
6586   }
6587 }
6588
6589
6590 Isolate::AllowJavascriptExecutionScope::AllowJavascriptExecutionScope(
6591     Isolate* isolate) {
6592   i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
6593   internal_assert_ = reinterpret_cast<void*>(
6594       new i::AllowJavascriptExecution(i_isolate));
6595   internal_throws_ = reinterpret_cast<void*>(
6596       new i::NoThrowOnJavascriptExecution(i_isolate));
6597 }
6598
6599
6600 Isolate::AllowJavascriptExecutionScope::~AllowJavascriptExecutionScope() {
6601   delete reinterpret_cast<i::AllowJavascriptExecution*>(internal_assert_);
6602   delete reinterpret_cast<i::NoThrowOnJavascriptExecution*>(internal_throws_);
6603 }
6604
6605
6606 Isolate::SuppressMicrotaskExecutionScope::SuppressMicrotaskExecutionScope(
6607     Isolate* isolate)
6608     : isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
6609   isolate_->handle_scope_implementer()->IncrementCallDepth();
6610 }
6611
6612
6613 Isolate::SuppressMicrotaskExecutionScope::~SuppressMicrotaskExecutionScope() {
6614   isolate_->handle_scope_implementer()->DecrementCallDepth();
6615 }
6616
6617
6618 void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) {
6619   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6620   if (!isolate->IsInitialized()) {
6621     heap_statistics->total_heap_size_ = 0;
6622     heap_statistics->total_heap_size_executable_ = 0;
6623     heap_statistics->total_physical_size_ = 0;
6624     heap_statistics->used_heap_size_ = 0;
6625     heap_statistics->heap_size_limit_ = 0;
6626     return;
6627   }
6628   i::Heap* heap = isolate->heap();
6629   heap_statistics->total_heap_size_ = heap->CommittedMemory();
6630   heap_statistics->total_heap_size_executable_ =
6631       heap->CommittedMemoryExecutable();
6632   heap_statistics->total_physical_size_ = heap->CommittedPhysicalMemory();
6633   heap_statistics->used_heap_size_ = heap->SizeOfObjects();
6634   heap_statistics->heap_size_limit_ = heap->MaxReserved();
6635 }
6636
6637
6638 void Isolate::SetEventLogger(LogEventCallback that) {
6639   // Do not overwrite the event logger if we want to log explicitly.
6640   if (i::FLAG_log_timer_events) return;
6641   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6642   isolate->set_event_logger(that);
6643 }
6644
6645
6646 void Isolate::AddCallCompletedCallback(CallCompletedCallback callback) {
6647   if (callback == NULL) return;
6648   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6649   isolate->AddCallCompletedCallback(callback);
6650 }
6651
6652
6653 void Isolate::RemoveCallCompletedCallback(CallCompletedCallback callback) {
6654   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6655   isolate->RemoveCallCompletedCallback(callback);
6656 }
6657
6658
6659 void Isolate::RunMicrotasks() {
6660   reinterpret_cast<i::Isolate*>(this)->RunMicrotasks();
6661 }
6662
6663
6664 void Isolate::EnqueueMicrotask(Handle<Function> microtask) {
6665   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6666   isolate->EnqueueMicrotask(Utils::OpenHandle(*microtask));
6667 }
6668
6669
6670 void Isolate::EnqueueMicrotask(MicrotaskCallback microtask, void* data) {
6671   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6672   i::HandleScope scope(isolate);
6673   i::Handle<i::CallHandlerInfo> callback_info =
6674       i::Handle<i::CallHandlerInfo>::cast(
6675           isolate->factory()->NewStruct(i::CALL_HANDLER_INFO_TYPE));
6676   SET_FIELD_WRAPPED(callback_info, set_callback, microtask);
6677   SET_FIELD_WRAPPED(callback_info, set_data, data);
6678   isolate->EnqueueMicrotask(callback_info);
6679 }
6680
6681
6682 void Isolate::SetAutorunMicrotasks(bool autorun) {
6683   reinterpret_cast<i::Isolate*>(this)->set_autorun_microtasks(autorun);
6684 }
6685
6686
6687 bool Isolate::WillAutorunMicrotasks() const {
6688   return reinterpret_cast<const i::Isolate*>(this)->autorun_microtasks();
6689 }
6690
6691
6692 void Isolate::SetUseCounterCallback(UseCounterCallback callback) {
6693   reinterpret_cast<i::Isolate*>(this)->SetUseCounterCallback(callback);
6694 }
6695
6696
6697 void Isolate::SetCounterFunction(CounterLookupCallback callback) {
6698   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6699   isolate->stats_table()->SetCounterFunction(callback);
6700   isolate->InitializeLoggingAndCounters();
6701   isolate->counters()->ResetCounters();
6702 }
6703
6704
6705 void Isolate::SetCreateHistogramFunction(CreateHistogramCallback callback) {
6706   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6707   isolate->stats_table()->SetCreateHistogramFunction(callback);
6708   isolate->InitializeLoggingAndCounters();
6709   isolate->counters()->ResetHistograms();
6710 }
6711
6712
6713 void Isolate::SetAddHistogramSampleFunction(
6714     AddHistogramSampleCallback callback) {
6715   reinterpret_cast<i::Isolate*>(this)
6716       ->stats_table()
6717       ->SetAddHistogramSampleFunction(callback);
6718 }
6719
6720
6721 bool v8::Isolate::IdleNotification(int idle_time_in_ms) {
6722   // Returning true tells the caller that it need not
6723   // continue to call IdleNotification.
6724   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6725   if (!i::FLAG_use_idle_notification) return true;
6726   return isolate->heap()->IdleNotification(idle_time_in_ms);
6727 }
6728
6729
6730 void v8::Isolate::LowMemoryNotification() {
6731   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6732   {
6733     i::HistogramTimerScope idle_notification_scope(
6734         isolate->counters()->gc_low_memory_notification());
6735     isolate->heap()->CollectAllAvailableGarbage("low memory notification");
6736   }
6737 }
6738
6739
6740 int v8::Isolate::ContextDisposedNotification() {
6741   i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
6742   return isolate->heap()->NotifyContextDisposed();
6743 }
6744
6745
6746 String::Utf8Value::Utf8Value(v8::Handle<v8::Value> obj)
6747     : str_(NULL), length_(0) {
6748   i::Isolate* isolate = i::Isolate::Current();
6749   if (obj.IsEmpty()) return;
6750   ENTER_V8(isolate);
6751   i::HandleScope scope(isolate);
6752   TryCatch try_catch;
6753   Handle<String> str = obj->ToString();
6754   if (str.IsEmpty()) return;
6755   i::Handle<i::String> i_str = Utils::OpenHandle(*str);
6756   length_ = v8::Utf8Length(*i_str, isolate);
6757   str_ = i::NewArray<char>(length_ + 1);
6758   str->WriteUtf8(str_);
6759 }
6760
6761
6762 String::Utf8Value::~Utf8Value() {
6763   i::DeleteArray(str_);
6764 }
6765
6766
6767 String::Value::Value(v8::Handle<v8::Value> obj)
6768     : str_(NULL), length_(0) {
6769   i::Isolate* isolate = i::Isolate::Current();
6770   if (obj.IsEmpty()) return;
6771   ENTER_V8(isolate);
6772   i::HandleScope scope(isolate);
6773   TryCatch try_catch;
6774   Handle<String> str = obj->ToString();
6775   if (str.IsEmpty()) return;
6776   length_ = str->Length();
6777   str_ = i::NewArray<uint16_t>(length_ + 1);
6778   str->Write(str_);
6779 }
6780
6781
6782 String::Value::~Value() {
6783   i::DeleteArray(str_);
6784 }
6785
6786
6787 Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) {
6788   i::Isolate* isolate = i::Isolate::Current();
6789   LOG_API(isolate, "RangeError");
6790   ON_BAILOUT(isolate, "v8::Exception::RangeError()", return Local<Value>());
6791   ENTER_V8(isolate);
6792   i::Object* error;
6793   {
6794     i::HandleScope scope(isolate);
6795     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6796     i::Handle<i::Object> result = isolate->factory()->NewRangeError(message);
6797     error = *result;
6798   }
6799   i::Handle<i::Object> result(error, isolate);
6800   return Utils::ToLocal(result);
6801 }
6802
6803
6804 Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) {
6805   i::Isolate* isolate = i::Isolate::Current();
6806   LOG_API(isolate, "ReferenceError");
6807   ON_BAILOUT(isolate, "v8::Exception::ReferenceError()", return Local<Value>());
6808   ENTER_V8(isolate);
6809   i::Object* error;
6810   {
6811     i::HandleScope scope(isolate);
6812     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6813     i::Handle<i::Object> result =
6814         isolate->factory()->NewReferenceError(message);
6815     error = *result;
6816   }
6817   i::Handle<i::Object> result(error, isolate);
6818   return Utils::ToLocal(result);
6819 }
6820
6821
6822 Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) {
6823   i::Isolate* isolate = i::Isolate::Current();
6824   LOG_API(isolate, "SyntaxError");
6825   ON_BAILOUT(isolate, "v8::Exception::SyntaxError()", return Local<Value>());
6826   ENTER_V8(isolate);
6827   i::Object* error;
6828   {
6829     i::HandleScope scope(isolate);
6830     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6831     i::Handle<i::Object> result = isolate->factory()->NewSyntaxError(message);
6832     error = *result;
6833   }
6834   i::Handle<i::Object> result(error, isolate);
6835   return Utils::ToLocal(result);
6836 }
6837
6838
6839 Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) {
6840   i::Isolate* isolate = i::Isolate::Current();
6841   LOG_API(isolate, "TypeError");
6842   ON_BAILOUT(isolate, "v8::Exception::TypeError()", return Local<Value>());
6843   ENTER_V8(isolate);
6844   i::Object* error;
6845   {
6846     i::HandleScope scope(isolate);
6847     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6848     i::Handle<i::Object> result = isolate->factory()->NewTypeError(message);
6849     error = *result;
6850   }
6851   i::Handle<i::Object> result(error, isolate);
6852   return Utils::ToLocal(result);
6853 }
6854
6855
6856 Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) {
6857   i::Isolate* isolate = i::Isolate::Current();
6858   LOG_API(isolate, "Error");
6859   ON_BAILOUT(isolate, "v8::Exception::Error()", return Local<Value>());
6860   ENTER_V8(isolate);
6861   i::Object* error;
6862   {
6863     i::HandleScope scope(isolate);
6864     i::Handle<i::String> message = Utils::OpenHandle(*raw_message);
6865     i::Handle<i::Object> result = isolate->factory()->NewError(message);
6866     error = *result;
6867   }
6868   i::Handle<i::Object> result(error, isolate);
6869   return Utils::ToLocal(result);
6870 }
6871
6872
6873 // --- D e b u g   S u p p o r t ---
6874
6875 bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) {
6876   i::Isolate* isolate = i::Isolate::Current();
6877   EnsureInitializedForIsolate(isolate, "v8::Debug::SetDebugEventListener()");
6878   ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false);
6879   ENTER_V8(isolate);
6880   i::HandleScope scope(isolate);
6881   i::Handle<i::Object> foreign = isolate->factory()->undefined_value();
6882   if (that != NULL) {
6883     foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that));
6884   }
6885   isolate->debug()->SetEventListener(foreign,
6886                                      Utils::OpenHandle(*data, true));
6887   return true;
6888 }
6889
6890
6891 void Debug::DebugBreak(Isolate* isolate) {
6892   reinterpret_cast<i::Isolate*>(isolate)->stack_guard()->RequestDebugBreak();
6893 }
6894
6895
6896 void Debug::CancelDebugBreak(Isolate* isolate) {
6897   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6898   internal_isolate->stack_guard()->ClearDebugBreak();
6899 }
6900
6901
6902 void Debug::DebugBreakForCommand(Isolate* isolate, ClientData* data) {
6903   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6904   internal_isolate->debug()->EnqueueDebugCommand(data);
6905 }
6906
6907
6908 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
6909   i::Isolate* isolate = i::Isolate::Current();
6910   EnsureInitializedForIsolate(isolate, "v8::Debug::SetMessageHandler");
6911   ENTER_V8(isolate);
6912   isolate->debug()->SetMessageHandler(handler);
6913 }
6914
6915
6916 void Debug::SendCommand(Isolate* isolate,
6917                         const uint16_t* command,
6918                         int length,
6919                         ClientData* client_data) {
6920   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6921   internal_isolate->debug()->EnqueueCommandMessage(
6922       i::Vector<const uint16_t>(command, length), client_data);
6923 }
6924
6925
6926 Local<Value> Debug::Call(v8::Handle<v8::Function> fun,
6927                          v8::Handle<v8::Value> data) {
6928   i::Isolate* isolate = i::Isolate::Current();
6929   if (!isolate->IsInitialized()) return Local<Value>();
6930   ON_BAILOUT(isolate, "v8::Debug::Call()", return Local<Value>());
6931   ENTER_V8(isolate);
6932   i::MaybeHandle<i::Object> maybe_result;
6933   EXCEPTION_PREAMBLE(isolate);
6934   if (data.IsEmpty()) {
6935     maybe_result = isolate->debug()->Call(
6936         Utils::OpenHandle(*fun), isolate->factory()->undefined_value());
6937   } else {
6938     maybe_result = isolate->debug()->Call(
6939         Utils::OpenHandle(*fun), Utils::OpenHandle(*data));
6940   }
6941   i::Handle<i::Object> result;
6942   has_pending_exception = !maybe_result.ToHandle(&result);
6943   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6944   return Utils::ToLocal(result);
6945 }
6946
6947
6948 Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) {
6949   i::Isolate* isolate = i::Isolate::Current();
6950   if (!isolate->IsInitialized()) return Local<Value>();
6951   ON_BAILOUT(isolate, "v8::Debug::GetMirror()", return Local<Value>());
6952   ENTER_V8(isolate);
6953   v8::EscapableHandleScope scope(reinterpret_cast<Isolate*>(isolate));
6954   i::Debug* isolate_debug = isolate->debug();
6955   EXCEPTION_PREAMBLE(isolate);
6956   has_pending_exception = !isolate_debug->Load();
6957   v8::Local<v8::Value> result;
6958   if (!has_pending_exception) {
6959     i::Handle<i::JSObject> debug(
6960         isolate_debug->debug_context()->global_object());
6961     i::Handle<i::String> name = isolate->factory()->InternalizeOneByteString(
6962         STATIC_ASCII_VECTOR("MakeMirror"));
6963     i::Handle<i::Object> fun_obj =
6964         i::Object::GetProperty(debug, name).ToHandleChecked();
6965     i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(fun_obj);
6966     v8::Handle<v8::Function> v8_fun = Utils::ToLocal(fun);
6967     const int kArgc = 1;
6968     v8::Handle<v8::Value> argv[kArgc] = { obj };
6969     result = v8_fun->Call(Utils::ToLocal(debug), kArgc, argv);
6970     has_pending_exception = result.IsEmpty();
6971   }
6972   EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
6973   return scope.Escape(result);
6974 }
6975
6976
6977 void Debug::ProcessDebugMessages() {
6978   i::Isolate::Current()->debug()->ProcessDebugMessages(true);
6979 }
6980
6981
6982 Local<Context> Debug::GetDebugContext() {
6983   i::Isolate* isolate = i::Isolate::Current();
6984   EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()");
6985   ENTER_V8(isolate);
6986   return Utils::ToLocal(i::Isolate::Current()->debug()->GetDebugContext());
6987 }
6988
6989
6990 void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
6991   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
6992   internal_isolate->debug()->set_live_edit_enabled(enable);
6993 }
6994
6995
6996 Handle<String> CpuProfileNode::GetFunctionName() const {
6997   i::Isolate* isolate = i::Isolate::Current();
6998   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
6999   const i::CodeEntry* entry = node->entry();
7000   i::Handle<i::String> name =
7001       isolate->factory()->InternalizeUtf8String(entry->name());
7002   if (!entry->has_name_prefix()) {
7003     return ToApiHandle<String>(name);
7004   } else {
7005     // We do not expect this to fail. Change this if it does.
7006     i::Handle<i::String> cons = isolate->factory()->NewConsString(
7007         isolate->factory()->InternalizeUtf8String(entry->name_prefix()),
7008         name).ToHandleChecked();
7009     return ToApiHandle<String>(cons);
7010   }
7011 }
7012
7013
7014 int CpuProfileNode::GetScriptId() const {
7015   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7016   const i::CodeEntry* entry = node->entry();
7017   return entry->script_id();
7018 }
7019
7020
7021 Handle<String> CpuProfileNode::GetScriptResourceName() const {
7022   i::Isolate* isolate = i::Isolate::Current();
7023   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7024   return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7025       node->entry()->resource_name()));
7026 }
7027
7028
7029 int CpuProfileNode::GetLineNumber() const {
7030   return reinterpret_cast<const i::ProfileNode*>(this)->entry()->line_number();
7031 }
7032
7033
7034 int CpuProfileNode::GetColumnNumber() const {
7035   return reinterpret_cast<const i::ProfileNode*>(this)->
7036       entry()->column_number();
7037 }
7038
7039
7040 unsigned int CpuProfileNode::GetHitLineCount() const {
7041   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7042   return node->GetHitLineCount();
7043 }
7044
7045
7046 bool CpuProfileNode::GetLineTicks(LineTick* entries,
7047                                   unsigned int length) const {
7048   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7049   return node->GetLineTicks(entries, length);
7050 }
7051
7052
7053 const char* CpuProfileNode::GetBailoutReason() const {
7054   const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
7055   return node->entry()->bailout_reason();
7056 }
7057
7058
7059 unsigned CpuProfileNode::GetHitCount() const {
7060   return reinterpret_cast<const i::ProfileNode*>(this)->self_ticks();
7061 }
7062
7063
7064 unsigned CpuProfileNode::GetCallUid() const {
7065   return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
7066 }
7067
7068
7069 unsigned CpuProfileNode::GetNodeId() const {
7070   return reinterpret_cast<const i::ProfileNode*>(this)->id();
7071 }
7072
7073
7074 int CpuProfileNode::GetChildrenCount() const {
7075   return reinterpret_cast<const i::ProfileNode*>(this)->children()->length();
7076 }
7077
7078
7079 const CpuProfileNode* CpuProfileNode::GetChild(int index) const {
7080   const i::ProfileNode* child =
7081       reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
7082   return reinterpret_cast<const CpuProfileNode*>(child);
7083 }
7084
7085
7086 void CpuProfile::Delete() {
7087   i::Isolate* isolate = i::Isolate::Current();
7088   i::CpuProfiler* profiler = isolate->cpu_profiler();
7089   DCHECK(profiler != NULL);
7090   profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
7091 }
7092
7093
7094 Handle<String> CpuProfile::GetTitle() const {
7095   i::Isolate* isolate = i::Isolate::Current();
7096   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7097   return ToApiHandle<String>(isolate->factory()->InternalizeUtf8String(
7098       profile->title()));
7099 }
7100
7101
7102 const CpuProfileNode* CpuProfile::GetTopDownRoot() const {
7103   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7104   return reinterpret_cast<const CpuProfileNode*>(profile->top_down()->root());
7105 }
7106
7107
7108 const CpuProfileNode* CpuProfile::GetSample(int index) const {
7109   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7110   return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
7111 }
7112
7113
7114 int64_t CpuProfile::GetSampleTimestamp(int index) const {
7115   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7116   return (profile->sample_timestamp(index) - base::TimeTicks())
7117       .InMicroseconds();
7118 }
7119
7120
7121 int64_t CpuProfile::GetStartTime() const {
7122   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7123   return (profile->start_time() - base::TimeTicks()).InMicroseconds();
7124 }
7125
7126
7127 int64_t CpuProfile::GetEndTime() const {
7128   const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
7129   return (profile->end_time() - base::TimeTicks()).InMicroseconds();
7130 }
7131
7132
7133 int CpuProfile::GetSamplesCount() const {
7134   return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
7135 }
7136
7137
7138 void CpuProfiler::SetSamplingInterval(int us) {
7139   DCHECK(us >= 0);
7140   return reinterpret_cast<i::CpuProfiler*>(this)->set_sampling_interval(
7141       base::TimeDelta::FromMicroseconds(us));
7142 }
7143
7144
7145 void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
7146   reinterpret_cast<i::CpuProfiler*>(this)->StartProfiling(
7147       *Utils::OpenHandle(*title), record_samples);
7148 }
7149
7150
7151 void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) {
7152   StartProfiling(title, record_samples);
7153 }
7154
7155
7156 CpuProfile* CpuProfiler::StopProfiling(Handle<String> title) {
7157   return reinterpret_cast<CpuProfile*>(
7158       reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling(
7159           *Utils::OpenHandle(*title)));
7160 }
7161
7162
7163 const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) {
7164   return StopProfiling(title);
7165 }
7166
7167
7168 void CpuProfiler::SetIdle(bool is_idle) {
7169   i::Isolate* isolate = reinterpret_cast<i::CpuProfiler*>(this)->isolate();
7170   i::StateTag state = isolate->current_vm_state();
7171   DCHECK(state == i::EXTERNAL || state == i::IDLE);
7172   if (isolate->js_entry_sp() != NULL) return;
7173   if (is_idle) {
7174     isolate->set_current_vm_state(i::IDLE);
7175   } else if (state == i::IDLE) {
7176     isolate->set_current_vm_state(i::EXTERNAL);
7177   }
7178 }
7179
7180
7181 static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
7182   return const_cast<i::HeapGraphEdge*>(
7183       reinterpret_cast<const i::HeapGraphEdge*>(edge));
7184 }
7185
7186
7187 HeapGraphEdge::Type HeapGraphEdge::GetType() const {
7188   return static_cast<HeapGraphEdge::Type>(ToInternal(this)->type());
7189 }
7190
7191
7192 Handle<Value> HeapGraphEdge::GetName() const {
7193   i::Isolate* isolate = i::Isolate::Current();
7194   i::HeapGraphEdge* edge = ToInternal(this);
7195   switch (edge->type()) {
7196     case i::HeapGraphEdge::kContextVariable:
7197     case i::HeapGraphEdge::kInternal:
7198     case i::HeapGraphEdge::kProperty:
7199     case i::HeapGraphEdge::kShortcut:
7200     case i::HeapGraphEdge::kWeak:
7201       return ToApiHandle<String>(
7202           isolate->factory()->InternalizeUtf8String(edge->name()));
7203     case i::HeapGraphEdge::kElement:
7204     case i::HeapGraphEdge::kHidden:
7205       return ToApiHandle<Number>(
7206           isolate->factory()->NewNumberFromInt(edge->index()));
7207     default: UNREACHABLE();
7208   }
7209   return v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
7210 }
7211
7212
7213 const HeapGraphNode* HeapGraphEdge::GetFromNode() const {
7214   const i::HeapEntry* from = ToInternal(this)->from();
7215   return reinterpret_cast<const HeapGraphNode*>(from);
7216 }
7217
7218
7219 const HeapGraphNode* HeapGraphEdge::GetToNode() const {
7220   const i::HeapEntry* to = ToInternal(this)->to();
7221   return reinterpret_cast<const HeapGraphNode*>(to);
7222 }
7223
7224
7225 static i::HeapEntry* ToInternal(const HeapGraphNode* entry) {
7226   return const_cast<i::HeapEntry*>(
7227       reinterpret_cast<const i::HeapEntry*>(entry));
7228 }
7229
7230
7231 HeapGraphNode::Type HeapGraphNode::GetType() const {
7232   return static_cast<HeapGraphNode::Type>(ToInternal(this)->type());
7233 }
7234
7235
7236 Handle<String> HeapGraphNode::GetName() const {
7237   i::Isolate* isolate = i::Isolate::Current();
7238   return ToApiHandle<String>(
7239       isolate->factory()->InternalizeUtf8String(ToInternal(this)->name()));
7240 }
7241
7242
7243 SnapshotObjectId HeapGraphNode::GetId() const {
7244   return ToInternal(this)->id();
7245 }
7246
7247
7248 int HeapGraphNode::GetSelfSize() const {
7249   size_t size = ToInternal(this)->self_size();
7250   CHECK(size <= static_cast<size_t>(internal::kMaxInt));
7251   return static_cast<int>(size);
7252 }
7253
7254
7255 size_t HeapGraphNode::GetShallowSize() const {
7256   return ToInternal(this)->self_size();
7257 }
7258
7259
7260 int HeapGraphNode::GetChildrenCount() const {
7261   return ToInternal(this)->children().length();
7262 }
7263
7264
7265 const HeapGraphEdge* HeapGraphNode::GetChild(int index) const {
7266   return reinterpret_cast<const HeapGraphEdge*>(
7267       ToInternal(this)->children()[index]);
7268 }
7269
7270
7271 static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) {
7272   return const_cast<i::HeapSnapshot*>(
7273       reinterpret_cast<const i::HeapSnapshot*>(snapshot));
7274 }
7275
7276
7277 void HeapSnapshot::Delete() {
7278   i::Isolate* isolate = i::Isolate::Current();
7279   if (isolate->heap_profiler()->GetSnapshotsCount() > 1) {
7280     ToInternal(this)->Delete();
7281   } else {
7282     // If this is the last snapshot, clean up all accessory data as well.
7283     isolate->heap_profiler()->DeleteAllSnapshots();
7284   }
7285 }
7286
7287
7288 unsigned HeapSnapshot::GetUid() const {
7289   return ToInternal(this)->uid();
7290 }
7291
7292
7293 Handle<String> HeapSnapshot::GetTitle() const {
7294   i::Isolate* isolate = i::Isolate::Current();
7295   return ToApiHandle<String>(
7296       isolate->factory()->InternalizeUtf8String(ToInternal(this)->title()));
7297 }
7298
7299
7300 const HeapGraphNode* HeapSnapshot::GetRoot() const {
7301   return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->root());
7302 }
7303
7304
7305 const HeapGraphNode* HeapSnapshot::GetNodeById(SnapshotObjectId id) const {
7306   return reinterpret_cast<const HeapGraphNode*>(
7307       ToInternal(this)->GetEntryById(id));
7308 }
7309
7310
7311 int HeapSnapshot::GetNodesCount() const {
7312   return ToInternal(this)->entries().length();
7313 }
7314
7315
7316 const HeapGraphNode* HeapSnapshot::GetNode(int index) const {
7317   return reinterpret_cast<const HeapGraphNode*>(
7318       &ToInternal(this)->entries().at(index));
7319 }
7320
7321
7322 SnapshotObjectId HeapSnapshot::GetMaxSnapshotJSObjectId() const {
7323   return ToInternal(this)->max_snapshot_js_object_id();
7324 }
7325
7326
7327 void HeapSnapshot::Serialize(OutputStream* stream,
7328                              HeapSnapshot::SerializationFormat format) const {
7329   Utils::ApiCheck(format == kJSON,
7330                   "v8::HeapSnapshot::Serialize",
7331                   "Unknown serialization format");
7332   Utils::ApiCheck(stream->GetChunkSize() > 0,
7333                   "v8::HeapSnapshot::Serialize",
7334                   "Invalid stream chunk size");
7335   i::HeapSnapshotJSONSerializer serializer(ToInternal(this));
7336   serializer.Serialize(stream);
7337 }
7338
7339
7340 int HeapProfiler::GetSnapshotCount() {
7341   return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotsCount();
7342 }
7343
7344
7345 const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) {
7346   return reinterpret_cast<const HeapSnapshot*>(
7347       reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshot(index));
7348 }
7349
7350
7351 SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) {
7352   i::Handle<i::Object> obj = Utils::OpenHandle(*value);
7353   return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj);
7354 }
7355
7356
7357 Handle<Value> HeapProfiler::FindObjectById(SnapshotObjectId id) {
7358   i::Handle<i::Object> obj =
7359       reinterpret_cast<i::HeapProfiler*>(this)->FindHeapObjectById(id);
7360   if (obj.is_null()) return Local<Value>();
7361   return Utils::ToLocal(obj);
7362 }
7363
7364
7365 void HeapProfiler::ClearObjectIds() {
7366   reinterpret_cast<i::HeapProfiler*>(this)->ClearHeapObjectMap();
7367 }
7368
7369
7370 const HeapSnapshot* HeapProfiler::TakeHeapSnapshot(
7371     Handle<String> title,
7372     ActivityControl* control,
7373     ObjectNameResolver* resolver) {
7374   return reinterpret_cast<const HeapSnapshot*>(
7375       reinterpret_cast<i::HeapProfiler*>(this)->TakeSnapshot(
7376           *Utils::OpenHandle(*title), control, resolver));
7377 }
7378
7379
7380 void HeapProfiler::StartTrackingHeapObjects(bool track_allocations) {
7381   reinterpret_cast<i::HeapProfiler*>(this)->StartHeapObjectsTracking(
7382       track_allocations);
7383 }
7384
7385
7386 void HeapProfiler::StopTrackingHeapObjects() {
7387   reinterpret_cast<i::HeapProfiler*>(this)->StopHeapObjectsTracking();
7388 }
7389
7390
7391 SnapshotObjectId HeapProfiler::GetHeapStats(OutputStream* stream) {
7392   return reinterpret_cast<i::HeapProfiler*>(this)->PushHeapObjectsStats(stream);
7393 }
7394
7395
7396 void HeapProfiler::DeleteAllHeapSnapshots() {
7397   reinterpret_cast<i::HeapProfiler*>(this)->DeleteAllSnapshots();
7398 }
7399
7400
7401 void HeapProfiler::SetWrapperClassInfoProvider(uint16_t class_id,
7402                                                WrapperInfoCallback callback) {
7403   reinterpret_cast<i::HeapProfiler*>(this)->DefineWrapperClass(class_id,
7404                                                                callback);
7405 }
7406
7407
7408 size_t HeapProfiler::GetProfilerMemorySize() {
7409   return reinterpret_cast<i::HeapProfiler*>(this)->
7410       GetMemorySizeUsedByProfiler();
7411 }
7412
7413
7414 void HeapProfiler::SetRetainedObjectInfo(UniqueId id,
7415                                          RetainedObjectInfo* info) {
7416   reinterpret_cast<i::HeapProfiler*>(this)->SetRetainedObjectInfo(id, info);
7417 }
7418
7419
7420 v8::Testing::StressType internal::Testing::stress_type_ =
7421     v8::Testing::kStressTypeOpt;
7422
7423
7424 void Testing::SetStressRunType(Testing::StressType type) {
7425   internal::Testing::set_stress_type(type);
7426 }
7427
7428
7429 int Testing::GetStressRuns() {
7430   if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs;
7431 #ifdef DEBUG
7432   // In debug mode the code runs much slower so stressing will only make two
7433   // runs.
7434   return 2;
7435 #else
7436   return 5;
7437 #endif
7438 }
7439
7440
7441 static void SetFlagsFromString(const char* flags) {
7442   V8::SetFlagsFromString(flags, i::StrLength(flags));
7443 }
7444
7445
7446 void Testing::PrepareStressRun(int run) {
7447   static const char* kLazyOptimizations =
7448       "--prepare-always-opt "
7449       "--max-inlined-source-size=999999 "
7450       "--max-inlined-nodes=999999 "
7451       "--max-inlined-nodes-cumulative=999999 "
7452       "--noalways-opt";
7453   static const char* kForcedOptimizations = "--always-opt";
7454
7455   // If deoptimization stressed turn on frequent deoptimization. If no value
7456   // is spefified through --deopt-every-n-times use a default default value.
7457   static const char* kDeoptEvery13Times = "--deopt-every-n-times=13";
7458   if (internal::Testing::stress_type() == Testing::kStressTypeDeopt &&
7459       internal::FLAG_deopt_every_n_times == 0) {
7460     SetFlagsFromString(kDeoptEvery13Times);
7461   }
7462
7463 #ifdef DEBUG
7464   // As stressing in debug mode only make two runs skip the deopt stressing
7465   // here.
7466   if (run == GetStressRuns() - 1) {
7467     SetFlagsFromString(kForcedOptimizations);
7468   } else {
7469     SetFlagsFromString(kLazyOptimizations);
7470   }
7471 #else
7472   if (run == GetStressRuns() - 1) {
7473     SetFlagsFromString(kForcedOptimizations);
7474   } else if (run != GetStressRuns() - 2) {
7475     SetFlagsFromString(kLazyOptimizations);
7476   }
7477 #endif
7478 }
7479
7480
7481 // TODO(svenpanne) Deprecate this.
7482 void Testing::DeoptimizeAll() {
7483   i::Isolate* isolate = i::Isolate::Current();
7484   i::HandleScope scope(isolate);
7485   internal::Deoptimizer::DeoptimizeAll(isolate);
7486 }
7487
7488
7489 namespace internal {
7490
7491
7492 void HandleScopeImplementer::FreeThreadResources() {
7493   Free();
7494 }
7495
7496
7497 char* HandleScopeImplementer::ArchiveThread(char* storage) {
7498   HandleScopeData* current = isolate_->handle_scope_data();
7499   handle_scope_data_ = *current;
7500   MemCopy(storage, this, sizeof(*this));
7501
7502   ResetAfterArchive();
7503   current->Initialize();
7504
7505   return storage + ArchiveSpacePerThread();
7506 }
7507
7508
7509 int HandleScopeImplementer::ArchiveSpacePerThread() {
7510   return sizeof(HandleScopeImplementer);
7511 }
7512
7513
7514 char* HandleScopeImplementer::RestoreThread(char* storage) {
7515   MemCopy(this, storage, sizeof(*this));
7516   *isolate_->handle_scope_data() = handle_scope_data_;
7517   return storage + ArchiveSpacePerThread();
7518 }
7519
7520
7521 void HandleScopeImplementer::IterateThis(ObjectVisitor* v) {
7522 #ifdef DEBUG
7523   bool found_block_before_deferred = false;
7524 #endif
7525   // Iterate over all handles in the blocks except for the last.
7526   for (int i = blocks()->length() - 2; i >= 0; --i) {
7527     Object** block = blocks()->at(i);
7528     if (last_handle_before_deferred_block_ != NULL &&
7529         (last_handle_before_deferred_block_ <= &block[kHandleBlockSize]) &&
7530         (last_handle_before_deferred_block_ >= block)) {
7531       v->VisitPointers(block, last_handle_before_deferred_block_);
7532       DCHECK(!found_block_before_deferred);
7533 #ifdef DEBUG
7534       found_block_before_deferred = true;
7535 #endif
7536     } else {
7537       v->VisitPointers(block, &block[kHandleBlockSize]);
7538     }
7539   }
7540
7541   DCHECK(last_handle_before_deferred_block_ == NULL ||
7542          found_block_before_deferred);
7543
7544   // Iterate over live handles in the last block (if any).
7545   if (!blocks()->is_empty()) {
7546     v->VisitPointers(blocks()->last(), handle_scope_data_.next);
7547   }
7548
7549   List<Context*>* context_lists[2] = { &saved_contexts_, &entered_contexts_};
7550   for (unsigned i = 0; i < ARRAY_SIZE(context_lists); i++) {
7551     if (context_lists[i]->is_empty()) continue;
7552     Object** start = reinterpret_cast<Object**>(&context_lists[i]->first());
7553     v->VisitPointers(start, start + context_lists[i]->length());
7554   }
7555 }
7556
7557
7558 void HandleScopeImplementer::Iterate(ObjectVisitor* v) {
7559   HandleScopeData* current = isolate_->handle_scope_data();
7560   handle_scope_data_ = *current;
7561   IterateThis(v);
7562 }
7563
7564
7565 char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) {
7566   HandleScopeImplementer* scope_implementer =
7567       reinterpret_cast<HandleScopeImplementer*>(storage);
7568   scope_implementer->IterateThis(v);
7569   return storage + ArchiveSpacePerThread();
7570 }
7571
7572
7573 DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) {
7574   DeferredHandles* deferred =
7575       new DeferredHandles(isolate()->handle_scope_data()->next, isolate());
7576
7577   while (!blocks_.is_empty()) {
7578     Object** block_start = blocks_.last();
7579     Object** block_limit = &block_start[kHandleBlockSize];
7580     // We should not need to check for SealHandleScope here. Assert this.
7581     DCHECK(prev_limit == block_limit ||
7582            !(block_start <= prev_limit && prev_limit <= block_limit));
7583     if (prev_limit == block_limit) break;
7584     deferred->blocks_.Add(blocks_.last());
7585     blocks_.RemoveLast();
7586   }
7587
7588   // deferred->blocks_ now contains the blocks installed on the
7589   // HandleScope stack since BeginDeferredScope was called, but in
7590   // reverse order.
7591
7592   DCHECK(prev_limit == NULL || !blocks_.is_empty());
7593
7594   DCHECK(!blocks_.is_empty() && prev_limit != NULL);
7595   DCHECK(last_handle_before_deferred_block_ != NULL);
7596   last_handle_before_deferred_block_ = NULL;
7597   return deferred;
7598 }
7599
7600
7601 void HandleScopeImplementer::BeginDeferredScope() {
7602   DCHECK(last_handle_before_deferred_block_ == NULL);
7603   last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next;
7604 }
7605
7606
7607 DeferredHandles::~DeferredHandles() {
7608   isolate_->UnlinkDeferredHandles(this);
7609
7610   for (int i = 0; i < blocks_.length(); i++) {
7611 #ifdef ENABLE_HANDLE_ZAPPING
7612     HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]);
7613 #endif
7614     isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]);
7615   }
7616 }
7617
7618
7619 void DeferredHandles::Iterate(ObjectVisitor* v) {
7620   DCHECK(!blocks_.is_empty());
7621
7622   DCHECK((first_block_limit_ >= blocks_.first()) &&
7623          (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize]));
7624
7625   v->VisitPointers(blocks_.first(), first_block_limit_);
7626
7627   for (int i = 1; i < blocks_.length(); i++) {
7628     v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]);
7629   }
7630 }
7631
7632
7633 void InvokeAccessorGetterCallback(
7634     v8::Local<v8::String> property,
7635     const v8::PropertyCallbackInfo<v8::Value>& info,
7636     v8::AccessorGetterCallback getter) {
7637   // Leaving JavaScript.
7638   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7639   Address getter_address = reinterpret_cast<Address>(reinterpret_cast<intptr_t>(
7640       getter));
7641   VMState<EXTERNAL> state(isolate);
7642   ExternalCallbackScope call_scope(isolate, getter_address);
7643   getter(property, info);
7644 }
7645
7646
7647 void InvokeFunctionCallback(const v8::FunctionCallbackInfo<v8::Value>& info,
7648                             v8::FunctionCallback callback) {
7649   Isolate* isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
7650   Address callback_address =
7651       reinterpret_cast<Address>(reinterpret_cast<intptr_t>(callback));
7652   VMState<EXTERNAL> state(isolate);
7653   ExternalCallbackScope call_scope(isolate, callback_address);
7654   callback(info);
7655 }
7656
7657
7658 } }  // namespace v8::internal