• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "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"
39 
40 namespace v8 {
41 namespace internal {
42 
43 // A SourceCodeCache uses a FixedArray to store pairs of
44 // (AsciiString*, JSFunction*), mapping names of native code files
45 // (runtime.js, etc.) to precompiled functions. Instead of mapping
46 // names to functions it might make sense to let the JS2C tool
47 // generate an index for each native JS file.
48 class SourceCodeCache BASE_EMBEDDED {
49  public:
SourceCodeCache(Script::Type type)50   explicit SourceCodeCache(Script::Type type): type_(type), cache_(NULL) { }
51 
Initialize(bool create_heap_objects)52   void Initialize(bool create_heap_objects) {
53     cache_ = create_heap_objects ? Heap::empty_fixed_array() : NULL;
54   }
55 
Iterate(ObjectVisitor * v)56   void Iterate(ObjectVisitor* v) {
57     v->VisitPointer(bit_cast<Object**, FixedArray**>(&cache_));
58   }
59 
60 
Lookup(Vector<const char> name,Handle<JSFunction> * handle)61   bool Lookup(Vector<const char> name, Handle<JSFunction>* handle) {
62     for (int i = 0; i < cache_->length(); i+=2) {
63       SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
64       if (str->IsEqualTo(name)) {
65         *handle = Handle<JSFunction>(JSFunction::cast(cache_->get(i + 1)));
66         return true;
67       }
68     }
69     return false;
70   }
71 
72 
Add(Vector<const char> name,Handle<JSFunction> fun)73   void Add(Vector<const char> name, Handle<JSFunction> fun) {
74     ASSERT(fun->IsBoilerplate());
75     HandleScope scope;
76     int length = cache_->length();
77     Handle<FixedArray> new_array =
78         Factory::NewFixedArray(length + 2, TENURED);
79     cache_->CopyTo(0, *new_array, 0, cache_->length());
80     cache_ = *new_array;
81     Handle<String> str = Factory::NewStringFromAscii(name, TENURED);
82     cache_->set(length, *str);
83     cache_->set(length + 1, *fun);
84     Script::cast(fun->shared()->script())->set_type(Smi::FromInt(type_));
85   }
86 
87  private:
88   Script::Type type_;
89   FixedArray* cache_;
90   DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
91 };
92 
93 static SourceCodeCache natives_cache(Script::TYPE_NATIVE);
94 static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
95 
96 
NativesSourceLookup(int index)97 Handle<String> Bootstrapper::NativesSourceLookup(int index) {
98   ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
99   if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
100     Handle<String> source_code =
101       Factory::NewStringFromAscii(Natives::GetScriptSource(index));
102     Heap::natives_source_cache()->set(index, *source_code);
103   }
104   Handle<Object> cached_source(Heap::natives_source_cache()->get(index));
105   return Handle<String>::cast(cached_source);
106 }
107 
108 
NativesCacheLookup(Vector<const char> name,Handle<JSFunction> * handle)109 bool Bootstrapper::NativesCacheLookup(Vector<const char> name,
110                                       Handle<JSFunction>* handle) {
111   return natives_cache.Lookup(name, handle);
112 }
113 
114 
NativesCacheAdd(Vector<const char> name,Handle<JSFunction> fun)115 void Bootstrapper::NativesCacheAdd(Vector<const char> name,
116                                    Handle<JSFunction> fun) {
117   natives_cache.Add(name, fun);
118 }
119 
120 
Initialize(bool create_heap_objects)121 void Bootstrapper::Initialize(bool create_heap_objects) {
122   natives_cache.Initialize(create_heap_objects);
123   extensions_cache.Initialize(create_heap_objects);
124 }
125 
126 
TearDown()127 void Bootstrapper::TearDown() {
128   natives_cache.Initialize(false);  // Yes, symmetrical
129   extensions_cache.Initialize(false);
130 }
131 
132 
133 // Pending fixups are code positions that refer to builtin code
134 // objects that were not available at the time the code was generated.
135 // The pending list is processed whenever an environment has been
136 // created.
137 class PendingFixups : public AllStatic {
138  public:
139   static void Add(Code* code, MacroAssembler* masm);
140   static bool Process(Handle<JSBuiltinsObject> builtins);
141 
142   static void Iterate(ObjectVisitor* v);
143 
144  private:
145   static List<Object*> code_;
146   static List<const char*> name_;
147   static List<int> pc_;
148   static List<uint32_t> flags_;
149 
150   static void Clear();
151 };
152 
153 
154 List<Object*> PendingFixups::code_(0);
155 List<const char*> PendingFixups::name_(0);
156 List<int> PendingFixups::pc_(0);
157 List<uint32_t> PendingFixups::flags_(0);
158 
159 
Add(Code * code,MacroAssembler * masm)160 void PendingFixups::Add(Code* code, MacroAssembler* masm) {
161   // Note this code is not only called during bootstrapping.
162   List<MacroAssembler::Unresolved>* unresolved = masm->unresolved();
163   int n = unresolved->length();
164   for (int i = 0; i < n; i++) {
165     const char* name = unresolved->at(i).name;
166     code_.Add(code);
167     name_.Add(name);
168     pc_.Add(unresolved->at(i).pc);
169     flags_.Add(unresolved->at(i).flags);
170     LOG(StringEvent("unresolved", name));
171   }
172 }
173 
174 
Process(Handle<JSBuiltinsObject> builtins)175 bool PendingFixups::Process(Handle<JSBuiltinsObject> builtins) {
176   HandleScope scope;
177   // NOTE: Extra fixups may be added to the list during the iteration
178   // due to lazy compilation of functions during the processing. Do not
179   // cache the result of getting the length of the code list.
180   for (int i = 0; i < code_.length(); i++) {
181     const char* name = name_[i];
182     uint32_t flags = flags_[i];
183     Handle<String> symbol = Factory::LookupAsciiSymbol(name);
184     Object* o = builtins->GetProperty(*symbol);
185 #ifdef DEBUG
186     if (!o->IsJSFunction()) {
187       V8_Fatal(__FILE__, __LINE__, "Cannot resolve call to builtin %s", name);
188     }
189 #endif
190     Handle<JSFunction> f = Handle<JSFunction>(JSFunction::cast(o));
191     // Make sure the number of parameters match the formal parameter count.
192     int argc = Bootstrapper::FixupFlagsArgumentsCount::decode(flags);
193     USE(argc);
194     ASSERT(f->shared()->formal_parameter_count() == argc);
195     if (!f->is_compiled()) {
196       // Do lazy compilation and check for stack overflows.
197       if (!CompileLazy(f, CLEAR_EXCEPTION)) {
198         Clear();
199         return false;
200       }
201     }
202     Code* code = Code::cast(code_[i]);
203     Address pc = code->instruction_start() + pc_[i];
204     bool is_pc_relative = Bootstrapper::FixupFlagsIsPCRelative::decode(flags);
205     bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
206 
207     if (use_code_object) {
208       if (is_pc_relative) {
209         Assembler::set_target_address_at(
210             pc, reinterpret_cast<Address>(f->code()));
211       } else {
212         *reinterpret_cast<Object**>(pc) = f->code();
213       }
214     } else {
215       Assembler::set_target_address_at(pc, f->code()->instruction_start());
216     }
217 
218     LOG(StringEvent("resolved", name));
219   }
220   Clear();
221 
222   // TODO(1240818): We should probably try to avoid doing this for all
223   // the V8 builtin JS files. It should only happen after running
224   // runtime.js - just like there shouldn't be any fixups left after
225   // that.
226   for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
227     Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
228     Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
229     JSFunction* function = JSFunction::cast(builtins->GetProperty(*name));
230     builtins->set_javascript_builtin(id, function);
231   }
232 
233   return true;
234 }
235 
236 
Clear()237 void PendingFixups::Clear() {
238   code_.Clear();
239   name_.Clear();
240   pc_.Clear();
241   flags_.Clear();
242 }
243 
244 
Iterate(ObjectVisitor * v)245 void PendingFixups::Iterate(ObjectVisitor* v) {
246   if (!code_.is_empty()) {
247     v->VisitPointers(&code_[0], &code_[0] + code_.length());
248   }
249 }
250 
251 
252 class Genesis BASE_EMBEDDED {
253  public:
254   Genesis(Handle<Object> global_object,
255           v8::Handle<v8::ObjectTemplate> global_template,
256           v8::ExtensionConfiguration* extensions);
257   ~Genesis();
258 
result()259   Handle<Context> result() { return result_; }
260 
previous()261   Genesis* previous() { return previous_; }
current()262   static Genesis* current() { return current_; }
263 
264   // Support for thread preemption.
265   static int ArchiveSpacePerThread();
266   static char* ArchiveState(char* to);
267   static char* RestoreState(char* from);
268 
269  private:
270   Handle<Context> global_context_;
271 
272   // There may be more than one active genesis object: When GC is
273   // triggered during environment creation there may be weak handle
274   // processing callbacks which may create new environments.
275   Genesis* previous_;
276   static Genesis* current_;
277 
global_context()278   Handle<Context> global_context() { return global_context_; }
279 
280   void CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
281                    Handle<Object> global_object);
282   void InstallNativeFunctions();
283   bool InstallNatives();
284   bool InstallExtensions(v8::ExtensionConfiguration* extensions);
285   bool InstallExtension(const char* name);
286   bool InstallExtension(v8::RegisteredExtension* current);
287   bool InstallSpecialObjects();
288   bool ConfigureApiObject(Handle<JSObject> object,
289                           Handle<ObjectTemplateInfo> object_template);
290   bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
291 
292   // Migrates all properties from the 'from' object to the 'to'
293   // object and overrides the prototype in 'to' with the one from
294   // 'from'.
295   void TransferObject(Handle<JSObject> from, Handle<JSObject> to);
296   void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
297   void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);
298 
299   Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
300       bool make_prototype_read_only,
301       bool make_prototype_enumerable = false);
302   void MakeFunctionInstancePrototypeWritable();
303 
304   void AddSpecialFunction(Handle<JSObject> prototype,
305                           const char* name,
306                           Handle<Code> code);
307 
308   void BuildSpecialFunctionTable();
309 
310   static bool CompileBuiltin(int index);
311   static bool CompileNative(Vector<const char> name, Handle<String> source);
312   static bool CompileScriptCached(Vector<const char> name,
313                                   Handle<String> source,
314                                   SourceCodeCache* cache,
315                                   v8::Extension* extension,
316                                   bool use_runtime_context);
317 
318   Handle<Context> result_;
319 };
320 
321 Genesis* Genesis::current_ = NULL;
322 
323 
Iterate(ObjectVisitor * v)324 void Bootstrapper::Iterate(ObjectVisitor* v) {
325   natives_cache.Iterate(v);
326   extensions_cache.Iterate(v);
327   PendingFixups::Iterate(v);
328 }
329 
330 
331 // While setting up the environment, we collect code positions that
332 // need to be patched before we can run any code in the environment.
AddFixup(Code * code,MacroAssembler * masm)333 void Bootstrapper::AddFixup(Code* code, MacroAssembler* masm) {
334   PendingFixups::Add(code, masm);
335 }
336 
337 
IsActive()338 bool Bootstrapper::IsActive() {
339   return Genesis::current() != NULL;
340 }
341 
342 
CreateEnvironment(Handle<Object> global_object,v8::Handle<v8::ObjectTemplate> global_template,v8::ExtensionConfiguration * extensions)343 Handle<Context> Bootstrapper::CreateEnvironment(
344     Handle<Object> global_object,
345     v8::Handle<v8::ObjectTemplate> global_template,
346     v8::ExtensionConfiguration* extensions) {
347   Genesis genesis(global_object, global_template, extensions);
348   return genesis.result();
349 }
350 
351 
SetObjectPrototype(Handle<JSObject> object,Handle<Object> proto)352 static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
353   // object.__proto__ = proto;
354   Handle<Map> old_to_map = Handle<Map>(object->map());
355   Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
356   new_to_map->set_prototype(*proto);
357   object->set_map(*new_to_map);
358 }
359 
360 
DetachGlobal(Handle<Context> env)361 void Bootstrapper::DetachGlobal(Handle<Context> env) {
362   JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value());
363   SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
364                      Factory::null_value());
365   env->set_global_proxy(env->global());
366   env->global()->set_global_receiver(env->global());
367 }
368 
369 
~Genesis()370 Genesis::~Genesis() {
371   ASSERT(current_ == this);
372   current_ = previous_;
373 }
374 
375 
InstallFunction(Handle<JSObject> target,const char * name,InstanceType type,int instance_size,Handle<JSObject> prototype,Builtins::Name call,bool is_ecma_native)376 static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
377                                           const char* name,
378                                           InstanceType type,
379                                           int instance_size,
380                                           Handle<JSObject> prototype,
381                                           Builtins::Name call,
382                                           bool is_ecma_native) {
383   Handle<String> symbol = Factory::LookupAsciiSymbol(name);
384   Handle<Code> call_code = Handle<Code>(Builtins::builtin(call));
385   Handle<JSFunction> function =
386     Factory::NewFunctionWithPrototype(symbol,
387                                       type,
388                                       instance_size,
389                                       prototype,
390                                       call_code,
391                                       is_ecma_native);
392   SetProperty(target, symbol, function, DONT_ENUM);
393   if (is_ecma_native) {
394     function->shared()->set_instance_class_name(*symbol);
395   }
396   return function;
397 }
398 
399 
ComputeFunctionInstanceDescriptor(bool make_prototype_read_only,bool make_prototype_enumerable)400 Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
401     bool make_prototype_read_only,
402     bool make_prototype_enumerable) {
403   Handle<DescriptorArray> result = Factory::empty_descriptor_array();
404 
405   // Add prototype.
406   PropertyAttributes attributes = static_cast<PropertyAttributes>(
407       (make_prototype_enumerable ? 0 : DONT_ENUM)
408       | DONT_DELETE
409       | (make_prototype_read_only ? READ_ONLY : 0));
410   result =
411       Factory::CopyAppendProxyDescriptor(
412           result,
413           Factory::prototype_symbol(),
414           Factory::NewProxy(&Accessors::FunctionPrototype),
415           attributes);
416 
417   attributes =
418       static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
419   // Add length.
420   result =
421       Factory::CopyAppendProxyDescriptor(
422           result,
423           Factory::length_symbol(),
424           Factory::NewProxy(&Accessors::FunctionLength),
425           attributes);
426 
427   // Add name.
428   result =
429       Factory::CopyAppendProxyDescriptor(
430           result,
431           Factory::name_symbol(),
432           Factory::NewProxy(&Accessors::FunctionName),
433           attributes);
434 
435   // Add arguments.
436   result =
437       Factory::CopyAppendProxyDescriptor(
438           result,
439           Factory::arguments_symbol(),
440           Factory::NewProxy(&Accessors::FunctionArguments),
441           attributes);
442 
443   // Add caller.
444   result =
445       Factory::CopyAppendProxyDescriptor(
446           result,
447           Factory::caller_symbol(),
448           Factory::NewProxy(&Accessors::FunctionCaller),
449           attributes);
450 
451   return result;
452 }
453 
454 
CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,Handle<Object> global_object)455 void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
456                           Handle<Object> global_object) {
457   HandleScope scope;
458   // Allocate the global context FixedArray first and then patch the
459   // closure and extension object later (we need the empty function
460   // and the global object, but in order to create those, we need the
461   // global context).
462   global_context_ =
463       Handle<Context>::cast(
464           GlobalHandles::Create(*Factory::NewGlobalContext()));
465   Top::set_context(*global_context());
466 
467   // Allocate the message listeners object.
468   v8::NeanderArray listeners;
469   global_context()->set_message_listeners(*listeners.value());
470 
471   // Allocate the map for function instances.
472   Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
473   global_context()->set_function_instance_map(*fm);
474   // Please note that the prototype property for function instances must be
475   // writable.
476   Handle<DescriptorArray> function_map_descriptors =
477       ComputeFunctionInstanceDescriptor(false, true);
478   fm->set_instance_descriptors(*function_map_descriptors);
479 
480   // Allocate the function map first and then patch the prototype later
481   fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
482   global_context()->set_function_map(*fm);
483   function_map_descriptors = ComputeFunctionInstanceDescriptor(true);
484   fm->set_instance_descriptors(*function_map_descriptors);
485 
486   Handle<String> object_name = Handle<String>(Heap::Object_symbol());
487 
488   {  // --- O b j e c t ---
489     Handle<JSFunction> object_fun =
490         Factory::NewFunction(object_name, Factory::null_value());
491     Handle<Map> object_function_map =
492         Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
493     object_fun->set_initial_map(*object_function_map);
494     object_function_map->set_constructor(*object_fun);
495 
496     global_context()->set_object_function(*object_fun);
497 
498     // Allocate a new prototype for the object function.
499     Handle<JSObject> prototype = Factory::NewJSObject(Top::object_function(),
500                                                       TENURED);
501 
502     global_context()->set_initial_object_prototype(*prototype);
503     SetPrototype(object_fun, prototype);
504     object_function_map->
505       set_instance_descriptors(Heap::empty_descriptor_array());
506   }
507 
508   // Allocate the empty function as the prototype for function ECMAScript
509   // 262 15.3.4.
510   Handle<String> symbol = Factory::LookupAsciiSymbol("Empty");
511   Handle<JSFunction> empty_function =
512       Factory::NewFunction(symbol, Factory::null_value());
513 
514   {  // --- E m p t y ---
515     Handle<Code> code =
516         Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
517     empty_function->set_code(*code);
518     Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
519     Handle<Script> script = Factory::NewScript(source);
520     script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
521     empty_function->shared()->set_script(*script);
522     empty_function->shared()->set_start_position(0);
523     empty_function->shared()->set_end_position(source->length());
524     empty_function->shared()->DontAdaptArguments();
525     global_context()->function_map()->set_prototype(*empty_function);
526     global_context()->function_instance_map()->set_prototype(*empty_function);
527 
528     // Allocate the function map first and then patch the prototype later
529     Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
530     empty_fm->set_instance_descriptors(*function_map_descriptors);
531     empty_fm->set_prototype(global_context()->object_function()->prototype());
532     empty_function->set_map(*empty_fm);
533   }
534 
535   {  // --- G l o b a l ---
536     // Step 1: create a fresh inner JSGlobalObject
537     Handle<GlobalObject> object;
538     {
539       Handle<JSFunction> js_global_function;
540       Handle<ObjectTemplateInfo> js_global_template;
541       if (!global_template.IsEmpty()) {
542         // Get prototype template of the global_template
543         Handle<ObjectTemplateInfo> data =
544             v8::Utils::OpenHandle(*global_template);
545         Handle<FunctionTemplateInfo> global_constructor =
546             Handle<FunctionTemplateInfo>(
547                 FunctionTemplateInfo::cast(data->constructor()));
548         Handle<Object> proto_template(global_constructor->prototype_template());
549         if (!proto_template->IsUndefined()) {
550           js_global_template =
551               Handle<ObjectTemplateInfo>::cast(proto_template);
552         }
553       }
554 
555       if (js_global_template.is_null()) {
556         Handle<String> name = Handle<String>(Heap::empty_symbol());
557         Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
558         js_global_function =
559             Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
560                                  JSGlobalObject::kSize, code, true);
561         // Change the constructor property of the prototype of the
562         // hidden global function to refer to the Object function.
563         Handle<JSObject> prototype =
564             Handle<JSObject>(
565                 JSObject::cast(js_global_function->instance_prototype()));
566         SetProperty(prototype, Factory::constructor_symbol(),
567                     Top::object_function(), NONE);
568       } else {
569         Handle<FunctionTemplateInfo> js_global_constructor(
570             FunctionTemplateInfo::cast(js_global_template->constructor()));
571         js_global_function =
572             Factory::CreateApiFunction(js_global_constructor,
573                                        Factory::InnerGlobalObject);
574       }
575 
576       js_global_function->initial_map()->set_is_hidden_prototype();
577       object = Factory::NewGlobalObject(js_global_function);
578     }
579 
580     // Set the global context for the global object.
581     object->set_global_context(*global_context());
582 
583     // Step 2: create or re-initialize the global proxy object.
584     Handle<JSGlobalProxy> global_proxy;
585     {
586       Handle<JSFunction> global_proxy_function;
587       if (global_template.IsEmpty()) {
588         Handle<String> name = Handle<String>(Heap::empty_symbol());
589         Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
590         global_proxy_function =
591             Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
592                                  JSGlobalProxy::kSize, code, true);
593       } else {
594         Handle<ObjectTemplateInfo> data =
595             v8::Utils::OpenHandle(*global_template);
596         Handle<FunctionTemplateInfo> global_constructor(
597                 FunctionTemplateInfo::cast(data->constructor()));
598         global_proxy_function =
599             Factory::CreateApiFunction(global_constructor,
600                                        Factory::OuterGlobalObject);
601       }
602 
603       Handle<String> global_name = Factory::LookupAsciiSymbol("global");
604       global_proxy_function->shared()->set_instance_class_name(*global_name);
605       global_proxy_function->initial_map()->set_is_access_check_needed(true);
606 
607       // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
608 
609       if (global_object.location() != NULL) {
610         ASSERT(global_object->IsJSGlobalProxy());
611         global_proxy =
612             ReinitializeJSGlobalProxy(
613                 global_proxy_function,
614                 Handle<JSGlobalProxy>::cast(global_object));
615       } else {
616         global_proxy = Handle<JSGlobalProxy>::cast(
617             Factory::NewJSObject(global_proxy_function, TENURED));
618       }
619 
620       // Security setup: Set the security token of the global object to
621       // its the inner global. This makes the security check between two
622       // different contexts fail by default even in case of global
623       // object reinitialization.
624       object->set_global_receiver(*global_proxy);
625       global_proxy->set_context(*global_context());
626     }
627 
628     {  // --- G l o b a l   C o n t e x t ---
629       // use the empty function as closure (no scope info)
630       global_context()->set_closure(*empty_function);
631       global_context()->set_fcontext(*global_context());
632       global_context()->set_previous(NULL);
633 
634       // set extension and global object
635       global_context()->set_extension(*object);
636       global_context()->set_global(*object);
637       global_context()->set_global_proxy(*global_proxy);
638       // use inner global object as security token by default
639       global_context()->set_security_token(*object);
640     }
641 
642     Handle<JSObject> global = Handle<JSObject>(global_context()->global());
643     SetProperty(global, object_name, Top::object_function(), DONT_ENUM);
644   }
645 
646   Handle<JSObject> global = Handle<JSObject>(global_context()->global());
647 
648   // Install global Function object
649   InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize,
650                   empty_function, Builtins::Illegal, true);  // ECMA native.
651 
652   {  // --- A r r a y ---
653     Handle<JSFunction> array_function =
654         InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize,
655                         Top::initial_object_prototype(), Builtins::ArrayCode,
656                         true);
657     array_function->shared()->DontAdaptArguments();
658 
659     // This seems a bit hackish, but we need to make sure Array.length
660     // is 1.
661     array_function->shared()->set_length(1);
662     Handle<DescriptorArray> array_descriptors =
663         Factory::CopyAppendProxyDescriptor(
664             Factory::empty_descriptor_array(),
665             Factory::length_symbol(),
666             Factory::NewProxy(&Accessors::ArrayLength),
667             static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE));
668 
669     // Cache the fast JavaScript array map
670     global_context()->set_js_array_map(array_function->initial_map());
671     global_context()->js_array_map()->set_instance_descriptors(
672         *array_descriptors);
673     // array_function is used internally. JS code creating array object should
674     // search for the 'Array' property on the global object and use that one
675     // as the constructor. 'Array' property on a global object can be
676     // overwritten by JS code.
677     global_context()->set_array_function(*array_function);
678   }
679 
680   {  // --- N u m b e r ---
681     Handle<JSFunction> number_fun =
682         InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize,
683                         Top::initial_object_prototype(), Builtins::Illegal,
684                         true);
685     global_context()->set_number_function(*number_fun);
686   }
687 
688   {  // --- B o o l e a n ---
689     Handle<JSFunction> boolean_fun =
690         InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize,
691                         Top::initial_object_prototype(), Builtins::Illegal,
692                         true);
693     global_context()->set_boolean_function(*boolean_fun);
694   }
695 
696   {  // --- S t r i n g ---
697     Handle<JSFunction> string_fun =
698         InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize,
699                         Top::initial_object_prototype(), Builtins::Illegal,
700                         true);
701     global_context()->set_string_function(*string_fun);
702     // Add 'length' property to strings.
703     Handle<DescriptorArray> string_descriptors =
704         Factory::CopyAppendProxyDescriptor(
705             Factory::empty_descriptor_array(),
706             Factory::length_symbol(),
707             Factory::NewProxy(&Accessors::StringLength),
708             static_cast<PropertyAttributes>(DONT_ENUM |
709                                             DONT_DELETE |
710                                             READ_ONLY));
711 
712     Handle<Map> string_map =
713         Handle<Map>(global_context()->string_function()->initial_map());
714     string_map->set_instance_descriptors(*string_descriptors);
715   }
716 
717   {  // --- D a t e ---
718     // Builtin functions for Date.prototype.
719     Handle<JSFunction> date_fun =
720         InstallFunction(global, "Date", JS_VALUE_TYPE, JSValue::kSize,
721                         Top::initial_object_prototype(), Builtins::Illegal,
722                         true);
723 
724     global_context()->set_date_function(*date_fun);
725   }
726 
727 
728   {  // -- R e g E x p
729     // Builtin functions for RegExp.prototype.
730     Handle<JSFunction> regexp_fun =
731         InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
732                         Top::initial_object_prototype(), Builtins::Illegal,
733                         true);
734 
735     global_context()->set_regexp_function(*regexp_fun);
736   }
737 
738   {  // -- J S O N
739     Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON"));
740     Handle<JSFunction> cons = Factory::NewFunction(
741         name,
742         Factory::the_hole_value());
743     cons->SetInstancePrototype(global_context()->initial_object_prototype());
744     cons->SetInstanceClassName(*name);
745     Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED);
746     ASSERT(json_object->IsJSObject());
747     SetProperty(global, name, json_object, DONT_ENUM);
748     global_context()->set_json_object(*json_object);
749   }
750 
751   {  // --- arguments_boilerplate_
752     // Make sure we can recognize argument objects at runtime.
753     // This is done by introducing an anonymous function with
754     // class_name equals 'Arguments'.
755     Handle<String> symbol = Factory::LookupAsciiSymbol("Arguments");
756     Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
757     Handle<JSObject> prototype =
758         Handle<JSObject>(
759             JSObject::cast(global_context()->object_function()->prototype()));
760 
761     Handle<JSFunction> function =
762         Factory::NewFunctionWithPrototype(symbol,
763                                           JS_OBJECT_TYPE,
764                                           JSObject::kHeaderSize,
765                                           prototype,
766                                           code,
767                                           false);
768     ASSERT(!function->has_initial_map());
769     function->shared()->set_instance_class_name(*symbol);
770     function->shared()->set_expected_nof_properties(2);
771     Handle<JSObject> result = Factory::NewJSObject(function);
772 
773     global_context()->set_arguments_boilerplate(*result);
774     // Note: callee must be added as the first property and
775     //       length must be added as the second property.
776     SetProperty(result, Factory::callee_symbol(),
777                 Factory::undefined_value(),
778                 DONT_ENUM);
779     SetProperty(result, Factory::length_symbol(),
780                 Factory::undefined_value(),
781                 DONT_ENUM);
782 
783 #ifdef DEBUG
784     LookupResult lookup;
785     result->LocalLookup(Heap::callee_symbol(), &lookup);
786     ASSERT(lookup.IsValid() && (lookup.type() == FIELD));
787     ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index);
788 
789     result->LocalLookup(Heap::length_symbol(), &lookup);
790     ASSERT(lookup.IsValid() && (lookup.type() == FIELD));
791     ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index);
792 
793     ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index);
794     ASSERT(result->map()->inobject_properties() > Heap::arguments_length_index);
795 
796     // Check the state of the object.
797     ASSERT(result->HasFastProperties());
798     ASSERT(result->HasFastElements());
799 #endif
800   }
801 
802   {  // --- context extension
803     // Create a function for the context extension objects.
804     Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
805     Handle<JSFunction> context_extension_fun =
806         Factory::NewFunction(Factory::empty_symbol(),
807                              JS_CONTEXT_EXTENSION_OBJECT_TYPE,
808                              JSObject::kHeaderSize,
809                              code,
810                              true);
811 
812     Handle<String> name = Factory::LookupAsciiSymbol("context_extension");
813     context_extension_fun->shared()->set_instance_class_name(*name);
814     global_context()->set_context_extension_function(*context_extension_fun);
815   }
816 
817 
818   {
819     // Setup the call-as-function delegate.
820     Handle<Code> code =
821         Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction));
822     Handle<JSFunction> delegate =
823         Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
824                              JSObject::kHeaderSize, code, true);
825     global_context()->set_call_as_function_delegate(*delegate);
826     delegate->shared()->DontAdaptArguments();
827   }
828 
829   {
830     // Setup the call-as-constructor delegate.
831     Handle<Code> code =
832         Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsConstructor));
833     Handle<JSFunction> delegate =
834         Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
835                              JSObject::kHeaderSize, code, true);
836     global_context()->set_call_as_constructor_delegate(*delegate);
837     delegate->shared()->DontAdaptArguments();
838   }
839 
840   global_context()->set_special_function_table(Heap::empty_fixed_array());
841 
842   // Initialize the out of memory slot.
843   global_context()->set_out_of_memory(Heap::false_value());
844 
845   // Initialize the data slot.
846   global_context()->set_data(Heap::undefined_value());
847 }
848 
849 
CompileBuiltin(int index)850 bool Genesis::CompileBuiltin(int index) {
851   Vector<const char> name = Natives::GetScriptName(index);
852   Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
853   return CompileNative(name, source_code);
854 }
855 
856 
CompileNative(Vector<const char> name,Handle<String> source)857 bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
858   HandleScope scope;
859 #ifdef ENABLE_DEBUGGER_SUPPORT
860   Debugger::set_compiling_natives(true);
861 #endif
862   bool result =
863       CompileScriptCached(name, source, &natives_cache, NULL, true);
864   ASSERT(Top::has_pending_exception() != result);
865   if (!result) Top::clear_pending_exception();
866 #ifdef ENABLE_DEBUGGER_SUPPORT
867   Debugger::set_compiling_natives(false);
868 #endif
869   return result;
870 }
871 
872 
CompileScriptCached(Vector<const char> name,Handle<String> source,SourceCodeCache * cache,v8::Extension * extension,bool use_runtime_context)873 bool Genesis::CompileScriptCached(Vector<const char> name,
874                                   Handle<String> source,
875                                   SourceCodeCache* cache,
876                                   v8::Extension* extension,
877                                   bool use_runtime_context) {
878   HandleScope scope;
879   Handle<JSFunction> boilerplate;
880 
881   // If we can't find the function in the cache, we compile a new
882   // function and insert it into the cache.
883   if (!cache->Lookup(name, &boilerplate)) {
884     ASSERT(source->IsAsciiRepresentation());
885     Handle<String> script_name = Factory::NewStringFromUtf8(name);
886     boilerplate =
887         Compiler::Compile(source, script_name, 0, 0, extension, NULL);
888     if (boilerplate.is_null()) return false;
889     cache->Add(name, boilerplate);
890   }
891 
892   // Setup the function context. Conceptually, we should clone the
893   // function before overwriting the context but since we're in a
894   // single-threaded environment it is not strictly necessary.
895   ASSERT(Top::context()->IsGlobalContext());
896   Handle<Context> context =
897       Handle<Context>(use_runtime_context
898                       ? Top::context()->runtime_context()
899                       : Top::context());
900   Handle<JSFunction> fun =
901       Factory::NewFunctionFromBoilerplate(boilerplate, context);
902 
903   // Call function using the either the runtime object or the global
904   // object as the receiver. Provide no parameters.
905   Handle<Object> receiver =
906       Handle<Object>(use_runtime_context
907                      ? Top::context()->builtins()
908                      : Top::context()->global());
909   bool has_pending_exception;
910   Handle<Object> result =
911       Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
912   if (has_pending_exception) return false;
913   return PendingFixups::Process(
914       Handle<JSBuiltinsObject>(Top::context()->builtins()));
915 }
916 
917 
918 #define INSTALL_NATIVE(Type, name, var)                                  \
919   Handle<String> var##_name = Factory::LookupAsciiSymbol(name);          \
920   global_context()->set_##var(Type::cast(global_context()->              \
921                                            builtins()->                  \
922                                              GetProperty(*var##_name)));
923 
InstallNativeFunctions()924 void Genesis::InstallNativeFunctions() {
925   HandleScope scope;
926   INSTALL_NATIVE(JSFunction, "CreateDate", create_date_fun);
927   INSTALL_NATIVE(JSFunction, "ToNumber", to_number_fun);
928   INSTALL_NATIVE(JSFunction, "ToString", to_string_fun);
929   INSTALL_NATIVE(JSFunction, "ToDetailString", to_detail_string_fun);
930   INSTALL_NATIVE(JSFunction, "ToObject", to_object_fun);
931   INSTALL_NATIVE(JSFunction, "ToInteger", to_integer_fun);
932   INSTALL_NATIVE(JSFunction, "ToUint32", to_uint32_fun);
933   INSTALL_NATIVE(JSFunction, "ToInt32", to_int32_fun);
934   INSTALL_NATIVE(JSFunction, "ToBoolean", to_boolean_fun);
935   INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
936   INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance",
937                  configure_instance_fun);
938   INSTALL_NATIVE(JSFunction, "MakeMessage", make_message_fun);
939   INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun);
940   INSTALL_NATIVE(JSObject, "functionCache", function_cache);
941 }
942 
943 #undef INSTALL_NATIVE
944 
945 
InstallNatives()946 bool Genesis::InstallNatives() {
947   HandleScope scope;
948 
949   // Create a function for the builtins object. Allocate space for the
950   // JavaScript builtins, a reference to the builtins object
951   // (itself) and a reference to the global_context directly in the object.
952   Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
953   Handle<JSFunction> builtins_fun =
954       Factory::NewFunction(Factory::empty_symbol(), JS_BUILTINS_OBJECT_TYPE,
955                            JSBuiltinsObject::kSize, code, true);
956 
957   Handle<String> name = Factory::LookupAsciiSymbol("builtins");
958   builtins_fun->shared()->set_instance_class_name(*name);
959 
960   // Allocate the builtins object.
961   Handle<JSBuiltinsObject> builtins =
962       Handle<JSBuiltinsObject>::cast(Factory::NewGlobalObject(builtins_fun));
963   builtins->set_builtins(*builtins);
964   builtins->set_global_context(*global_context());
965   builtins->set_global_receiver(*builtins);
966 
967   // Setup the 'global' properties of the builtins object. The
968   // 'global' property that refers to the global object is the only
969   // way to get from code running in the builtins context to the
970   // global object.
971   static const PropertyAttributes attributes =
972       static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
973   SetProperty(builtins, Factory::LookupAsciiSymbol("global"),
974               Handle<Object>(global_context()->global()), attributes);
975 
976   // Setup the reference from the global object to the builtins object.
977   JSGlobalObject::cast(global_context()->global())->set_builtins(*builtins);
978 
979   // Create a bridge function that has context in the global context.
980   Handle<JSFunction> bridge =
981       Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value());
982   ASSERT(bridge->context() == *Top::global_context());
983 
984   // Allocate the builtins context.
985   Handle<Context> context =
986     Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
987   context->set_global(*builtins);  // override builtins global object
988 
989   global_context()->set_runtime_context(*context);
990 
991   {  // -- S c r i p t
992     // Builtin functions for Script.
993     Handle<JSFunction> script_fun =
994         InstallFunction(builtins, "Script", JS_VALUE_TYPE, JSValue::kSize,
995                         Top::initial_object_prototype(), Builtins::Illegal,
996                         false);
997     Handle<JSObject> prototype =
998         Factory::NewJSObject(Top::object_function(), TENURED);
999     SetPrototype(script_fun, prototype);
1000     global_context()->set_script_function(*script_fun);
1001 
1002     // Add 'source' and 'data' property to scripts.
1003     PropertyAttributes common_attributes =
1004         static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
1005     Handle<Proxy> proxy_source = Factory::NewProxy(&Accessors::ScriptSource);
1006     Handle<DescriptorArray> script_descriptors =
1007         Factory::CopyAppendProxyDescriptor(
1008             Factory::empty_descriptor_array(),
1009             Factory::LookupAsciiSymbol("source"),
1010             proxy_source,
1011             common_attributes);
1012     Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName);
1013     script_descriptors =
1014         Factory::CopyAppendProxyDescriptor(
1015             script_descriptors,
1016             Factory::LookupAsciiSymbol("name"),
1017             proxy_name,
1018             common_attributes);
1019     Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId);
1020     script_descriptors =
1021         Factory::CopyAppendProxyDescriptor(
1022             script_descriptors,
1023             Factory::LookupAsciiSymbol("id"),
1024             proxy_id,
1025             common_attributes);
1026     Handle<Proxy> proxy_line_offset =
1027         Factory::NewProxy(&Accessors::ScriptLineOffset);
1028     script_descriptors =
1029         Factory::CopyAppendProxyDescriptor(
1030             script_descriptors,
1031             Factory::LookupAsciiSymbol("line_offset"),
1032             proxy_line_offset,
1033             common_attributes);
1034     Handle<Proxy> proxy_column_offset =
1035         Factory::NewProxy(&Accessors::ScriptColumnOffset);
1036     script_descriptors =
1037         Factory::CopyAppendProxyDescriptor(
1038             script_descriptors,
1039             Factory::LookupAsciiSymbol("column_offset"),
1040             proxy_column_offset,
1041             common_attributes);
1042     Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData);
1043     script_descriptors =
1044         Factory::CopyAppendProxyDescriptor(
1045             script_descriptors,
1046             Factory::LookupAsciiSymbol("data"),
1047             proxy_data,
1048             common_attributes);
1049     Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
1050     script_descriptors =
1051         Factory::CopyAppendProxyDescriptor(
1052             script_descriptors,
1053             Factory::LookupAsciiSymbol("type"),
1054             proxy_type,
1055             common_attributes);
1056     Handle<Proxy> proxy_compilation_type =
1057         Factory::NewProxy(&Accessors::ScriptCompilationType);
1058     script_descriptors =
1059         Factory::CopyAppendProxyDescriptor(
1060             script_descriptors,
1061             Factory::LookupAsciiSymbol("compilation_type"),
1062             proxy_compilation_type,
1063             common_attributes);
1064     Handle<Proxy> proxy_line_ends =
1065         Factory::NewProxy(&Accessors::ScriptLineEnds);
1066     script_descriptors =
1067         Factory::CopyAppendProxyDescriptor(
1068             script_descriptors,
1069             Factory::LookupAsciiSymbol("line_ends"),
1070             proxy_line_ends,
1071             common_attributes);
1072     Handle<Proxy> proxy_context_data =
1073         Factory::NewProxy(&Accessors::ScriptContextData);
1074     script_descriptors =
1075         Factory::CopyAppendProxyDescriptor(
1076             script_descriptors,
1077             Factory::LookupAsciiSymbol("context_data"),
1078             proxy_context_data,
1079             common_attributes);
1080     Handle<Proxy> proxy_eval_from_function =
1081         Factory::NewProxy(&Accessors::ScriptEvalFromFunction);
1082     script_descriptors =
1083         Factory::CopyAppendProxyDescriptor(
1084             script_descriptors,
1085             Factory::LookupAsciiSymbol("eval_from_function"),
1086             proxy_eval_from_function,
1087             common_attributes);
1088     Handle<Proxy> proxy_eval_from_position =
1089         Factory::NewProxy(&Accessors::ScriptEvalFromPosition);
1090     script_descriptors =
1091         Factory::CopyAppendProxyDescriptor(
1092             script_descriptors,
1093             Factory::LookupAsciiSymbol("eval_from_position"),
1094             proxy_eval_from_position,
1095             common_attributes);
1096 
1097     Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
1098     script_map->set_instance_descriptors(*script_descriptors);
1099 
1100     // Allocate the empty script.
1101     Handle<Script> script = Factory::NewScript(Factory::empty_string());
1102     script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
1103     global_context()->set_empty_script(*script);
1104   }
1105 
1106   if (FLAG_natives_file == NULL) {
1107     // Without natives file, install default natives.
1108     for (int i = Natives::GetDelayCount();
1109          i < Natives::GetBuiltinsCount();
1110          i++) {
1111       if (!CompileBuiltin(i)) return false;
1112     }
1113 
1114     // Setup natives with lazy loading.
1115     SetupLazy(Handle<JSFunction>(global_context()->date_function()),
1116               Natives::GetIndex("date"),
1117               Top::global_context(),
1118               Handle<Context>(Top::context()->runtime_context()));
1119     SetupLazy(Handle<JSFunction>(global_context()->regexp_function()),
1120               Natives::GetIndex("regexp"),
1121               Top::global_context(),
1122               Handle<Context>(Top::context()->runtime_context()));
1123     SetupLazy(Handle<JSObject>(global_context()->json_object()),
1124               Natives::GetIndex("json"),
1125               Top::global_context(),
1126               Handle<Context>(Top::context()->runtime_context()));
1127 
1128   } else if (strlen(FLAG_natives_file) != 0) {
1129     // Otherwise install natives from natives file if file exists and
1130     // compiles.
1131     bool exists;
1132     Vector<const char> source = ReadFile(FLAG_natives_file, &exists);
1133     Handle<String> source_string = Factory::NewStringFromAscii(source);
1134     if (source.is_empty()) return false;
1135     bool result = CompileNative(CStrVector(FLAG_natives_file), source_string);
1136     if (!result) return false;
1137 
1138   } else {
1139     // Empty natives file name - do not install any natives.
1140     PrintF("Warning: Running without installed natives!\n");
1141     return true;
1142   }
1143 
1144   InstallNativeFunctions();
1145 
1146   // Install Function.prototype.call and apply.
1147   { Handle<String> key = Factory::function_class_symbol();
1148     Handle<JSFunction> function =
1149         Handle<JSFunction>::cast(GetProperty(Top::global(), key));
1150     Handle<JSObject> proto =
1151         Handle<JSObject>(JSObject::cast(function->instance_prototype()));
1152 
1153     // Install the call and the apply functions.
1154     Handle<JSFunction> call =
1155         InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
1156                         Factory::NewJSObject(Top::object_function(), TENURED),
1157                         Builtins::FunctionCall,
1158                         false);
1159     Handle<JSFunction> apply =
1160         InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
1161                         Factory::NewJSObject(Top::object_function(), TENURED),
1162                         Builtins::FunctionApply,
1163                         false);
1164 
1165     // Make sure that Function.prototype.call appears to be compiled.
1166     // The code will never be called, but inline caching for call will
1167     // only work if it appears to be compiled.
1168     call->shared()->DontAdaptArguments();
1169     ASSERT(call->is_compiled());
1170 
1171     // Set the expected parameters for apply to 2; required by builtin.
1172     apply->shared()->set_formal_parameter_count(2);
1173 
1174     // Set the lengths for the functions to satisfy ECMA-262.
1175     call->shared()->set_length(1);
1176     apply->shared()->set_length(2);
1177   }
1178 
1179 #ifdef DEBUG
1180   builtins->Verify();
1181 #endif
1182   return true;
1183 }
1184 
1185 
InstallSpecialObjects()1186 bool Genesis::InstallSpecialObjects() {
1187   HandleScope scope;
1188   Handle<JSGlobalObject> js_global(
1189       JSGlobalObject::cast(global_context()->global()));
1190   // Expose the natives in global if a name for it is specified.
1191   if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
1192     Handle<String> natives_string =
1193         Factory::LookupAsciiSymbol(FLAG_expose_natives_as);
1194     SetProperty(js_global, natives_string,
1195                 Handle<JSObject>(js_global->builtins()), DONT_ENUM);
1196   }
1197 
1198   Handle<Object> Error = GetProperty(js_global, "Error");
1199   if (Error->IsJSObject()) {
1200     Handle<String> name = Factory::LookupAsciiSymbol("stackTraceLimit");
1201     SetProperty(Handle<JSObject>::cast(Error),
1202                 name,
1203                 Handle<Smi>(Smi::FromInt(FLAG_stack_trace_limit)),
1204                 NONE);
1205   }
1206 
1207 #ifdef ENABLE_DEBUGGER_SUPPORT
1208   // Expose the debug global object in global if a name for it is specified.
1209   if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
1210     // If loading fails we just bail out without installing the
1211     // debugger but without tanking the whole context.
1212     if (!Debug::Load())
1213       return true;
1214     // Set the security token for the debugger context to the same as
1215     // the shell global context to allow calling between these (otherwise
1216     // exposing debug global object doesn't make much sense).
1217     Debug::debug_context()->set_security_token(
1218         global_context()->security_token());
1219 
1220     Handle<String> debug_string =
1221         Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
1222     SetProperty(js_global, debug_string,
1223         Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
1224   }
1225 #endif
1226 
1227   return true;
1228 }
1229 
1230 
InstallExtensions(v8::ExtensionConfiguration * extensions)1231 bool Genesis::InstallExtensions(v8::ExtensionConfiguration* extensions) {
1232   // Clear coloring of extension list
1233   v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
1234   while (current != NULL) {
1235     current->set_state(v8::UNVISITED);
1236     current = current->next();
1237   }
1238   // Install auto extensions
1239   current = v8::RegisteredExtension::first_extension();
1240   while (current != NULL) {
1241     if (current->extension()->auto_enable())
1242       InstallExtension(current);
1243     current = current->next();
1244   }
1245 
1246   if (FLAG_expose_gc) InstallExtension("v8/gc");
1247 
1248   if (extensions == NULL) return true;
1249   // Install required extensions
1250   int count = v8::ImplementationUtilities::GetNameCount(extensions);
1251   const char** names = v8::ImplementationUtilities::GetNames(extensions);
1252   for (int i = 0; i < count; i++) {
1253     if (!InstallExtension(names[i]))
1254       return false;
1255   }
1256 
1257   return true;
1258 }
1259 
1260 
1261 // Installs a named extension.  This methods is unoptimized and does
1262 // not scale well if we want to support a large number of extensions.
InstallExtension(const char * name)1263 bool Genesis::InstallExtension(const char* name) {
1264   v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
1265   // Loop until we find the relevant extension
1266   while (current != NULL) {
1267     if (strcmp(name, current->extension()->name()) == 0) break;
1268     current = current->next();
1269   }
1270   // Didn't find the extension; fail.
1271   if (current == NULL) {
1272     v8::Utils::ReportApiFailure(
1273         "v8::Context::New()", "Cannot find required extension");
1274     return false;
1275   }
1276   return InstallExtension(current);
1277 }
1278 
1279 
InstallExtension(v8::RegisteredExtension * current)1280 bool Genesis::InstallExtension(v8::RegisteredExtension* current) {
1281   HandleScope scope;
1282 
1283   if (current->state() == v8::INSTALLED) return true;
1284   // The current node has already been visited so there must be a
1285   // cycle in the dependency graph; fail.
1286   if (current->state() == v8::VISITED) {
1287     v8::Utils::ReportApiFailure(
1288         "v8::Context::New()", "Circular extension dependency");
1289     return false;
1290   }
1291   ASSERT(current->state() == v8::UNVISITED);
1292   current->set_state(v8::VISITED);
1293   v8::Extension* extension = current->extension();
1294   // Install the extension's dependencies
1295   for (int i = 0; i < extension->dependency_count(); i++) {
1296     if (!InstallExtension(extension->dependencies()[i])) return false;
1297   }
1298   Vector<const char> source = CStrVector(extension->source());
1299   Handle<String> source_code = Factory::NewStringFromAscii(source);
1300   bool result = CompileScriptCached(CStrVector(extension->name()),
1301                                     source_code,
1302                                     &extensions_cache, extension,
1303                                     false);
1304   ASSERT(Top::has_pending_exception() != result);
1305   if (!result) {
1306     Top::clear_pending_exception();
1307     v8::Utils::ReportApiFailure(
1308         "v8::Context::New()", "Error installing extension");
1309   }
1310   current->set_state(v8::INSTALLED);
1311   return result;
1312 }
1313 
1314 
ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_proxy_template)1315 bool Genesis::ConfigureGlobalObjects(
1316     v8::Handle<v8::ObjectTemplate> global_proxy_template) {
1317   Handle<JSObject> global_proxy(
1318       JSObject::cast(global_context()->global_proxy()));
1319   Handle<JSObject> js_global(JSObject::cast(global_context()->global()));
1320 
1321   if (!global_proxy_template.IsEmpty()) {
1322     // Configure the global proxy object.
1323     Handle<ObjectTemplateInfo> proxy_data =
1324         v8::Utils::OpenHandle(*global_proxy_template);
1325     if (!ConfigureApiObject(global_proxy, proxy_data)) return false;
1326 
1327     // Configure the inner global object.
1328     Handle<FunctionTemplateInfo> proxy_constructor(
1329         FunctionTemplateInfo::cast(proxy_data->constructor()));
1330     if (!proxy_constructor->prototype_template()->IsUndefined()) {
1331       Handle<ObjectTemplateInfo> inner_data(
1332           ObjectTemplateInfo::cast(proxy_constructor->prototype_template()));
1333       if (!ConfigureApiObject(js_global, inner_data)) return false;
1334     }
1335   }
1336 
1337   SetObjectPrototype(global_proxy, js_global);
1338   return true;
1339 }
1340 
1341 
ConfigureApiObject(Handle<JSObject> object,Handle<ObjectTemplateInfo> object_template)1342 bool Genesis::ConfigureApiObject(Handle<JSObject> object,
1343     Handle<ObjectTemplateInfo> object_template) {
1344   ASSERT(!object_template.is_null());
1345   ASSERT(object->IsInstanceOf(
1346       FunctionTemplateInfo::cast(object_template->constructor())));
1347 
1348   bool pending_exception = false;
1349   Handle<JSObject> obj =
1350       Execution::InstantiateObject(object_template, &pending_exception);
1351   if (pending_exception) {
1352     ASSERT(Top::has_pending_exception());
1353     Top::clear_pending_exception();
1354     return false;
1355   }
1356   TransferObject(obj, object);
1357   return true;
1358 }
1359 
1360 
TransferNamedProperties(Handle<JSObject> from,Handle<JSObject> to)1361 void Genesis::TransferNamedProperties(Handle<JSObject> from,
1362                                       Handle<JSObject> to) {
1363   if (from->HasFastProperties()) {
1364     Handle<DescriptorArray> descs =
1365         Handle<DescriptorArray>(from->map()->instance_descriptors());
1366     for (int i = 0; i < descs->number_of_descriptors(); i++) {
1367       PropertyDetails details = PropertyDetails(descs->GetDetails(i));
1368       switch (details.type()) {
1369         case FIELD: {
1370           HandleScope inner;
1371           Handle<String> key = Handle<String>(descs->GetKey(i));
1372           int index = descs->GetFieldIndex(i);
1373           Handle<Object> value = Handle<Object>(from->FastPropertyAt(index));
1374           SetProperty(to, key, value, details.attributes());
1375           break;
1376         }
1377         case CONSTANT_FUNCTION: {
1378           HandleScope inner;
1379           Handle<String> key = Handle<String>(descs->GetKey(i));
1380           Handle<JSFunction> fun =
1381               Handle<JSFunction>(descs->GetConstantFunction(i));
1382           SetProperty(to, key, fun, details.attributes());
1383           break;
1384         }
1385         case CALLBACKS: {
1386           LookupResult result;
1387           to->LocalLookup(descs->GetKey(i), &result);
1388           // If the property is already there we skip it
1389           if (result.IsValid()) continue;
1390           HandleScope inner;
1391           Handle<DescriptorArray> inst_descs =
1392               Handle<DescriptorArray>(to->map()->instance_descriptors());
1393           Handle<String> key = Handle<String>(descs->GetKey(i));
1394           Handle<Object> entry = Handle<Object>(descs->GetCallbacksObject(i));
1395           inst_descs = Factory::CopyAppendProxyDescriptor(inst_descs,
1396                                                           key,
1397                                                           entry,
1398                                                           details.attributes());
1399           to->map()->set_instance_descriptors(*inst_descs);
1400           break;
1401         }
1402         case MAP_TRANSITION:
1403         case CONSTANT_TRANSITION:
1404         case NULL_DESCRIPTOR:
1405           // Ignore non-properties.
1406           break;
1407         case NORMAL:
1408           // Do not occur since the from object has fast properties.
1409         case INTERCEPTOR:
1410           // No element in instance descriptors have interceptor type.
1411           UNREACHABLE();
1412           break;
1413       }
1414     }
1415   } else {
1416     Handle<StringDictionary> properties =
1417         Handle<StringDictionary>(from->property_dictionary());
1418     int capacity = properties->Capacity();
1419     for (int i = 0; i < capacity; i++) {
1420       Object* raw_key(properties->KeyAt(i));
1421       if (properties->IsKey(raw_key)) {
1422         ASSERT(raw_key->IsString());
1423         // If the property is already there we skip it.
1424         LookupResult result;
1425         to->LocalLookup(String::cast(raw_key), &result);
1426         if (result.IsValid()) continue;
1427         // Set the property.
1428         Handle<String> key = Handle<String>(String::cast(raw_key));
1429         Handle<Object> value = Handle<Object>(properties->ValueAt(i));
1430         if (value->IsJSGlobalPropertyCell()) {
1431           value = Handle<Object>(JSGlobalPropertyCell::cast(*value)->value());
1432         }
1433         PropertyDetails details = properties->DetailsAt(i);
1434         SetProperty(to, key, value, details.attributes());
1435       }
1436     }
1437   }
1438 }
1439 
1440 
TransferIndexedProperties(Handle<JSObject> from,Handle<JSObject> to)1441 void Genesis::TransferIndexedProperties(Handle<JSObject> from,
1442                                         Handle<JSObject> to) {
1443   // Cloning the elements array is sufficient.
1444   Handle<FixedArray> from_elements =
1445       Handle<FixedArray>(FixedArray::cast(from->elements()));
1446   Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements);
1447   to->set_elements(*to_elements);
1448 }
1449 
1450 
TransferObject(Handle<JSObject> from,Handle<JSObject> to)1451 void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {
1452   HandleScope outer;
1453 
1454   ASSERT(!from->IsJSArray());
1455   ASSERT(!to->IsJSArray());
1456 
1457   TransferNamedProperties(from, to);
1458   TransferIndexedProperties(from, to);
1459 
1460   // Transfer the prototype (new map is needed).
1461   Handle<Map> old_to_map = Handle<Map>(to->map());
1462   Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
1463   new_to_map->set_prototype(from->map()->prototype());
1464   to->set_map(*new_to_map);
1465 }
1466 
1467 
MakeFunctionInstancePrototypeWritable()1468 void Genesis::MakeFunctionInstancePrototypeWritable() {
1469   // Make a new function map so all future functions
1470   // will have settable and enumerable prototype properties.
1471   HandleScope scope;
1472 
1473   Handle<DescriptorArray> function_map_descriptors =
1474       ComputeFunctionInstanceDescriptor(false, true);
1475   Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
1476   fm->set_instance_descriptors(*function_map_descriptors);
1477   Top::context()->global_context()->set_function_map(*fm);
1478 }
1479 
1480 
AddSpecialFunction(Handle<JSObject> prototype,const char * name,Handle<Code> code)1481 void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
1482                                  const char* name,
1483                                  Handle<Code> code) {
1484   Handle<String> key = Factory::LookupAsciiSymbol(name);
1485   Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
1486   if (value->IsJSFunction()) {
1487     Handle<JSFunction> optimized = Factory::NewFunction(key,
1488                                                         JS_OBJECT_TYPE,
1489                                                         JSObject::kHeaderSize,
1490                                                         code,
1491                                                         false);
1492     optimized->shared()->DontAdaptArguments();
1493     int len = global_context()->special_function_table()->length();
1494     Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
1495     for (int index = 0; index < len; index++) {
1496       new_array->set(index,
1497                      global_context()->special_function_table()->get(index));
1498     }
1499     new_array->set(len+0, *prototype);
1500     new_array->set(len+1, *value);
1501     new_array->set(len+2, *optimized);
1502     global_context()->set_special_function_table(*new_array);
1503   }
1504 }
1505 
1506 
BuildSpecialFunctionTable()1507 void Genesis::BuildSpecialFunctionTable() {
1508   HandleScope scope;
1509   Handle<JSObject> global = Handle<JSObject>(global_context()->global());
1510   // Add special versions for Array.prototype.pop and push.
1511   Handle<JSFunction> function =
1512       Handle<JSFunction>(
1513           JSFunction::cast(global->GetProperty(Heap::Array_symbol())));
1514   Handle<JSObject> visible_prototype =
1515       Handle<JSObject>(JSObject::cast(function->prototype()));
1516   // Remember to put push and pop on the hidden prototype if it's there.
1517   Handle<JSObject> push_and_pop_prototype;
1518   Handle<Object> superproto(visible_prototype->GetPrototype());
1519   if (superproto->IsJSObject() &&
1520       JSObject::cast(*superproto)->map()->is_hidden_prototype()) {
1521     push_and_pop_prototype = Handle<JSObject>::cast(superproto);
1522   } else {
1523     push_and_pop_prototype = visible_prototype;
1524   }
1525   AddSpecialFunction(push_and_pop_prototype, "pop",
1526                      Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
1527   AddSpecialFunction(push_and_pop_prototype, "push",
1528                      Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
1529 }
1530 
1531 
Genesis(Handle<Object> global_object,v8::Handle<v8::ObjectTemplate> global_template,v8::ExtensionConfiguration * extensions)1532 Genesis::Genesis(Handle<Object> global_object,
1533                  v8::Handle<v8::ObjectTemplate> global_template,
1534                  v8::ExtensionConfiguration* extensions) {
1535   // Link this genesis object into the stacked genesis chain. This
1536   // must be done before any early exits because the destructor
1537   // will always do unlinking.
1538   previous_ = current_;
1539   current_  = this;
1540   result_ = Handle<Context>::null();
1541 
1542   // If V8 isn't running and cannot be initialized, just return.
1543   if (!V8::IsRunning() && !V8::Initialize(NULL)) return;
1544 
1545   // Before creating the roots we must save the context and restore it
1546   // on all function exits.
1547   HandleScope scope;
1548   SaveContext context;
1549 
1550   CreateRoots(global_template, global_object);
1551 
1552   if (!InstallNatives()) return;
1553 
1554   MakeFunctionInstancePrototypeWritable();
1555   BuildSpecialFunctionTable();
1556 
1557   if (!ConfigureGlobalObjects(global_template)) return;
1558 
1559   if (!InstallExtensions(extensions)) return;
1560 
1561   if (!InstallSpecialObjects()) return;
1562 
1563   result_ = global_context_;
1564 }
1565 
1566 
1567 // Support for thread preemption.
1568 
1569 // Reserve space for statics needing saving and restoring.
ArchiveSpacePerThread()1570 int Bootstrapper::ArchiveSpacePerThread() {
1571   return Genesis::ArchiveSpacePerThread();
1572 }
1573 
1574 
1575 // Archive statics that are thread local.
ArchiveState(char * to)1576 char* Bootstrapper::ArchiveState(char* to) {
1577   return Genesis::ArchiveState(to);
1578 }
1579 
1580 
1581 // Restore statics that are thread local.
RestoreState(char * from)1582 char* Bootstrapper::RestoreState(char* from) {
1583   return Genesis::RestoreState(from);
1584 }
1585 
1586 
1587 // Reserve space for statics needing saving and restoring.
ArchiveSpacePerThread()1588 int Genesis::ArchiveSpacePerThread() {
1589   return sizeof(current_);
1590 }
1591 
1592 
1593 // Archive statics that are thread local.
ArchiveState(char * to)1594 char* Genesis::ArchiveState(char* to) {
1595   *reinterpret_cast<Genesis**>(to) = current_;
1596   current_ = NULL;
1597   return to + sizeof(current_);
1598 }
1599 
1600 
1601 // Restore statics that are thread local.
RestoreState(char * from)1602 char* Genesis::RestoreState(char* from) {
1603   current_ = *reinterpret_cast<Genesis**>(from);
1604   return from + sizeof(current_);
1605 }
1606 
1607 } }  // namespace v8::internal
1608