blob: 225865cf521161304f69d3d1e694b55e9c9bb960 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "accessors.h"
31#include "api.h"
32#include "bootstrapper.h"
33#include "compiler.h"
34#include "debug.h"
35#include "execution.h"
36#include "global-handles.h"
37#include "macro-assembler.h"
38#include "natives.h"
Steve Blockd0582a62009-12-15 09:54:21 +000039#include "snapshot.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000040
41namespace v8 {
42namespace internal {
43
44// A SourceCodeCache uses a FixedArray to store pairs of
45// (AsciiString*, JSFunction*), mapping names of native code files
46// (runtime.js, etc.) to precompiled functions. Instead of mapping
47// names to functions it might make sense to let the JS2C tool
48// generate an index for each native JS file.
49class SourceCodeCache BASE_EMBEDDED {
50 public:
51 explicit SourceCodeCache(Script::Type type): type_(type), cache_(NULL) { }
52
53 void Initialize(bool create_heap_objects) {
54 cache_ = create_heap_objects ? Heap::empty_fixed_array() : NULL;
55 }
56
57 void Iterate(ObjectVisitor* v) {
58 v->VisitPointer(bit_cast<Object**, FixedArray**>(&cache_));
59 }
60
61
62 bool Lookup(Vector<const char> name, Handle<JSFunction>* handle) {
63 for (int i = 0; i < cache_->length(); i+=2) {
64 SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
65 if (str->IsEqualTo(name)) {
66 *handle = Handle<JSFunction>(JSFunction::cast(cache_->get(i + 1)));
67 return true;
68 }
69 }
70 return false;
71 }
72
73
74 void Add(Vector<const char> name, Handle<JSFunction> fun) {
75 ASSERT(fun->IsBoilerplate());
76 HandleScope scope;
77 int length = cache_->length();
78 Handle<FixedArray> new_array =
79 Factory::NewFixedArray(length + 2, TENURED);
80 cache_->CopyTo(0, *new_array, 0, cache_->length());
81 cache_ = *new_array;
82 Handle<String> str = Factory::NewStringFromAscii(name, TENURED);
83 cache_->set(length, *str);
84 cache_->set(length + 1, *fun);
85 Script::cast(fun->shared()->script())->set_type(Smi::FromInt(type_));
86 }
87
88 private:
89 Script::Type type_;
90 FixedArray* cache_;
91 DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
92};
93
Steve Blocka7e24c12009-10-30 11:49:00 +000094static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
Steve Blockd0582a62009-12-15 09:54:21 +000095// This is for delete, not delete[].
96static List<char*>* delete_these_non_arrays_on_tear_down = NULL;
Leon Clarkee46be812010-01-19 14:06:41 +000097// This is for delete[]
98static List<char*>* delete_these_arrays_on_tear_down = NULL;
Steve Blockd0582a62009-12-15 09:54:21 +000099
100
101NativesExternalStringResource::NativesExternalStringResource(const char* source)
102 : data_(source), length_(StrLength(source)) {
103 if (delete_these_non_arrays_on_tear_down == NULL) {
104 delete_these_non_arrays_on_tear_down = new List<char*>(2);
105 }
106 // The resources are small objects and we only make a fixed number of
107 // them, but let's clean them up on exit for neatness.
108 delete_these_non_arrays_on_tear_down->
109 Add(reinterpret_cast<char*>(this));
110}
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
112
113Handle<String> Bootstrapper::NativesSourceLookup(int index) {
114 ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
115 if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
Steve Blockd0582a62009-12-15 09:54:21 +0000116 if (!Snapshot::IsEnabled() || FLAG_new_snapshot) {
117 // We can use external strings for the natives.
118 NativesExternalStringResource* resource =
119 new NativesExternalStringResource(
120 Natives::GetScriptSource(index).start());
121 Handle<String> source_code =
122 Factory::NewExternalStringFromAscii(resource);
123 Heap::natives_source_cache()->set(index, *source_code);
124 } else {
125 // Old snapshot code can't cope with external strings at all.
126 Handle<String> source_code =
127 Factory::NewStringFromAscii(Natives::GetScriptSource(index));
128 Heap::natives_source_cache()->set(index, *source_code);
129 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 }
131 Handle<Object> cached_source(Heap::natives_source_cache()->get(index));
132 return Handle<String>::cast(cached_source);
133}
134
135
Steve Blocka7e24c12009-10-30 11:49:00 +0000136void Bootstrapper::Initialize(bool create_heap_objects) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 extensions_cache.Initialize(create_heap_objects);
138}
139
140
Leon Clarkee46be812010-01-19 14:06:41 +0000141char* Bootstrapper::AllocateAutoDeletedArray(int bytes) {
142 char* memory = new char[bytes];
143 if (memory != NULL) {
144 if (delete_these_arrays_on_tear_down == NULL) {
145 delete_these_arrays_on_tear_down = new List<char*>(2);
146 }
147 delete_these_arrays_on_tear_down->Add(memory);
148 }
149 return memory;
150}
151
152
Steve Blocka7e24c12009-10-30 11:49:00 +0000153void Bootstrapper::TearDown() {
Steve Blockd0582a62009-12-15 09:54:21 +0000154 if (delete_these_non_arrays_on_tear_down != NULL) {
155 int len = delete_these_non_arrays_on_tear_down->length();
156 ASSERT(len < 20); // Don't use this mechanism for unbounded allocations.
157 for (int i = 0; i < len; i++) {
158 delete delete_these_non_arrays_on_tear_down->at(i);
Leon Clarkee46be812010-01-19 14:06:41 +0000159 delete_these_non_arrays_on_tear_down->at(i) = NULL;
Steve Blockd0582a62009-12-15 09:54:21 +0000160 }
161 delete delete_these_non_arrays_on_tear_down;
162 delete_these_non_arrays_on_tear_down = NULL;
163 }
164
Leon Clarkee46be812010-01-19 14:06:41 +0000165 if (delete_these_arrays_on_tear_down != NULL) {
166 int len = delete_these_arrays_on_tear_down->length();
167 ASSERT(len < 1000); // Don't use this mechanism for unbounded allocations.
168 for (int i = 0; i < len; i++) {
169 delete[] delete_these_arrays_on_tear_down->at(i);
170 delete_these_arrays_on_tear_down->at(i) = NULL;
171 }
172 delete delete_these_arrays_on_tear_down;
173 delete_these_arrays_on_tear_down = NULL;
174 }
175
Andrei Popescu31002712010-02-23 13:46:05 +0000176 extensions_cache.Initialize(false); // Yes, symmetrical
Steve Blocka7e24c12009-10-30 11:49:00 +0000177}
178
179
Steve Blocka7e24c12009-10-30 11:49:00 +0000180class Genesis BASE_EMBEDDED {
181 public:
182 Genesis(Handle<Object> global_object,
183 v8::Handle<v8::ObjectTemplate> global_template,
184 v8::ExtensionConfiguration* extensions);
Andrei Popescu31002712010-02-23 13:46:05 +0000185 ~Genesis() { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000186
187 Handle<Context> result() { return result_; }
188
189 Genesis* previous() { return previous_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000190
191 private:
192 Handle<Context> global_context_;
193
194 // There may be more than one active genesis object: When GC is
195 // triggered during environment creation there may be weak handle
196 // processing callbacks which may create new environments.
197 Genesis* previous_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000198
199 Handle<Context> global_context() { return global_context_; }
200
Andrei Popescu31002712010-02-23 13:46:05 +0000201 // Creates some basic objects. Used for creating a context from scratch.
202 void CreateRoots();
203 // Creates the empty function. Used for creating a context from scratch.
204 Handle<JSFunction> CreateEmptyFunction();
205 // Creates the global objects using the global and the template passed in
206 // through the API. We call this regardless of whether we are building a
207 // context from scratch or using a deserialized one from the partial snapshot
208 // but in the latter case we don't use the objects it produces directly, as
209 // we have to used the deserialized ones that are linked together with the
210 // rest of the context snapshot.
211 Handle<JSGlobalProxy> CreateNewGlobals(
212 v8::Handle<v8::ObjectTemplate> global_template,
213 Handle<Object> global_object,
214 Handle<GlobalObject>* global_proxy_out);
215 // Hooks the given global proxy into the context. If the context was created
216 // by deserialization then this will unhook the global proxy that was
217 // deserialized, leaving the GC to pick it up.
218 void HookUpGlobalProxy(Handle<GlobalObject> inner_global,
219 Handle<JSGlobalProxy> global_proxy);
Andrei Popescu402d9372010-02-26 13:31:12 +0000220 // Similarly, we want to use the inner global that has been created by the
221 // templates passed through the API. The inner global from the snapshot is
222 // detached from the other objects in the snapshot.
223 void HookUpInnerGlobal(Handle<GlobalObject> inner_global);
Andrei Popescu31002712010-02-23 13:46:05 +0000224 // New context initialization. Used for creating a context from scratch.
225 void InitializeGlobal(Handle<GlobalObject> inner_global,
226 Handle<JSFunction> empty_function);
227 // Installs the contents of the native .js files on the global objects.
228 // Used for creating a context from scratch.
Steve Blocka7e24c12009-10-30 11:49:00 +0000229 void InstallNativeFunctions();
230 bool InstallNatives();
Andrei Popescu31002712010-02-23 13:46:05 +0000231 // Used both for deserialized and from-scratch contexts to add the extensions
232 // provided.
233 static bool InstallExtensions(Handle<Context> global_context,
234 v8::ExtensionConfiguration* extensions);
235 static bool InstallExtension(const char* name);
236 static bool InstallExtension(v8::RegisteredExtension* current);
237 static void InstallSpecialObjects(Handle<Context> global_context);
Andrei Popescu402d9372010-02-26 13:31:12 +0000238 bool InstallJSBuiltins(Handle<JSBuiltinsObject> builtins);
Steve Blocka7e24c12009-10-30 11:49:00 +0000239 bool ConfigureApiObject(Handle<JSObject> object,
240 Handle<ObjectTemplateInfo> object_template);
241 bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
242
243 // Migrates all properties from the 'from' object to the 'to'
244 // object and overrides the prototype in 'to' with the one from
245 // 'from'.
246 void TransferObject(Handle<JSObject> from, Handle<JSObject> to);
247 void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
248 void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
249
250 Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
251 bool make_prototype_read_only,
252 bool make_prototype_enumerable = false);
253 void MakeFunctionInstancePrototypeWritable();
254
255 void AddSpecialFunction(Handle<JSObject> prototype,
256 const char* name,
257 Handle<Code> code);
258
259 void BuildSpecialFunctionTable();
260
261 static bool CompileBuiltin(int index);
262 static bool CompileNative(Vector<const char> name, Handle<String> source);
263 static bool CompileScriptCached(Vector<const char> name,
264 Handle<String> source,
265 SourceCodeCache* cache,
266 v8::Extension* extension,
Andrei Popescu31002712010-02-23 13:46:05 +0000267 Handle<Context> top_context,
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 bool use_runtime_context);
269
270 Handle<Context> result_;
Andrei Popescu31002712010-02-23 13:46:05 +0000271 Handle<JSFunction> empty_function_;
272 BootstrapperActive active_;
273 friend class Bootstrapper;
Steve Blocka7e24c12009-10-30 11:49:00 +0000274};
275
Steve Blocka7e24c12009-10-30 11:49:00 +0000276
277void Bootstrapper::Iterate(ObjectVisitor* v) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000278 extensions_cache.Iterate(v);
Steve Blockd0582a62009-12-15 09:54:21 +0000279 v->Synchronize("Extensions");
Steve Blocka7e24c12009-10-30 11:49:00 +0000280}
281
282
Steve Blocka7e24c12009-10-30 11:49:00 +0000283Handle<Context> Bootstrapper::CreateEnvironment(
284 Handle<Object> global_object,
285 v8::Handle<v8::ObjectTemplate> global_template,
286 v8::ExtensionConfiguration* extensions) {
Andrei Popescu31002712010-02-23 13:46:05 +0000287 HandleScope scope;
288 Handle<Context> env;
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 Genesis genesis(global_object, global_template, extensions);
Andrei Popescu31002712010-02-23 13:46:05 +0000290 env = genesis.result();
291 if (!env.is_null()) {
292 if (InstallExtensions(env, extensions)) {
293 return env;
294 }
295 }
296 return Handle<Context>();
Steve Blocka7e24c12009-10-30 11:49:00 +0000297}
298
299
300static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
301 // object.__proto__ = proto;
302 Handle<Map> old_to_map = Handle<Map>(object->map());
303 Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
304 new_to_map->set_prototype(*proto);
305 object->set_map(*new_to_map);
306}
307
308
309void Bootstrapper::DetachGlobal(Handle<Context> env) {
310 JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value());
311 SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
312 Factory::null_value());
313 env->set_global_proxy(env->global());
314 env->global()->set_global_receiver(env->global());
315}
316
317
Andrei Popescu74b3c142010-03-29 12:03:09 +0100318void Bootstrapper::ReattachGlobal(Handle<Context> env,
319 Handle<Object> global_object) {
320 ASSERT(global_object->IsJSGlobalProxy());
321 Handle<JSGlobalProxy> global = Handle<JSGlobalProxy>::cast(global_object);
322 env->global()->set_global_receiver(*global);
323 env->set_global_proxy(*global);
324 SetObjectPrototype(global, Handle<JSObject>(env->global()));
325 global->set_context(*env);
326}
327
328
Steve Blocka7e24c12009-10-30 11:49:00 +0000329static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
330 const char* name,
331 InstanceType type,
332 int instance_size,
333 Handle<JSObject> prototype,
334 Builtins::Name call,
335 bool is_ecma_native) {
336 Handle<String> symbol = Factory::LookupAsciiSymbol(name);
337 Handle<Code> call_code = Handle<Code>(Builtins::builtin(call));
338 Handle<JSFunction> function =
339 Factory::NewFunctionWithPrototype(symbol,
340 type,
341 instance_size,
342 prototype,
343 call_code,
344 is_ecma_native);
345 SetProperty(target, symbol, function, DONT_ENUM);
346 if (is_ecma_native) {
347 function->shared()->set_instance_class_name(*symbol);
348 }
349 return function;
350}
351
352
353Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
354 bool make_prototype_read_only,
355 bool make_prototype_enumerable) {
356 Handle<DescriptorArray> result = Factory::empty_descriptor_array();
357
358 // Add prototype.
359 PropertyAttributes attributes = static_cast<PropertyAttributes>(
360 (make_prototype_enumerable ? 0 : DONT_ENUM)
361 | DONT_DELETE
362 | (make_prototype_read_only ? READ_ONLY : 0));
363 result =
364 Factory::CopyAppendProxyDescriptor(
365 result,
366 Factory::prototype_symbol(),
367 Factory::NewProxy(&Accessors::FunctionPrototype),
368 attributes);
369
370 attributes =
371 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
372 // Add length.
373 result =
374 Factory::CopyAppendProxyDescriptor(
375 result,
376 Factory::length_symbol(),
377 Factory::NewProxy(&Accessors::FunctionLength),
378 attributes);
379
380 // Add name.
381 result =
382 Factory::CopyAppendProxyDescriptor(
383 result,
384 Factory::name_symbol(),
385 Factory::NewProxy(&Accessors::FunctionName),
386 attributes);
387
388 // Add arguments.
389 result =
390 Factory::CopyAppendProxyDescriptor(
391 result,
392 Factory::arguments_symbol(),
393 Factory::NewProxy(&Accessors::FunctionArguments),
394 attributes);
395
396 // Add caller.
397 result =
398 Factory::CopyAppendProxyDescriptor(
399 result,
400 Factory::caller_symbol(),
401 Factory::NewProxy(&Accessors::FunctionCaller),
402 attributes);
403
404 return result;
405}
406
407
Andrei Popescu31002712010-02-23 13:46:05 +0000408Handle<JSFunction> Genesis::CreateEmptyFunction() {
Steve Blocka7e24c12009-10-30 11:49:00 +0000409 // Allocate the map for function instances.
410 Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
411 global_context()->set_function_instance_map(*fm);
412 // Please note that the prototype property for function instances must be
413 // writable.
414 Handle<DescriptorArray> function_map_descriptors =
415 ComputeFunctionInstanceDescriptor(false, false);
416 fm->set_instance_descriptors(*function_map_descriptors);
417
418 // Allocate the function map first and then patch the prototype later
419 fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
420 global_context()->set_function_map(*fm);
421 function_map_descriptors = ComputeFunctionInstanceDescriptor(true);
422 fm->set_instance_descriptors(*function_map_descriptors);
423
424 Handle<String> object_name = Handle<String>(Heap::Object_symbol());
425
426 { // --- O b j e c t ---
427 Handle<JSFunction> object_fun =
428 Factory::NewFunction(object_name, Factory::null_value());
429 Handle<Map> object_function_map =
430 Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
431 object_fun->set_initial_map(*object_function_map);
432 object_function_map->set_constructor(*object_fun);
433
434 global_context()->set_object_function(*object_fun);
435
436 // Allocate a new prototype for the object function.
437 Handle<JSObject> prototype = Factory::NewJSObject(Top::object_function(),
438 TENURED);
439
440 global_context()->set_initial_object_prototype(*prototype);
441 SetPrototype(object_fun, prototype);
442 object_function_map->
443 set_instance_descriptors(Heap::empty_descriptor_array());
444 }
445
446 // Allocate the empty function as the prototype for function ECMAScript
447 // 262 15.3.4.
448 Handle<String> symbol = Factory::LookupAsciiSymbol("Empty");
449 Handle<JSFunction> empty_function =
450 Factory::NewFunction(symbol, Factory::null_value());
451
Andrei Popescu31002712010-02-23 13:46:05 +0000452 // --- E m p t y ---
453 Handle<Code> code =
454 Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
455 empty_function->set_code(*code);
456 Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
457 Handle<Script> script = Factory::NewScript(source);
458 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
459 empty_function->shared()->set_script(*script);
460 empty_function->shared()->set_start_position(0);
461 empty_function->shared()->set_end_position(source->length());
462 empty_function->shared()->DontAdaptArguments();
463 global_context()->function_map()->set_prototype(*empty_function);
464 global_context()->function_instance_map()->set_prototype(*empty_function);
Steve Blocka7e24c12009-10-30 11:49:00 +0000465
Andrei Popescu31002712010-02-23 13:46:05 +0000466 // Allocate the function map first and then patch the prototype later
467 Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
468 empty_fm->set_instance_descriptors(*function_map_descriptors);
469 empty_fm->set_prototype(global_context()->object_function()->prototype());
470 empty_function->set_map(*empty_fm);
471 return empty_function;
472}
473
474
475void Genesis::CreateRoots() {
476 // Allocate the global context FixedArray first and then patch the
477 // closure and extension object later (we need the empty function
478 // and the global object, but in order to create those, we need the
479 // global context).
480 global_context_ =
481 Handle<Context>::cast(
482 GlobalHandles::Create(*Factory::NewGlobalContext()));
483 Top::set_context(*global_context());
484
485 // Allocate the message listeners object.
486 {
487 v8::NeanderArray listeners;
488 global_context()->set_message_listeners(*listeners.value());
489 }
490}
491
492
493Handle<JSGlobalProxy> Genesis::CreateNewGlobals(
494 v8::Handle<v8::ObjectTemplate> global_template,
495 Handle<Object> global_object,
496 Handle<GlobalObject>* inner_global_out) {
497 // The argument global_template aka data is an ObjectTemplateInfo.
498 // It has a constructor pointer that points at global_constructor which is a
499 // FunctionTemplateInfo.
500 // The global_constructor is used to create or reinitialize the global_proxy.
501 // The global_constructor also has a prototype_template pointer that points at
502 // js_global_template which is an ObjectTemplateInfo.
503 // That in turn has a constructor pointer that points at
504 // js_global_constructor which is a FunctionTemplateInfo.
505 // js_global_constructor is used to make js_global_function
506 // js_global_function is used to make the new inner_global.
507 //
508 // --- G l o b a l ---
509 // Step 1: Create a fresh inner JSGlobalObject.
510 Handle<JSFunction> js_global_function;
511 Handle<ObjectTemplateInfo> js_global_template;
512 if (!global_template.IsEmpty()) {
513 // Get prototype template of the global_template.
514 Handle<ObjectTemplateInfo> data =
515 v8::Utils::OpenHandle(*global_template);
516 Handle<FunctionTemplateInfo> global_constructor =
517 Handle<FunctionTemplateInfo>(
518 FunctionTemplateInfo::cast(data->constructor()));
519 Handle<Object> proto_template(global_constructor->prototype_template());
520 if (!proto_template->IsUndefined()) {
521 js_global_template =
522 Handle<ObjectTemplateInfo>::cast(proto_template);
523 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000524 }
525
Andrei Popescu31002712010-02-23 13:46:05 +0000526 if (js_global_template.is_null()) {
527 Handle<String> name = Handle<String>(Heap::empty_symbol());
528 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
529 js_global_function =
530 Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
Andrei Popescu402d9372010-02-26 13:31:12 +0000531 JSGlobalObject::kSize, code, true);
Andrei Popescu31002712010-02-23 13:46:05 +0000532 // Change the constructor property of the prototype of the
533 // hidden global function to refer to the Object function.
534 Handle<JSObject> prototype =
535 Handle<JSObject>(
536 JSObject::cast(js_global_function->instance_prototype()));
537 SetProperty(prototype, Factory::constructor_symbol(),
538 Top::object_function(), NONE);
539 } else {
540 Handle<FunctionTemplateInfo> js_global_constructor(
541 FunctionTemplateInfo::cast(js_global_template->constructor()));
542 js_global_function =
543 Factory::CreateApiFunction(js_global_constructor,
544 Factory::InnerGlobalObject);
Steve Blocka7e24c12009-10-30 11:49:00 +0000545 }
546
Andrei Popescu31002712010-02-23 13:46:05 +0000547 js_global_function->initial_map()->set_is_hidden_prototype();
548 Handle<GlobalObject> inner_global =
549 Factory::NewGlobalObject(js_global_function);
550 if (inner_global_out != NULL) {
551 *inner_global_out = inner_global;
552 }
553
554 // Step 2: create or re-initialize the global proxy object.
555 Handle<JSFunction> global_proxy_function;
556 if (global_template.IsEmpty()) {
557 Handle<String> name = Handle<String>(Heap::empty_symbol());
558 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
559 global_proxy_function =
560 Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
561 JSGlobalProxy::kSize, code, true);
562 } else {
563 Handle<ObjectTemplateInfo> data =
564 v8::Utils::OpenHandle(*global_template);
565 Handle<FunctionTemplateInfo> global_constructor(
566 FunctionTemplateInfo::cast(data->constructor()));
567 global_proxy_function =
568 Factory::CreateApiFunction(global_constructor,
569 Factory::OuterGlobalObject);
570 }
571
572 Handle<String> global_name = Factory::LookupAsciiSymbol("global");
573 global_proxy_function->shared()->set_instance_class_name(*global_name);
574 global_proxy_function->initial_map()->set_is_access_check_needed(true);
575
576 // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
577 // Return the global proxy.
578
579 if (global_object.location() != NULL) {
580 ASSERT(global_object->IsJSGlobalProxy());
581 return ReinitializeJSGlobalProxy(
582 global_proxy_function,
583 Handle<JSGlobalProxy>::cast(global_object));
584 } else {
585 return Handle<JSGlobalProxy>::cast(
586 Factory::NewJSObject(global_proxy_function, TENURED));
587 }
588}
589
590
591void Genesis::HookUpGlobalProxy(Handle<GlobalObject> inner_global,
592 Handle<JSGlobalProxy> global_proxy) {
593 // Set the global context for the global object.
594 inner_global->set_global_context(*global_context());
595 inner_global->set_global_receiver(*global_proxy);
596 global_proxy->set_context(*global_context());
597 global_context()->set_global_proxy(*global_proxy);
598}
599
600
Andrei Popescu402d9372010-02-26 13:31:12 +0000601void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
602 Handle<GlobalObject> inner_global_from_snapshot(
603 GlobalObject::cast(global_context_->extension()));
604 Handle<JSBuiltinsObject> builtins_global(global_context_->builtins());
605 global_context_->set_extension(*inner_global);
606 global_context_->set_global(*inner_global);
607 global_context_->set_security_token(*inner_global);
608 static const PropertyAttributes attributes =
609 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
610 ForceSetProperty(builtins_global,
611 Factory::LookupAsciiSymbol("global"),
612 inner_global,
613 attributes);
614 // Setup the reference from the global object to the builtins object.
615 JSGlobalObject::cast(*inner_global)->set_builtins(*builtins_global);
616 TransferNamedProperties(inner_global_from_snapshot, inner_global);
617 TransferIndexedProperties(inner_global_from_snapshot, inner_global);
618}
619
620
621// This is only called if we are not using snapshots. The equivalent
622// work in the snapshot case is done in HookUpInnerGlobal.
Andrei Popescu31002712010-02-23 13:46:05 +0000623void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
624 Handle<JSFunction> empty_function) {
625 // --- G l o b a l C o n t e x t ---
626 // Use the empty function as closure (no scope info).
627 global_context()->set_closure(*empty_function);
628 global_context()->set_fcontext(*global_context());
629 global_context()->set_previous(NULL);
630 // Set extension and global object.
631 global_context()->set_extension(*inner_global);
632 global_context()->set_global(*inner_global);
633 // Security setup: Set the security token of the global object to
634 // its the inner global. This makes the security check between two
635 // different contexts fail by default even in case of global
636 // object reinitialization.
637 global_context()->set_security_token(*inner_global);
638
639 Handle<String> object_name = Handle<String>(Heap::Object_symbol());
640 SetProperty(inner_global, object_name, Top::object_function(), DONT_ENUM);
641
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 Handle<JSObject> global = Handle<JSObject>(global_context()->global());
643
644 // Install global Function object
645 InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize,
646 empty_function, Builtins::Illegal, true); // ECMA native.
647
648 { // --- A r r a y ---
649 Handle<JSFunction> array_function =
650 InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize,
651 Top::initial_object_prototype(), Builtins::ArrayCode,
652 true);
653 array_function->shared()->set_construct_stub(
654 Builtins::builtin(Builtins::ArrayConstructCode));
655 array_function->shared()->DontAdaptArguments();
656
657 // This seems a bit hackish, but we need to make sure Array.length
658 // is 1.
659 array_function->shared()->set_length(1);
660 Handle<DescriptorArray> array_descriptors =
661 Factory::CopyAppendProxyDescriptor(
662 Factory::empty_descriptor_array(),
663 Factory::length_symbol(),
664 Factory::NewProxy(&Accessors::ArrayLength),
665 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE));
666
667 // Cache the fast JavaScript array map
668 global_context()->set_js_array_map(array_function->initial_map());
669 global_context()->js_array_map()->set_instance_descriptors(
670 *array_descriptors);
671 // array_function is used internally. JS code creating array object should
672 // search for the 'Array' property on the global object and use that one
673 // as the constructor. 'Array' property on a global object can be
674 // overwritten by JS code.
675 global_context()->set_array_function(*array_function);
676 }
677
678 { // --- N u m b e r ---
679 Handle<JSFunction> number_fun =
680 InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize,
681 Top::initial_object_prototype(), Builtins::Illegal,
682 true);
683 global_context()->set_number_function(*number_fun);
684 }
685
686 { // --- B o o l e a n ---
687 Handle<JSFunction> boolean_fun =
688 InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize,
689 Top::initial_object_prototype(), Builtins::Illegal,
690 true);
691 global_context()->set_boolean_function(*boolean_fun);
692 }
693
694 { // --- S t r i n g ---
695 Handle<JSFunction> string_fun =
696 InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize,
697 Top::initial_object_prototype(), Builtins::Illegal,
698 true);
699 global_context()->set_string_function(*string_fun);
700 // Add 'length' property to strings.
701 Handle<DescriptorArray> string_descriptors =
702 Factory::CopyAppendProxyDescriptor(
703 Factory::empty_descriptor_array(),
704 Factory::length_symbol(),
705 Factory::NewProxy(&Accessors::StringLength),
706 static_cast<PropertyAttributes>(DONT_ENUM |
707 DONT_DELETE |
708 READ_ONLY));
709
710 Handle<Map> string_map =
711 Handle<Map>(global_context()->string_function()->initial_map());
712 string_map->set_instance_descriptors(*string_descriptors);
713 }
714
715 { // --- D a t e ---
716 // Builtin functions for Date.prototype.
717 Handle<JSFunction> date_fun =
718 InstallFunction(global, "Date", JS_VALUE_TYPE, JSValue::kSize,
719 Top::initial_object_prototype(), Builtins::Illegal,
720 true);
721
722 global_context()->set_date_function(*date_fun);
723 }
724
725
726 { // -- R e g E x p
727 // Builtin functions for RegExp.prototype.
728 Handle<JSFunction> regexp_fun =
729 InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
730 Top::initial_object_prototype(), Builtins::Illegal,
731 true);
732
733 global_context()->set_regexp_function(*regexp_fun);
734 }
735
736 { // -- J S O N
737 Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON"));
738 Handle<JSFunction> cons = Factory::NewFunction(
739 name,
740 Factory::the_hole_value());
741 cons->SetInstancePrototype(global_context()->initial_object_prototype());
742 cons->SetInstanceClassName(*name);
743 Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED);
744 ASSERT(json_object->IsJSObject());
745 SetProperty(global, name, json_object, DONT_ENUM);
746 global_context()->set_json_object(*json_object);
747 }
748
749 { // --- arguments_boilerplate_
750 // Make sure we can recognize argument objects at runtime.
751 // This is done by introducing an anonymous function with
752 // class_name equals 'Arguments'.
753 Handle<String> symbol = Factory::LookupAsciiSymbol("Arguments");
754 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
755 Handle<JSObject> prototype =
756 Handle<JSObject>(
757 JSObject::cast(global_context()->object_function()->prototype()));
758
759 Handle<JSFunction> function =
760 Factory::NewFunctionWithPrototype(symbol,
761 JS_OBJECT_TYPE,
762 JSObject::kHeaderSize,
763 prototype,
764 code,
765 false);
766 ASSERT(!function->has_initial_map());
767 function->shared()->set_instance_class_name(*symbol);
768 function->shared()->set_expected_nof_properties(2);
769 Handle<JSObject> result = Factory::NewJSObject(function);
770
771 global_context()->set_arguments_boilerplate(*result);
772 // Note: callee must be added as the first property and
773 // length must be added as the second property.
774 SetProperty(result, Factory::callee_symbol(),
775 Factory::undefined_value(),
776 DONT_ENUM);
777 SetProperty(result, Factory::length_symbol(),
778 Factory::undefined_value(),
779 DONT_ENUM);
780
781#ifdef DEBUG
782 LookupResult lookup;
783 result->LocalLookup(Heap::callee_symbol(), &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +0000784 ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index);
786
787 result->LocalLookup(Heap::length_symbol(), &lookup);
Andrei Popescu402d9372010-02-26 13:31:12 +0000788 ASSERT(lookup.IsProperty() && (lookup.type() == FIELD));
Steve Blocka7e24c12009-10-30 11:49:00 +0000789 ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index);
790
791 ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index);
792 ASSERT(result->map()->inobject_properties() > Heap::arguments_length_index);
793
794 // Check the state of the object.
795 ASSERT(result->HasFastProperties());
796 ASSERT(result->HasFastElements());
797#endif
798 }
799
800 { // --- context extension
801 // Create a function for the context extension objects.
802 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
803 Handle<JSFunction> context_extension_fun =
804 Factory::NewFunction(Factory::empty_symbol(),
805 JS_CONTEXT_EXTENSION_OBJECT_TYPE,
806 JSObject::kHeaderSize,
807 code,
808 true);
809
810 Handle<String> name = Factory::LookupAsciiSymbol("context_extension");
811 context_extension_fun->shared()->set_instance_class_name(*name);
812 global_context()->set_context_extension_function(*context_extension_fun);
813 }
814
815
816 {
817 // Setup the call-as-function delegate.
818 Handle<Code> code =
819 Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction));
820 Handle<JSFunction> delegate =
821 Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
822 JSObject::kHeaderSize, code, true);
823 global_context()->set_call_as_function_delegate(*delegate);
824 delegate->shared()->DontAdaptArguments();
825 }
826
827 {
828 // Setup the call-as-constructor delegate.
829 Handle<Code> code =
830 Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsConstructor));
831 Handle<JSFunction> delegate =
832 Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
833 JSObject::kHeaderSize, code, true);
834 global_context()->set_call_as_constructor_delegate(*delegate);
835 delegate->shared()->DontAdaptArguments();
836 }
837
838 global_context()->set_special_function_table(Heap::empty_fixed_array());
839
840 // Initialize the out of memory slot.
841 global_context()->set_out_of_memory(Heap::false_value());
842
843 // Initialize the data slot.
844 global_context()->set_data(Heap::undefined_value());
845}
846
847
848bool Genesis::CompileBuiltin(int index) {
849 Vector<const char> name = Natives::GetScriptName(index);
850 Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
851 return CompileNative(name, source_code);
852}
853
854
855bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
856 HandleScope scope;
857#ifdef ENABLE_DEBUGGER_SUPPORT
858 Debugger::set_compiling_natives(true);
859#endif
Andrei Popescu31002712010-02-23 13:46:05 +0000860 bool result = CompileScriptCached(name,
861 source,
862 NULL,
863 NULL,
864 Handle<Context>(Top::context()),
865 true);
Steve Blocka7e24c12009-10-30 11:49:00 +0000866 ASSERT(Top::has_pending_exception() != result);
867 if (!result) Top::clear_pending_exception();
868#ifdef ENABLE_DEBUGGER_SUPPORT
869 Debugger::set_compiling_natives(false);
870#endif
871 return result;
872}
873
874
875bool Genesis::CompileScriptCached(Vector<const char> name,
876 Handle<String> source,
877 SourceCodeCache* cache,
878 v8::Extension* extension,
Andrei Popescu31002712010-02-23 13:46:05 +0000879 Handle<Context> top_context,
Steve Blocka7e24c12009-10-30 11:49:00 +0000880 bool use_runtime_context) {
881 HandleScope scope;
882 Handle<JSFunction> boilerplate;
883
884 // If we can't find the function in the cache, we compile a new
885 // function and insert it into the cache.
Andrei Popescu31002712010-02-23 13:46:05 +0000886 if (cache == NULL || !cache->Lookup(name, &boilerplate)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000887 ASSERT(source->IsAsciiRepresentation());
888 Handle<String> script_name = Factory::NewStringFromUtf8(name);
Andrei Popescu31002712010-02-23 13:46:05 +0000889 boilerplate = Compiler::Compile(
890 source,
891 script_name,
892 0,
893 0,
894 extension,
895 NULL,
Andrei Popescu402d9372010-02-26 13:31:12 +0000896 Handle<String>::null(),
Andrei Popescu31002712010-02-23 13:46:05 +0000897 use_runtime_context ? NATIVES_CODE : NOT_NATIVES_CODE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000898 if (boilerplate.is_null()) return false;
Andrei Popescu31002712010-02-23 13:46:05 +0000899 if (cache != NULL) cache->Add(name, boilerplate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000900 }
901
902 // Setup the function context. Conceptually, we should clone the
903 // function before overwriting the context but since we're in a
904 // single-threaded environment it is not strictly necessary.
Andrei Popescu31002712010-02-23 13:46:05 +0000905 ASSERT(top_context->IsGlobalContext());
Steve Blocka7e24c12009-10-30 11:49:00 +0000906 Handle<Context> context =
907 Handle<Context>(use_runtime_context
Andrei Popescu31002712010-02-23 13:46:05 +0000908 ? Handle<Context>(top_context->runtime_context())
909 : top_context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000910 Handle<JSFunction> fun =
911 Factory::NewFunctionFromBoilerplate(boilerplate, context);
912
Leon Clarke4515c472010-02-03 11:58:03 +0000913 // Call function using either the runtime object or the global
Steve Blocka7e24c12009-10-30 11:49:00 +0000914 // object as the receiver. Provide no parameters.
915 Handle<Object> receiver =
916 Handle<Object>(use_runtime_context
Andrei Popescu31002712010-02-23 13:46:05 +0000917 ? top_context->builtins()
918 : top_context->global());
Steve Blocka7e24c12009-10-30 11:49:00 +0000919 bool has_pending_exception;
920 Handle<Object> result =
921 Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
922 if (has_pending_exception) return false;
Andrei Popescu402d9372010-02-26 13:31:12 +0000923 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +0000924}
925
926
927#define INSTALL_NATIVE(Type, name, var) \
928 Handle<String> var##_name = Factory::LookupAsciiSymbol(name); \
929 global_context()->set_##var(Type::cast(global_context()-> \
930 builtins()-> \
931 GetProperty(*var##_name)));
932
933void Genesis::InstallNativeFunctions() {
934 HandleScope scope;
935 INSTALL_NATIVE(JSFunction, "CreateDate", create_date_fun);
936 INSTALL_NATIVE(JSFunction, "ToNumber", to_number_fun);
937 INSTALL_NATIVE(JSFunction, "ToString", to_string_fun);
938 INSTALL_NATIVE(JSFunction, "ToDetailString", to_detail_string_fun);
939 INSTALL_NATIVE(JSFunction, "ToObject", to_object_fun);
940 INSTALL_NATIVE(JSFunction, "ToInteger", to_integer_fun);
941 INSTALL_NATIVE(JSFunction, "ToUint32", to_uint32_fun);
942 INSTALL_NATIVE(JSFunction, "ToInt32", to_int32_fun);
Leon Clarkee46be812010-01-19 14:06:41 +0000943 INSTALL_NATIVE(JSFunction, "GlobalEval", global_eval_fun);
Steve Blocka7e24c12009-10-30 11:49:00 +0000944 INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
945 INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance",
946 configure_instance_fun);
947 INSTALL_NATIVE(JSFunction, "MakeMessage", make_message_fun);
948 INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun);
949 INSTALL_NATIVE(JSObject, "functionCache", function_cache);
950}
951
952#undef INSTALL_NATIVE
953
954
955bool Genesis::InstallNatives() {
956 HandleScope scope;
957
958 // Create a function for the builtins object. Allocate space for the
959 // JavaScript builtins, a reference to the builtins object
960 // (itself) and a reference to the global_context directly in the object.
961 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
962 Handle<JSFunction> builtins_fun =
963 Factory::NewFunction(Factory::empty_symbol(), JS_BUILTINS_OBJECT_TYPE,
964 JSBuiltinsObject::kSize, code, true);
965
966 Handle<String> name = Factory::LookupAsciiSymbol("builtins");
967 builtins_fun->shared()->set_instance_class_name(*name);
968
969 // Allocate the builtins object.
970 Handle<JSBuiltinsObject> builtins =
971 Handle<JSBuiltinsObject>::cast(Factory::NewGlobalObject(builtins_fun));
972 builtins->set_builtins(*builtins);
973 builtins->set_global_context(*global_context());
974 builtins->set_global_receiver(*builtins);
975
976 // Setup the 'global' properties of the builtins object. The
977 // 'global' property that refers to the global object is the only
978 // way to get from code running in the builtins context to the
979 // global object.
980 static const PropertyAttributes attributes =
981 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
982 SetProperty(builtins, Factory::LookupAsciiSymbol("global"),
983 Handle<Object>(global_context()->global()), attributes);
984
985 // Setup the reference from the global object to the builtins object.
986 JSGlobalObject::cast(global_context()->global())->set_builtins(*builtins);
987
988 // Create a bridge function that has context in the global context.
989 Handle<JSFunction> bridge =
990 Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value());
991 ASSERT(bridge->context() == *Top::global_context());
992
993 // Allocate the builtins context.
994 Handle<Context> context =
995 Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
996 context->set_global(*builtins); // override builtins global object
997
998 global_context()->set_runtime_context(*context);
999
1000 { // -- S c r i p t
1001 // Builtin functions for Script.
1002 Handle<JSFunction> script_fun =
1003 InstallFunction(builtins, "Script", JS_VALUE_TYPE, JSValue::kSize,
1004 Top::initial_object_prototype(), Builtins::Illegal,
1005 false);
1006 Handle<JSObject> prototype =
1007 Factory::NewJSObject(Top::object_function(), TENURED);
1008 SetPrototype(script_fun, prototype);
1009 global_context()->set_script_function(*script_fun);
1010
1011 // Add 'source' and 'data' property to scripts.
1012 PropertyAttributes common_attributes =
1013 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
1014 Handle<Proxy> proxy_source = Factory::NewProxy(&Accessors::ScriptSource);
1015 Handle<DescriptorArray> script_descriptors =
1016 Factory::CopyAppendProxyDescriptor(
1017 Factory::empty_descriptor_array(),
1018 Factory::LookupAsciiSymbol("source"),
1019 proxy_source,
1020 common_attributes);
1021 Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName);
1022 script_descriptors =
1023 Factory::CopyAppendProxyDescriptor(
1024 script_descriptors,
1025 Factory::LookupAsciiSymbol("name"),
1026 proxy_name,
1027 common_attributes);
1028 Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId);
1029 script_descriptors =
1030 Factory::CopyAppendProxyDescriptor(
1031 script_descriptors,
1032 Factory::LookupAsciiSymbol("id"),
1033 proxy_id,
1034 common_attributes);
1035 Handle<Proxy> proxy_line_offset =
1036 Factory::NewProxy(&Accessors::ScriptLineOffset);
1037 script_descriptors =
1038 Factory::CopyAppendProxyDescriptor(
1039 script_descriptors,
1040 Factory::LookupAsciiSymbol("line_offset"),
1041 proxy_line_offset,
1042 common_attributes);
1043 Handle<Proxy> proxy_column_offset =
1044 Factory::NewProxy(&Accessors::ScriptColumnOffset);
1045 script_descriptors =
1046 Factory::CopyAppendProxyDescriptor(
1047 script_descriptors,
1048 Factory::LookupAsciiSymbol("column_offset"),
1049 proxy_column_offset,
1050 common_attributes);
1051 Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData);
1052 script_descriptors =
1053 Factory::CopyAppendProxyDescriptor(
1054 script_descriptors,
1055 Factory::LookupAsciiSymbol("data"),
1056 proxy_data,
1057 common_attributes);
1058 Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
1059 script_descriptors =
1060 Factory::CopyAppendProxyDescriptor(
1061 script_descriptors,
1062 Factory::LookupAsciiSymbol("type"),
1063 proxy_type,
1064 common_attributes);
1065 Handle<Proxy> proxy_compilation_type =
1066 Factory::NewProxy(&Accessors::ScriptCompilationType);
1067 script_descriptors =
1068 Factory::CopyAppendProxyDescriptor(
1069 script_descriptors,
1070 Factory::LookupAsciiSymbol("compilation_type"),
1071 proxy_compilation_type,
1072 common_attributes);
1073 Handle<Proxy> proxy_line_ends =
1074 Factory::NewProxy(&Accessors::ScriptLineEnds);
1075 script_descriptors =
1076 Factory::CopyAppendProxyDescriptor(
1077 script_descriptors,
1078 Factory::LookupAsciiSymbol("line_ends"),
1079 proxy_line_ends,
1080 common_attributes);
1081 Handle<Proxy> proxy_context_data =
1082 Factory::NewProxy(&Accessors::ScriptContextData);
1083 script_descriptors =
1084 Factory::CopyAppendProxyDescriptor(
1085 script_descriptors,
1086 Factory::LookupAsciiSymbol("context_data"),
1087 proxy_context_data,
1088 common_attributes);
Steve Blockd0582a62009-12-15 09:54:21 +00001089 Handle<Proxy> proxy_eval_from_script =
1090 Factory::NewProxy(&Accessors::ScriptEvalFromScript);
Steve Blocka7e24c12009-10-30 11:49:00 +00001091 script_descriptors =
1092 Factory::CopyAppendProxyDescriptor(
1093 script_descriptors,
Steve Blockd0582a62009-12-15 09:54:21 +00001094 Factory::LookupAsciiSymbol("eval_from_script"),
1095 proxy_eval_from_script,
Steve Blocka7e24c12009-10-30 11:49:00 +00001096 common_attributes);
Steve Blockd0582a62009-12-15 09:54:21 +00001097 Handle<Proxy> proxy_eval_from_script_position =
1098 Factory::NewProxy(&Accessors::ScriptEvalFromScriptPosition);
Steve Blocka7e24c12009-10-30 11:49:00 +00001099 script_descriptors =
1100 Factory::CopyAppendProxyDescriptor(
1101 script_descriptors,
Steve Blockd0582a62009-12-15 09:54:21 +00001102 Factory::LookupAsciiSymbol("eval_from_script_position"),
1103 proxy_eval_from_script_position,
1104 common_attributes);
1105 Handle<Proxy> proxy_eval_from_function_name =
1106 Factory::NewProxy(&Accessors::ScriptEvalFromFunctionName);
1107 script_descriptors =
1108 Factory::CopyAppendProxyDescriptor(
1109 script_descriptors,
1110 Factory::LookupAsciiSymbol("eval_from_function_name"),
1111 proxy_eval_from_function_name,
Steve Blocka7e24c12009-10-30 11:49:00 +00001112 common_attributes);
1113
1114 Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
1115 script_map->set_instance_descriptors(*script_descriptors);
1116
1117 // Allocate the empty script.
1118 Handle<Script> script = Factory::NewScript(Factory::empty_string());
1119 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
Andrei Popescu31002712010-02-23 13:46:05 +00001120 Heap::public_set_empty_script(*script);
Steve Blocka7e24c12009-10-30 11:49:00 +00001121 }
1122
Andrei Popescu31002712010-02-23 13:46:05 +00001123 // Install natives.
1124 for (int i = Natives::GetDebuggerCount();
1125 i < Natives::GetBuiltinsCount();
1126 i++) {
1127 Vector<const char> name = Natives::GetScriptName(i);
1128 if (!CompileBuiltin(i)) return false;
Andrei Popescu402d9372010-02-26 13:31:12 +00001129 // TODO(ager): We really only need to install the JS builtin
1130 // functions on the builtins object after compiling and running
1131 // runtime.js.
1132 if (!InstallJSBuiltins(builtins)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001133 }
1134
1135 InstallNativeFunctions();
1136
1137 // Install Function.prototype.call and apply.
1138 { Handle<String> key = Factory::function_class_symbol();
1139 Handle<JSFunction> function =
1140 Handle<JSFunction>::cast(GetProperty(Top::global(), key));
1141 Handle<JSObject> proto =
1142 Handle<JSObject>(JSObject::cast(function->instance_prototype()));
1143
1144 // Install the call and the apply functions.
1145 Handle<JSFunction> call =
1146 InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
1147 Factory::NewJSObject(Top::object_function(), TENURED),
1148 Builtins::FunctionCall,
1149 false);
1150 Handle<JSFunction> apply =
1151 InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
1152 Factory::NewJSObject(Top::object_function(), TENURED),
1153 Builtins::FunctionApply,
1154 false);
1155
1156 // Make sure that Function.prototype.call appears to be compiled.
1157 // The code will never be called, but inline caching for call will
1158 // only work if it appears to be compiled.
1159 call->shared()->DontAdaptArguments();
1160 ASSERT(call->is_compiled());
1161
1162 // Set the expected parameters for apply to 2; required by builtin.
1163 apply->shared()->set_formal_parameter_count(2);
1164
1165 // Set the lengths for the functions to satisfy ECMA-262.
1166 call->shared()->set_length(1);
1167 apply->shared()->set_length(2);
1168 }
1169
1170#ifdef DEBUG
1171 builtins->Verify();
1172#endif
Andrei Popescu31002712010-02-23 13:46:05 +00001173
Steve Blocka7e24c12009-10-30 11:49:00 +00001174 return true;
1175}
1176
1177
Andrei Popescu31002712010-02-23 13:46:05 +00001178int BootstrapperActive::nesting_ = 0;
1179
1180
1181bool Bootstrapper::InstallExtensions(Handle<Context> global_context,
1182 v8::ExtensionConfiguration* extensions) {
1183 BootstrapperActive active;
1184 SaveContext saved_context;
1185 Top::set_context(*global_context);
1186 if (!Genesis::InstallExtensions(global_context, extensions)) return false;
1187 Genesis::InstallSpecialObjects(global_context);
1188 return true;
1189}
1190
1191
1192void Genesis::InstallSpecialObjects(Handle<Context> global_context) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001193 HandleScope scope;
1194 Handle<JSGlobalObject> js_global(
Andrei Popescu31002712010-02-23 13:46:05 +00001195 JSGlobalObject::cast(global_context->global()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 // Expose the natives in global if a name for it is specified.
1197 if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
1198 Handle<String> natives_string =
1199 Factory::LookupAsciiSymbol(FLAG_expose_natives_as);
1200 SetProperty(js_global, natives_string,
1201 Handle<JSObject>(js_global->builtins()), DONT_ENUM);
1202 }
1203
1204 Handle<Object> Error = GetProperty(js_global, "Error");
1205 if (Error->IsJSObject()) {
1206 Handle<String> name = Factory::LookupAsciiSymbol("stackTraceLimit");
1207 SetProperty(Handle<JSObject>::cast(Error),
1208 name,
1209 Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)),
1210 NONE);
1211 }
1212
1213#ifdef ENABLE_DEBUGGER_SUPPORT
1214 // Expose the debug global object in global if a name for it is specified.
1215 if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
1216 // If loading fails we just bail out without installing the
1217 // debugger but without tanking the whole context.
Andrei Popescu31002712010-02-23 13:46:05 +00001218 if (!Debug::Load()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001219 // Set the security token for the debugger context to the same as
1220 // the shell global context to allow calling between these (otherwise
1221 // exposing debug global object doesn't make much sense).
1222 Debug::debug_context()->set_security_token(
Andrei Popescu31002712010-02-23 13:46:05 +00001223 global_context->security_token());
Steve Blocka7e24c12009-10-30 11:49:00 +00001224
1225 Handle<String> debug_string =
1226 Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
1227 SetProperty(js_global, debug_string,
1228 Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
1229 }
1230#endif
Steve Blocka7e24c12009-10-30 11:49:00 +00001231}
1232
1233
Andrei Popescu31002712010-02-23 13:46:05 +00001234bool Genesis::InstallExtensions(Handle<Context> global_context,
1235 v8::ExtensionConfiguration* extensions) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001236 // Clear coloring of extension list
1237 v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
1238 while (current != NULL) {
1239 current->set_state(v8::UNVISITED);
1240 current = current->next();
1241 }
Andrei Popescu31002712010-02-23 13:46:05 +00001242 // Install auto extensions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001243 current = v8::RegisteredExtension::first_extension();
1244 while (current != NULL) {
1245 if (current->extension()->auto_enable())
1246 InstallExtension(current);
1247 current = current->next();
1248 }
1249
1250 if (FLAG_expose_gc) InstallExtension("v8/gc");
1251
1252 if (extensions == NULL) return true;
1253 // Install required extensions
1254 int count = v8::ImplementationUtilities::GetNameCount(extensions);
1255 const char** names = v8::ImplementationUtilities::GetNames(extensions);
1256 for (int i = 0; i < count; i++) {
1257 if (!InstallExtension(names[i]))
1258 return false;
1259 }
1260
1261 return true;
1262}
1263
1264
1265// Installs a named extension. This methods is unoptimized and does
1266// not scale well if we want to support a large number of extensions.
1267bool Genesis::InstallExtension(const char* name) {
1268 v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
1269 // Loop until we find the relevant extension
1270 while (current != NULL) {
1271 if (strcmp(name, current->extension()->name()) == 0) break;
1272 current = current->next();
1273 }
1274 // Didn't find the extension; fail.
1275 if (current == NULL) {
1276 v8::Utils::ReportApiFailure(
1277 "v8::Context::New()", "Cannot find required extension");
1278 return false;
1279 }
1280 return InstallExtension(current);
1281}
1282
1283
1284bool Genesis::InstallExtension(v8::RegisteredExtension* current) {
1285 HandleScope scope;
1286
1287 if (current->state() == v8::INSTALLED) return true;
1288 // The current node has already been visited so there must be a
1289 // cycle in the dependency graph; fail.
1290 if (current->state() == v8::VISITED) {
1291 v8::Utils::ReportApiFailure(
1292 "v8::Context::New()", "Circular extension dependency");
1293 return false;
1294 }
1295 ASSERT(current->state() == v8::UNVISITED);
1296 current->set_state(v8::VISITED);
1297 v8::Extension* extension = current->extension();
1298 // Install the extension's dependencies
1299 for (int i = 0; i < extension->dependency_count(); i++) {
1300 if (!InstallExtension(extension->dependencies()[i])) return false;
1301 }
1302 Vector<const char> source = CStrVector(extension->source());
1303 Handle<String> source_code = Factory::NewStringFromAscii(source);
1304 bool result = CompileScriptCached(CStrVector(extension->name()),
1305 source_code,
Andrei Popescu31002712010-02-23 13:46:05 +00001306 &extensions_cache,
1307 extension,
1308 Handle<Context>(Top::context()),
Steve Blocka7e24c12009-10-30 11:49:00 +00001309 false);
1310 ASSERT(Top::has_pending_exception() != result);
1311 if (!result) {
1312 Top::clear_pending_exception();
Steve Blocka7e24c12009-10-30 11:49:00 +00001313 }
1314 current->set_state(v8::INSTALLED);
1315 return result;
1316}
1317
1318
Andrei Popescu402d9372010-02-26 13:31:12 +00001319bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) {
1320 HandleScope scope;
1321 for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
1322 Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
1323 Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
1324 Handle<JSFunction> function
1325 = Handle<JSFunction>(JSFunction::cast(builtins->GetProperty(*name)));
1326 builtins->set_javascript_builtin(id, *function);
1327 Handle<SharedFunctionInfo> shared
1328 = Handle<SharedFunctionInfo>(function->shared());
1329 if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false;
1330 }
1331 return true;
Andrei Popescu31002712010-02-23 13:46:05 +00001332}
1333
1334
Steve Blocka7e24c12009-10-30 11:49:00 +00001335bool Genesis::ConfigureGlobalObjects(
1336 v8::Handle<v8::ObjectTemplate> global_proxy_template) {
1337 Handle<JSObject> global_proxy(
1338 JSObject::cast(global_context()->global_proxy()));
Andrei Popescu402d9372010-02-26 13:31:12 +00001339 Handle<JSObject> inner_global(JSObject::cast(global_context()->global()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001340
1341 if (!global_proxy_template.IsEmpty()) {
1342 // Configure the global proxy object.
1343 Handle<ObjectTemplateInfo> proxy_data =
1344 v8::Utils::OpenHandle(*global_proxy_template);
1345 if (!ConfigureApiObject(global_proxy, proxy_data)) return false;
1346
1347 // Configure the inner global object.
1348 Handle<FunctionTemplateInfo> proxy_constructor(
1349 FunctionTemplateInfo::cast(proxy_data->constructor()));
1350 if (!proxy_constructor->prototype_template()->IsUndefined()) {
1351 Handle<ObjectTemplateInfo> inner_data(
1352 ObjectTemplateInfo::cast(proxy_constructor->prototype_template()));
Andrei Popescu402d9372010-02-26 13:31:12 +00001353 if (!ConfigureApiObject(inner_global, inner_data)) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 }
1355 }
1356
Andrei Popescu402d9372010-02-26 13:31:12 +00001357 SetObjectPrototype(global_proxy, inner_global);
Steve Blocka7e24c12009-10-30 11:49:00 +00001358 return true;
1359}
1360
1361
1362bool Genesis::ConfigureApiObject(Handle<JSObject> object,
1363 Handle<ObjectTemplateInfo> object_template) {
1364 ASSERT(!object_template.is_null());
1365 ASSERT(object->IsInstanceOf(
1366 FunctionTemplateInfo::cast(object_template->constructor())));
1367
1368 bool pending_exception = false;
1369 Handle<JSObject> obj =
1370 Execution::InstantiateObject(object_template, &pending_exception);
1371 if (pending_exception) {
1372 ASSERT(Top::has_pending_exception());
1373 Top::clear_pending_exception();
1374 return false;
1375 }
1376 TransferObject(obj, object);
1377 return true;
1378}
1379
1380
1381void Genesis::TransferNamedProperties(Handle<JSObject> from,
1382 Handle<JSObject> to) {
1383 if (from->HasFastProperties()) {
1384 Handle<DescriptorArray> descs =
1385 Handle<DescriptorArray>(from->map()->instance_descriptors());
1386 for (int i = 0; i < descs->number_of_descriptors(); i++) {
1387 PropertyDetails details = PropertyDetails(descs->GetDetails(i));
1388 switch (details.type()) {
1389 case FIELD: {
1390 HandleScope inner;
1391 Handle<String> key = Handle<String>(descs->GetKey(i));
1392 int index = descs->GetFieldIndex(i);
1393 Handle<Object> value = Handle<Object>(from->FastPropertyAt(index));
1394 SetProperty(to, key, value, details.attributes());
1395 break;
1396 }
1397 case CONSTANT_FUNCTION: {
1398 HandleScope inner;
1399 Handle<String> key = Handle<String>(descs->GetKey(i));
1400 Handle<JSFunction> fun =
1401 Handle<JSFunction>(descs->GetConstantFunction(i));
1402 SetProperty(to, key, fun, details.attributes());
1403 break;
1404 }
1405 case CALLBACKS: {
1406 LookupResult result;
1407 to->LocalLookup(descs->GetKey(i), &result);
1408 // If the property is already there we skip it
Andrei Popescu402d9372010-02-26 13:31:12 +00001409 if (result.IsProperty()) continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001410 HandleScope inner;
Andrei Popescu31002712010-02-23 13:46:05 +00001411 ASSERT(!to->HasFastProperties());
1412 // Add to dictionary.
Steve Blocka7e24c12009-10-30 11:49:00 +00001413 Handle<String> key = Handle<String>(descs->GetKey(i));
Andrei Popescu31002712010-02-23 13:46:05 +00001414 Handle<Object> callbacks(descs->GetCallbacksObject(i));
1415 PropertyDetails d =
1416 PropertyDetails(details.attributes(), CALLBACKS, details.index());
1417 SetNormalizedProperty(to, key, callbacks, d);
Steve Blocka7e24c12009-10-30 11:49:00 +00001418 break;
1419 }
1420 case MAP_TRANSITION:
1421 case CONSTANT_TRANSITION:
1422 case NULL_DESCRIPTOR:
1423 // Ignore non-properties.
1424 break;
1425 case NORMAL:
1426 // Do not occur since the from object has fast properties.
1427 case INTERCEPTOR:
1428 // No element in instance descriptors have interceptor type.
1429 UNREACHABLE();
1430 break;
1431 }
1432 }
1433 } else {
1434 Handle<StringDictionary> properties =
1435 Handle<StringDictionary>(from->property_dictionary());
1436 int capacity = properties->Capacity();
1437 for (int i = 0; i < capacity; i++) {
1438 Object* raw_key(properties->KeyAt(i));
1439 if (properties->IsKey(raw_key)) {
1440 ASSERT(raw_key->IsString());
1441 // If the property is already there we skip it.
1442 LookupResult result;
1443 to->LocalLookup(String::cast(raw_key), &result);
Andrei Popescu402d9372010-02-26 13:31:12 +00001444 if (result.IsProperty()) continue;
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 // Set the property.
1446 Handle<String> key = Handle<String>(String::cast(raw_key));
1447 Handle<Object> value = Handle<Object>(properties->ValueAt(i));
1448 if (value->IsJSGlobalPropertyCell()) {
1449 value = Handle<Object>(JSGlobalPropertyCell::cast(*value)->value());
1450 }
1451 PropertyDetails details = properties->DetailsAt(i);
1452 SetProperty(to, key, value, details.attributes());
1453 }
1454 }
1455 }
1456}
1457
1458
1459void Genesis::TransferIndexedProperties(Handle<JSObject> from,
1460 Handle<JSObject> to) {
1461 // Cloning the elements array is sufficient.
1462 Handle<FixedArray> from_elements =
1463 Handle<FixedArray>(FixedArray::cast(from->elements()));
1464 Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements);
1465 to->set_elements(*to_elements);
1466}
1467
1468
1469void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {
1470 HandleScope outer;
1471
1472 ASSERT(!from->IsJSArray());
1473 ASSERT(!to->IsJSArray());
1474
1475 TransferNamedProperties(from, to);
1476 TransferIndexedProperties(from, to);
1477
1478 // Transfer the prototype (new map is needed).
1479 Handle<Map> old_to_map = Handle<Map>(to->map());
1480 Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
1481 new_to_map->set_prototype(from->map()->prototype());
1482 to->set_map(*new_to_map);
1483}
1484
1485
1486void Genesis::MakeFunctionInstancePrototypeWritable() {
1487 // Make a new function map so all future functions
1488 // will have settable and enumerable prototype properties.
1489 HandleScope scope;
1490
1491 Handle<DescriptorArray> function_map_descriptors =
1492 ComputeFunctionInstanceDescriptor(false);
1493 Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
1494 fm->set_instance_descriptors(*function_map_descriptors);
1495 Top::context()->global_context()->set_function_map(*fm);
1496}
1497
1498
1499void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
1500 const char* name,
1501 Handle<Code> code) {
1502 Handle<String> key = Factory::LookupAsciiSymbol(name);
1503 Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
1504 if (value->IsJSFunction()) {
1505 Handle<JSFunction> optimized = Factory::NewFunction(key,
1506 JS_OBJECT_TYPE,
1507 JSObject::kHeaderSize,
1508 code,
1509 false);
1510 optimized->shared()->DontAdaptArguments();
1511 int len = global_context()->special_function_table()->length();
1512 Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
1513 for (int index = 0; index < len; index++) {
1514 new_array->set(index,
1515 global_context()->special_function_table()->get(index));
1516 }
1517 new_array->set(len+0, *prototype);
1518 new_array->set(len+1, *value);
1519 new_array->set(len+2, *optimized);
1520 global_context()->set_special_function_table(*new_array);
1521 }
1522}
1523
1524
1525void Genesis::BuildSpecialFunctionTable() {
1526 HandleScope scope;
1527 Handle<JSObject> global = Handle<JSObject>(global_context()->global());
Andrei Popescu402d9372010-02-26 13:31:12 +00001528 // Add special versions for some Array.prototype functions.
Steve Blocka7e24c12009-10-30 11:49:00 +00001529 Handle<JSFunction> function =
1530 Handle<JSFunction>(
1531 JSFunction::cast(global->GetProperty(Heap::Array_symbol())));
1532 Handle<JSObject> visible_prototype =
1533 Handle<JSObject>(JSObject::cast(function->prototype()));
Andrei Popescu402d9372010-02-26 13:31:12 +00001534 // Remember to put those specializations on the hidden prototype if present.
1535 Handle<JSObject> special_prototype;
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 Handle<Object> superproto(visible_prototype->GetPrototype());
1537 if (superproto->IsJSObject() &&
1538 JSObject::cast(*superproto)->map()->is_hidden_prototype()) {
Andrei Popescu402d9372010-02-26 13:31:12 +00001539 special_prototype = Handle<JSObject>::cast(superproto);
Steve Blocka7e24c12009-10-30 11:49:00 +00001540 } else {
Andrei Popescu402d9372010-02-26 13:31:12 +00001541 special_prototype = visible_prototype;
Steve Blocka7e24c12009-10-30 11:49:00 +00001542 }
Andrei Popescu402d9372010-02-26 13:31:12 +00001543 AddSpecialFunction(special_prototype, "pop",
Steve Blocka7e24c12009-10-30 11:49:00 +00001544 Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
Andrei Popescu402d9372010-02-26 13:31:12 +00001545 AddSpecialFunction(special_prototype, "push",
Steve Blocka7e24c12009-10-30 11:49:00 +00001546 Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
Andrei Popescu402d9372010-02-26 13:31:12 +00001547 AddSpecialFunction(special_prototype, "shift",
1548 Handle<Code>(Builtins::builtin(Builtins::ArrayShift)));
1549 AddSpecialFunction(special_prototype, "unshift",
1550 Handle<Code>(Builtins::builtin(Builtins::ArrayUnshift)));
1551 AddSpecialFunction(special_prototype, "slice",
1552 Handle<Code>(Builtins::builtin(Builtins::ArraySlice)));
1553 AddSpecialFunction(special_prototype, "splice",
1554 Handle<Code>(Builtins::builtin(Builtins::ArraySplice)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001555}
1556
1557
1558Genesis::Genesis(Handle<Object> global_object,
1559 v8::Handle<v8::ObjectTemplate> global_template,
1560 v8::ExtensionConfiguration* extensions) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001561 result_ = Handle<Context>::null();
Steve Blocka7e24c12009-10-30 11:49:00 +00001562 // If V8 isn't running and cannot be initialized, just return.
1563 if (!V8::IsRunning() && !V8::Initialize(NULL)) return;
1564
1565 // Before creating the roots we must save the context and restore it
1566 // on all function exits.
1567 HandleScope scope;
Andrei Popescu31002712010-02-23 13:46:05 +00001568 SaveContext saved_context;
Steve Blocka7e24c12009-10-30 11:49:00 +00001569
Andrei Popescu31002712010-02-23 13:46:05 +00001570 Handle<Context> new_context = Snapshot::NewContextFromSnapshot();
1571 if (!new_context.is_null()) {
1572 global_context_ =
1573 Handle<Context>::cast(GlobalHandles::Create(*new_context));
1574 Top::set_context(*global_context_);
1575 i::Counters::contexts_created_by_snapshot.Increment();
1576 result_ = global_context_;
1577 JSFunction* empty_function =
1578 JSFunction::cast(result_->function_map()->prototype());
1579 empty_function_ = Handle<JSFunction>(empty_function);
Andrei Popescu402d9372010-02-26 13:31:12 +00001580 Handle<GlobalObject> inner_global;
Andrei Popescu31002712010-02-23 13:46:05 +00001581 Handle<JSGlobalProxy> global_proxy =
1582 CreateNewGlobals(global_template,
1583 global_object,
Andrei Popescu402d9372010-02-26 13:31:12 +00001584 &inner_global);
1585
Andrei Popescu31002712010-02-23 13:46:05 +00001586 HookUpGlobalProxy(inner_global, global_proxy);
Andrei Popescu402d9372010-02-26 13:31:12 +00001587 HookUpInnerGlobal(inner_global);
1588
Andrei Popescu31002712010-02-23 13:46:05 +00001589 if (!ConfigureGlobalObjects(global_template)) return;
1590 } else {
1591 // We get here if there was no context snapshot.
1592 CreateRoots();
1593 Handle<JSFunction> empty_function = CreateEmptyFunction();
1594 Handle<GlobalObject> inner_global;
1595 Handle<JSGlobalProxy> global_proxy =
1596 CreateNewGlobals(global_template, global_object, &inner_global);
1597 HookUpGlobalProxy(inner_global, global_proxy);
1598 InitializeGlobal(inner_global, empty_function);
1599 if (!InstallNatives()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00001600
Andrei Popescu31002712010-02-23 13:46:05 +00001601 MakeFunctionInstancePrototypeWritable();
1602 BuildSpecialFunctionTable();
Steve Blocka7e24c12009-10-30 11:49:00 +00001603
Andrei Popescu31002712010-02-23 13:46:05 +00001604 if (!ConfigureGlobalObjects(global_template)) return;
1605 i::Counters::contexts_created_from_scratch.Increment();
1606 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001607
1608 result_ = global_context_;
1609}
1610
1611
1612// Support for thread preemption.
1613
1614// Reserve space for statics needing saving and restoring.
1615int Bootstrapper::ArchiveSpacePerThread() {
Andrei Popescu31002712010-02-23 13:46:05 +00001616 return BootstrapperActive::ArchiveSpacePerThread();
Steve Blocka7e24c12009-10-30 11:49:00 +00001617}
1618
1619
1620// Archive statics that are thread local.
1621char* Bootstrapper::ArchiveState(char* to) {
Andrei Popescu31002712010-02-23 13:46:05 +00001622 return BootstrapperActive::ArchiveState(to);
Steve Blocka7e24c12009-10-30 11:49:00 +00001623}
1624
1625
1626// Restore statics that are thread local.
1627char* Bootstrapper::RestoreState(char* from) {
Andrei Popescu31002712010-02-23 13:46:05 +00001628 return BootstrapperActive::RestoreState(from);
Steve Blocka7e24c12009-10-30 11:49:00 +00001629}
1630
1631
1632// Called when the top-level V8 mutex is destroyed.
1633void Bootstrapper::FreeThreadResources() {
Andrei Popescu31002712010-02-23 13:46:05 +00001634 ASSERT(!BootstrapperActive::IsActive());
Steve Blocka7e24c12009-10-30 11:49:00 +00001635}
1636
1637
1638// Reserve space for statics needing saving and restoring.
Andrei Popescu31002712010-02-23 13:46:05 +00001639int BootstrapperActive::ArchiveSpacePerThread() {
1640 return sizeof(nesting_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001641}
1642
1643
1644// Archive statics that are thread local.
Andrei Popescu31002712010-02-23 13:46:05 +00001645char* BootstrapperActive::ArchiveState(char* to) {
1646 *reinterpret_cast<int*>(to) = nesting_;
1647 nesting_ = 0;
1648 return to + sizeof(nesting_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001649}
1650
1651
1652// Restore statics that are thread local.
Andrei Popescu31002712010-02-23 13:46:05 +00001653char* BootstrapperActive::RestoreState(char* from) {
1654 nesting_ = *reinterpret_cast<int*>(from);
1655 return from + sizeof(nesting_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001656}
1657
1658} } // namespace v8::internal