// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "v8.h"

#include "accessors.h"
#include "api.h"
#include "bootstrapper.h"
#include "compiler.h"
#include "debug.h"
#include "execution.h"
#include "global-handles.h"
#include "macro-assembler.h"
#include "natives.h"

namespace v8 { namespace internal {

// A SourceCodeCache uses a FixedArray to store pairs of
// (AsciiString*, JSFunction*), mapping names of native code files
// (runtime.js, etc.) to precompiled functions. Instead of mapping
// names to functions it might make sense to let the JS2C tool
// generate an index for each native JS file.
class SourceCodeCache BASE_EMBEDDED {
 public:
  explicit SourceCodeCache(ScriptType type): type_(type) { }

  void Initialize(bool create_heap_objects) {
    if (create_heap_objects) {
      cache_ = Heap::empty_fixed_array();
    } else {
      cache_ = NULL;
    }
  }

  void Iterate(ObjectVisitor* v) {
    v->VisitPointer(bit_cast<Object**, FixedArray**>(&cache_));
  }


  bool Lookup(Vector<const char> name, Handle<JSFunction>* handle) {
    for (int i = 0; i < cache_->length(); i+=2) {
      SeqAsciiString* str = SeqAsciiString::cast(cache_->get(i));
      if (str->IsEqualTo(name)) {
        *handle = Handle<JSFunction>(JSFunction::cast(cache_->get(i + 1)));
        return true;
      }
    }
    return false;
  }


  void Add(Vector<const char> name, Handle<JSFunction> fun) {
    ASSERT(fun->IsBoilerplate());
    HandleScope scope;
    int length = cache_->length();
    Handle<FixedArray> new_array =
        Factory::NewFixedArray(length + 2, TENURED);
    cache_->CopyTo(0, *new_array, 0, cache_->length());
    cache_ = *new_array;
    Handle<String> str = Factory::NewStringFromAscii(name, TENURED);
    cache_->set(length, *str);
    cache_->set(length + 1, *fun);
    Script::cast(fun->shared()->script())->set_type(Smi::FromInt(type_));
  }

 private:
  ScriptType type_;
  FixedArray* cache_;
  DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
};

static SourceCodeCache natives_cache(SCRIPT_TYPE_NATIVE);
static SourceCodeCache extensions_cache(SCRIPT_TYPE_EXTENSION);


Handle<String> Bootstrapper::NativesSourceLookup(int index) {
  ASSERT(0 <= index && index < Natives::GetBuiltinsCount());
  if (Heap::natives_source_cache()->get(index)->IsUndefined()) {
    Handle<String> source_code =
      Factory::NewStringFromAscii(Natives::GetScriptSource(index));
    Heap::natives_source_cache()->set(index, *source_code);
  }
  Handle<Object> cached_source(Heap::natives_source_cache()->get(index));
  return Handle<String>::cast(cached_source);
}


bool Bootstrapper::NativesCacheLookup(Vector<const char> name,
                                      Handle<JSFunction>* handle) {
  return natives_cache.Lookup(name, handle);
}


void Bootstrapper::NativesCacheAdd(Vector<const char> name,
                                   Handle<JSFunction> fun) {
  natives_cache.Add(name, fun);
}


void Bootstrapper::Initialize(bool create_heap_objects) {
  natives_cache.Initialize(create_heap_objects);
  extensions_cache.Initialize(create_heap_objects);
}


void Bootstrapper::TearDown() {
  natives_cache.Initialize(false);  // Yes, symmetrical
  extensions_cache.Initialize(false);
}


// Pending fixups are code positions that have refer to builtin code
// objects that were not available at the time the code was generated.
// The pending list is processed whenever an environment has been
// created.
class PendingFixups : public AllStatic {
 public:
  static void Add(Code* code, MacroAssembler* masm);
  static bool Process(Handle<JSBuiltinsObject> builtins);

  static void Iterate(ObjectVisitor* v);

 private:
  static List<Object*> code_;
  static List<const char*> name_;
  static List<int> pc_;
  static List<uint32_t> flags_;

  static void Clear();
};


List<Object*> PendingFixups::code_(0);
List<const char*> PendingFixups::name_(0);
List<int> PendingFixups::pc_(0);
List<uint32_t> PendingFixups::flags_(0);


void PendingFixups::Add(Code* code, MacroAssembler* masm) {
  // Note this code is not only called during bootstrapping.
  List<MacroAssembler::Unresolved>* unresolved = masm->unresolved();
  int n = unresolved->length();
  for (int i = 0; i < n; i++) {
    const char* name = unresolved->at(i).name;
    code_.Add(code);
    name_.Add(name);
    pc_.Add(unresolved->at(i).pc);
    flags_.Add(unresolved->at(i).flags);
    LOG(StringEvent("unresolved", name));
  }
}


bool PendingFixups::Process(Handle<JSBuiltinsObject> builtins) {
  HandleScope scope;
  // NOTE: Extra fixups may be added to the list during the iteration
  // due to lazy compilation of functions during the processing. Do not
  // cache the result of getting the length of the code list.
  for (int i = 0; i < code_.length(); i++) {
    const char* name = name_[i];
    uint32_t flags = flags_[i];
    Handle<String> symbol = Factory::LookupAsciiSymbol(name);
    Object* o = builtins->GetProperty(*symbol);
#ifdef DEBUG
    if (!o->IsJSFunction()) {
      V8_Fatal(__FILE__, __LINE__, "Cannot resolve call to builtin %s", name);
    }
#endif
    Handle<JSFunction> f = Handle<JSFunction>(JSFunction::cast(o));
    // Make sure the number of parameters match the formal parameter count.
    int argc = Bootstrapper::FixupFlagsArgumentsCount::decode(flags);
    USE(argc);
    ASSERT(f->shared()->formal_parameter_count() == argc);
    if (!f->is_compiled()) {
      // Do lazy compilation and check for stack overflows.
      if (!CompileLazy(f, CLEAR_EXCEPTION)) {
        Clear();
        return false;
      }
    }
    Code* code = Code::cast(code_[i]);
    Address pc = code->instruction_start() + pc_[i];
    bool is_pc_relative = Bootstrapper::FixupFlagsIsPCRelative::decode(flags);
    bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);

    if (use_code_object) {
      if (is_pc_relative) {
        Assembler::set_target_address_at(
            pc, reinterpret_cast<Address>(f->code()));
      } else {
        *reinterpret_cast<Object**>(pc) = f->code();
      }
    } else {
      ASSERT(is_pc_relative);
      Assembler::set_target_address_at(pc, f->code()->instruction_start());
    }

    LOG(StringEvent("resolved", name));
  }
  Clear();

  // TODO(1240818): We should probably try to avoid doing this for all
  // the V8 builtin JS files. It should only happen after running
  // runtime.js - just like there shouldn't be any fixups left after
  // that.
  for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
    Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
    Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
    JSFunction* function = JSFunction::cast(builtins->GetProperty(*name));
    builtins->set_javascript_builtin(id, function);
  }

  return true;
}


void PendingFixups::Clear() {
  code_.Clear();
  name_.Clear();
  pc_.Clear();
  flags_.Clear();
}


void PendingFixups::Iterate(ObjectVisitor* v) {
  if (!code_.is_empty()) {
    v->VisitPointers(&code_[0], &code_[0] + code_.length());
  }
}


class Genesis BASE_EMBEDDED {
 public:
  Genesis(Handle<Object> global_object,
          v8::Handle<v8::ObjectTemplate> global_template,
          v8::ExtensionConfiguration* extensions);
  ~Genesis();

  Handle<Context> result() { return result_; }

  Genesis* previous() { return previous_; }
  static Genesis* current() { return current_; }

  // Support for thread preemption.
  static int ArchiveSpacePerThread();
  static char* ArchiveState(char* to);
  static char* RestoreState(char* from);

 private:
  Handle<Context> global_context_;

  // There may be more than one active genesis object: When GC is
  // triggered during environment creation there may be weak handle
  // processing callbacks which may create new environments.
  Genesis* previous_;
  static Genesis* current_;

  Handle<Context> global_context() { return global_context_; }

  void CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
                   Handle<Object> global_object);
  void InstallNativeFunctions();
  bool InstallNatives();
  bool InstallExtensions(v8::ExtensionConfiguration* extensions);
  bool InstallExtension(const char* name);
  bool InstallExtension(v8::RegisteredExtension* current);
  bool InstallSpecialObjects();
  bool ConfigureApiObject(Handle<JSObject> object,
                          Handle<ObjectTemplateInfo> object_template);
  bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);

  // Migrates all properties from the 'from' object to the 'to'
  // object and overrides the prototype in 'to' with the one from
  // 'from'.
  void TransferObject(Handle<JSObject> from, Handle<JSObject> to);
  void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to);
  void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to);

  Handle<DescriptorArray> ComputeFunctionInstanceDescriptor(
      bool make_prototype_read_only,
      bool make_prototype_enumerable = false);
  void MakeFunctionInstancePrototypeWritable();

  void AddSpecialFunction(Handle<JSObject> prototype,
                          const char* name,
                          Handle<Code> code);

  void BuildSpecialFunctionTable();

  static bool CompileBuiltin(int index);
  static bool CompileNative(Vector<const char> name, Handle<String> source);
  static bool CompileScriptCached(Vector<const char> name,
                                  Handle<String> source,
                                  SourceCodeCache* cache,
                                  v8::Extension* extension,
                                  bool use_runtime_context);

  Handle<Context> result_;
};

Genesis* Genesis::current_ = NULL;


void Bootstrapper::Iterate(ObjectVisitor* v) {
  natives_cache.Iterate(v);
  extensions_cache.Iterate(v);
  PendingFixups::Iterate(v);
}


// While setting up the environment, we collect code positions that
// need to be patched before we can run any code in the environment.
void Bootstrapper::AddFixup(Code* code, MacroAssembler* masm) {
  PendingFixups::Add(code, masm);
}


bool Bootstrapper::IsActive() {
  return Genesis::current() != NULL;
}


Handle<Context> Bootstrapper::CreateEnvironment(
    Handle<Object> global_object,
    v8::Handle<v8::ObjectTemplate> global_template,
    v8::ExtensionConfiguration* extensions) {
  Genesis genesis(global_object, global_template, extensions);
  return genesis.result();
}


static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
  // object.__proto__ = proto;
  Handle<Map> old_to_map = Handle<Map>(object->map());
  Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
  new_to_map->set_prototype(*proto);
  object->set_map(*new_to_map);
}


void Bootstrapper::DetachGlobal(Handle<Context> env) {
  JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value());
  SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
                     Factory::null_value());
  env->set_global_proxy(env->global());
  env->global()->set_global_receiver(env->global());
}


Genesis::~Genesis() {
  ASSERT(current_ == this);
  current_ = previous_;
}


static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
                                          const char* name,
                                          InstanceType type,
                                          int instance_size,
                                          Handle<JSObject> prototype,
                                          Builtins::Name call,
                                          bool is_ecma_native) {
  Handle<String> symbol = Factory::LookupAsciiSymbol(name);
  Handle<Code> call_code = Handle<Code>(Builtins::builtin(call));
  Handle<JSFunction> function =
    Factory::NewFunctionWithPrototype(symbol,
                                      type,
                                      instance_size,
                                      prototype,
                                      call_code,
                                      is_ecma_native);
  SetProperty(target, symbol, function, DONT_ENUM);
  if (is_ecma_native) {
    function->shared()->set_instance_class_name(*symbol);
  }
  return function;
}


Handle<DescriptorArray> Genesis::ComputeFunctionInstanceDescriptor(
    bool make_prototype_read_only,
    bool make_prototype_enumerable) {
  Handle<DescriptorArray> result = Factory::empty_descriptor_array();

  // Add prototype.
  PropertyAttributes attributes = static_cast<PropertyAttributes>(
      (make_prototype_enumerable ? 0 : DONT_ENUM)
      | DONT_DELETE
      | (make_prototype_read_only ? READ_ONLY : 0));
  result =
      Factory::CopyAppendProxyDescriptor(
          result,
          Factory::prototype_symbol(),
          Factory::NewProxy(&Accessors::FunctionPrototype),
          attributes);

  attributes =
      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
  // Add length.
  result =
      Factory::CopyAppendProxyDescriptor(
          result,
          Factory::length_symbol(),
          Factory::NewProxy(&Accessors::FunctionLength),
          attributes);

  // Add name.
  result =
      Factory::CopyAppendProxyDescriptor(
          result,
          Factory::name_symbol(),
          Factory::NewProxy(&Accessors::FunctionName),
          attributes);

  // Add arguments.
  result =
      Factory::CopyAppendProxyDescriptor(
          result,
          Factory::arguments_symbol(),
          Factory::NewProxy(&Accessors::FunctionArguments),
          attributes);

  // Add caller.
  result =
      Factory::CopyAppendProxyDescriptor(
          result,
          Factory::caller_symbol(),
          Factory::NewProxy(&Accessors::FunctionCaller),
          attributes);

  return result;
}


void Genesis::CreateRoots(v8::Handle<v8::ObjectTemplate> global_template,
                          Handle<Object> global_object) {
  HandleScope scope;
  // Allocate the global context FixedArray first and then patch the
  // closure and extension object later (we need the empty function
  // and the global object, but in order to create those, we need the
  // global context).
  global_context_ =
      Handle<Context>::cast(
          GlobalHandles::Create(*Factory::NewGlobalContext()));
  Top::set_context(*global_context());

  // Allocate the message listeners object.
  v8::NeanderArray listeners;
  global_context()->set_message_listeners(*listeners.value());

  // Allocate the map for function instances.
  Handle<Map> fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
  global_context()->set_function_instance_map(*fm);
  // Please note that the prototype property for function instances must be
  // writable.
  Handle<DescriptorArray> function_map_descriptors =
      ComputeFunctionInstanceDescriptor(false, true);
  fm->set_instance_descriptors(*function_map_descriptors);

  // Allocate the function map first and then patch the prototype later
  fm = Factory::NewMap(JS_FUNCTION_TYPE, JSFunction::kSize);
  global_context()->set_function_map(*fm);
  function_map_descriptors = ComputeFunctionInstanceDescriptor(true);
  fm->set_instance_descriptors(*function_map_descriptors);

  Handle<String> object_name = Handle<String>(Heap::Object_symbol());

  {  // --- O b j e c t ---
    Handle<JSFunction> object_fun =
        Factory::NewFunction(object_name, Factory::null_value());
    Handle<Map> object_function_map =
        Factory::NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize);
    object_fun->set_initial_map(*object_function_map);
    object_function_map->set_constructor(*object_fun);

    global_context()->set_object_function(*object_fun);

    // Allocate a new prototype for the object function.
    Handle<JSObject> prototype = Factory::NewJSObject(Top::object_function(),
                                                      TENURED);

    global_context()->set_initial_object_prototype(*prototype);
    SetPrototype(object_fun, prototype);
    object_function_map->
      set_instance_descriptors(Heap::empty_descriptor_array());
  }

  // Allocate the empty function as the prototype for function ECMAScript
  // 262 15.3.4.
  Handle<String> symbol = Factory::LookupAsciiSymbol("Empty");
  Handle<JSFunction> empty_function =
      Factory::NewFunction(symbol, Factory::null_value());

  {  // --- E m p t y ---
    Handle<Code> code =
        Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
    empty_function->set_code(*code);
    Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
    Handle<Script> script = Factory::NewScript(source);
    script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
    empty_function->shared()->set_script(*script);
    empty_function->shared()->set_start_position(0);
    empty_function->shared()->set_end_position(source->length());
    empty_function->shared()->DontAdaptArguments();
    global_context()->function_map()->set_prototype(*empty_function);
    global_context()->function_instance_map()->set_prototype(*empty_function);

    // Allocate the function map first and then patch the prototype later
    Handle<Map> empty_fm = Factory::CopyMapDropDescriptors(fm);
    empty_fm->set_instance_descriptors(*function_map_descriptors);
    empty_fm->set_prototype(global_context()->object_function()->prototype());
    empty_function->set_map(*empty_fm);
  }

  {  // --- G l o b a l ---
    // Step 1: create a fresh inner JSGlobalObject
    Handle<JSGlobalObject> object;
    {
      Handle<JSFunction> js_global_function;
      Handle<ObjectTemplateInfo> js_global_template;
      if (!global_template.IsEmpty()) {
        // Get prototype template of the global_template
        Handle<ObjectTemplateInfo> data =
            v8::Utils::OpenHandle(*global_template);
        Handle<FunctionTemplateInfo> global_constructor =
            Handle<FunctionTemplateInfo>(
                FunctionTemplateInfo::cast(data->constructor()));
        Handle<Object> proto_template(global_constructor->prototype_template());
        if (!proto_template->IsUndefined()) {
          js_global_template =
              Handle<ObjectTemplateInfo>::cast(proto_template);
        }
      }

      if (js_global_template.is_null()) {
        Handle<String> name = Handle<String>(Heap::empty_symbol());
        Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
        js_global_function =
            Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
                                 JSGlobalObject::kSize, code, true);
        // Change the constructor property of the prototype of the
        // hidden global function to refer to the Object function.
        Handle<JSObject> prototype =
            Handle<JSObject>(
                JSObject::cast(js_global_function->instance_prototype()));
        SetProperty(prototype, Factory::constructor_symbol(),
                    Top::object_function(), NONE);
      } else {
        Handle<FunctionTemplateInfo> js_global_constructor(
            FunctionTemplateInfo::cast(js_global_template->constructor()));
        js_global_function =
            Factory::CreateApiFunction(js_global_constructor,
                                       Factory::InnerGlobalObject);
      }

      js_global_function->initial_map()->set_is_hidden_prototype();
      SetExpectedNofProperties(js_global_function, 100);
      object = Handle<JSGlobalObject>::cast(
          Factory::NewJSObject(js_global_function, TENURED));
    }

    // Set the global context for the global object.
    object->set_global_context(*global_context());

    // Step 2: create or re-initialize the global proxy object.
    Handle<JSGlobalProxy> global_proxy;
    {
      Handle<JSFunction> global_proxy_function;
      if (global_template.IsEmpty()) {
        Handle<String> name = Handle<String>(Heap::empty_symbol());
        Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
        global_proxy_function =
            Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
                                 JSGlobalProxy::kSize, code, true);
      } else {
        Handle<ObjectTemplateInfo> data =
            v8::Utils::OpenHandle(*global_template);
        Handle<FunctionTemplateInfo> global_constructor(
                FunctionTemplateInfo::cast(data->constructor()));
        global_proxy_function =
            Factory::CreateApiFunction(global_constructor,
                                       Factory::OuterGlobalObject);
      }

      Handle<String> global_name = Factory::LookupAsciiSymbol("global");
      global_proxy_function->shared()->set_instance_class_name(*global_name);
      global_proxy_function->initial_map()->set_is_access_check_needed(true);

      // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects

      if (global_object.location() != NULL) {
        ASSERT(global_object->IsJSGlobalProxy());
        global_proxy =
            ReinitializeJSGlobalProxy(
                global_proxy_function,
                Handle<JSGlobalProxy>::cast(global_object));
      } else {
        global_proxy = Handle<JSGlobalProxy>::cast(
            Factory::NewJSObject(global_proxy_function, TENURED));
      }

      // Security setup: Set the security token of the global object to
      // its the inner global. This makes the security check between two
      // different contexts fail by default even in case of global
      // object reinitialization.
      object->set_global_receiver(*global_proxy);
      global_proxy->set_context(*global_context());
    }

    {  // --- G l o b a l   C o n t e x t ---
      // use the empty function as closure (no scope info)
      global_context()->set_closure(*empty_function);
      global_context()->set_fcontext(*global_context());
      global_context()->set_previous(NULL);

      // set extension and global object
      global_context()->set_extension(*object);
      global_context()->set_global(*object);
      global_context()->set_global_proxy(*global_proxy);
      // use inner global object as security token by default
      global_context()->set_security_token(*object);
    }

    Handle<JSObject> global = Handle<JSObject>(global_context()->global());
    SetProperty(global, object_name, Top::object_function(), DONT_ENUM);
  }

  Handle<JSObject> global = Handle<JSObject>(global_context()->global());

  // Install global Function object
  InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize,
                  empty_function, Builtins::Illegal, true);  // ECMA native.

  {  // --- A r r a y ---
    Handle<JSFunction> array_function =
        InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize,
                        Top::initial_object_prototype(), Builtins::ArrayCode,
                        true);
    array_function->shared()->DontAdaptArguments();

    // This seems a bit hackish, but we need to make sure Array.length
    // is 1.
    array_function->shared()->set_length(1);
    Handle<DescriptorArray> array_descriptors =
        Factory::CopyAppendProxyDescriptor(
            Factory::empty_descriptor_array(),
            Factory::length_symbol(),
            Factory::NewProxy(&Accessors::ArrayLength),
            static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE));

    // Cache the fast JavaScript array map
    global_context()->set_js_array_map(array_function->initial_map());
    global_context()->js_array_map()->set_instance_descriptors(
        *array_descriptors);
    // array_function is used internally. JS code creating array object should
    // search for the 'Array' property on the global object and use that one
    // as the constructor. 'Array' property on a global object can be
    // overwritten by JS code.
    global_context()->set_array_function(*array_function);
  }

  {  // --- N u m b e r ---
    Handle<JSFunction> number_fun =
        InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize,
                        Top::initial_object_prototype(), Builtins::Illegal,
                        true);
    global_context()->set_number_function(*number_fun);
  }

  {  // --- B o o l e a n ---
    Handle<JSFunction> boolean_fun =
        InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize,
                        Top::initial_object_prototype(), Builtins::Illegal,
                        true);
    global_context()->set_boolean_function(*boolean_fun);
  }

  {  // --- S t r i n g ---
    Handle<JSFunction> string_fun =
        InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize,
                        Top::initial_object_prototype(), Builtins::Illegal,
                        true);
    global_context()->set_string_function(*string_fun);
    // Add 'length' property to strings.
    Handle<DescriptorArray> string_descriptors =
        Factory::CopyAppendProxyDescriptor(
            Factory::empty_descriptor_array(),
            Factory::length_symbol(),
            Factory::NewProxy(&Accessors::StringLength),
            static_cast<PropertyAttributes>(DONT_ENUM |
                                            DONT_DELETE |
                                            READ_ONLY));

    Handle<Map> string_map =
        Handle<Map>(global_context()->string_function()->initial_map());
    string_map->set_instance_descriptors(*string_descriptors);
  }

  {  // --- D a t e ---
    // Builtin functions for Date.prototype.
    Handle<JSFunction> date_fun =
        InstallFunction(global, "Date", JS_VALUE_TYPE, JSValue::kSize,
                        Top::initial_object_prototype(), Builtins::Illegal,
                        true);

    global_context()->set_date_function(*date_fun);
  }


  {  // -- R e g E x p
    // Builtin functions for RegExp.prototype.
    Handle<JSFunction> regexp_fun =
        InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize,
                        Top::initial_object_prototype(), Builtins::Illegal,
                        true);

    global_context()->set_regexp_function(*regexp_fun);
  }

  {  // -- J S O N
    Handle<String> name = Factory::NewStringFromAscii(CStrVector("JSON"));
    Handle<JSFunction> cons = Factory::NewFunction(
        name,
        Factory::the_hole_value());
    cons->SetInstancePrototype(global_context()->initial_object_prototype());
    cons->SetInstanceClassName(*name);
    Handle<JSObject> json_object = Factory::NewJSObject(cons, TENURED);
    ASSERT(json_object->IsJSObject());
    SetProperty(global, name, json_object, DONT_ENUM);
    global_context()->set_json_object(*json_object);
  }

  {  // --- arguments_boilerplate_
    // Make sure we can recognize argument objects at runtime.
    // This is done by introducing an anonymous function with
    // class_name equals 'Arguments'.
    Handle<String> symbol = Factory::LookupAsciiSymbol("Arguments");
    Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
    Handle<JSObject> prototype =
        Handle<JSObject>(
            JSObject::cast(global_context()->object_function()->prototype()));

    Handle<JSFunction> function =
        Factory::NewFunctionWithPrototype(symbol,
                                          JS_OBJECT_TYPE,
                                          JSObject::kHeaderSize,
                                          prototype,
                                          code,
                                          false);
    ASSERT(!function->has_initial_map());
    function->shared()->set_instance_class_name(*symbol);
    function->shared()->set_expected_nof_properties(2);
    Handle<JSObject> result = Factory::NewJSObject(function);

    global_context()->set_arguments_boilerplate(*result);
    // Note: callee must be added as the first property and
    //       length must be added as the second property.
    SetProperty(result, Factory::callee_symbol(),
                Factory::undefined_value(),
                DONT_ENUM);
    SetProperty(result, Factory::length_symbol(),
                Factory::undefined_value(),
                DONT_ENUM);

#ifdef DEBUG
    LookupResult lookup;
    result->LocalLookup(Heap::callee_symbol(), &lookup);
    ASSERT(lookup.IsValid() && (lookup.type() == FIELD));
    ASSERT(lookup.GetFieldIndex() == Heap::arguments_callee_index);

    result->LocalLookup(Heap::length_symbol(), &lookup);
    ASSERT(lookup.IsValid() && (lookup.type() == FIELD));
    ASSERT(lookup.GetFieldIndex() == Heap::arguments_length_index);

    ASSERT(result->map()->inobject_properties() > Heap::arguments_callee_index);
    ASSERT(result->map()->inobject_properties() > Heap::arguments_length_index);

    // Check the state of the object.
    ASSERT(result->HasFastProperties());
    ASSERT(result->HasFastElements());
#endif
  }

  {  // --- context extension
    // Create a function for the context extension objects.
    Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
    Handle<JSFunction> context_extension_fun =
        Factory::NewFunction(Factory::empty_symbol(),
                             JS_CONTEXT_EXTENSION_OBJECT_TYPE,
                             JSObject::kHeaderSize,
                             code,
                             true);

    Handle<String> name = Factory::LookupAsciiSymbol("context_extension");
    context_extension_fun->shared()->set_instance_class_name(*name);
    global_context()->set_context_extension_function(*context_extension_fun);
  }

  // Setup the call-as-function delegate.
  Handle<Code> code =
      Handle<Code>(Builtins::builtin(Builtins::HandleApiCallAsFunction));
  Handle<JSFunction> delegate =
      Factory::NewFunction(Factory::empty_symbol(), JS_OBJECT_TYPE,
                           JSObject::kHeaderSize, code, true);
  global_context()->set_call_as_function_delegate(*delegate);
  delegate->shared()->DontAdaptArguments();

  global_context()->set_special_function_table(Heap::empty_fixed_array());

  // Initialize the out of memory slot.
  global_context()->set_out_of_memory(Heap::false_value());
}


bool Genesis::CompileBuiltin(int index) {
  Vector<const char> name = Natives::GetScriptName(index);
  Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
  return CompileNative(name, source_code);
}


bool Genesis::CompileNative(Vector<const char> name, Handle<String> source) {
  HandleScope scope;
#ifdef ENABLE_DEBUGGER_SUPPORT
  Debugger::set_compiling_natives(true);
#endif
  bool result =
      CompileScriptCached(name, source, &natives_cache, NULL, true);
  ASSERT(Top::has_pending_exception() != result);
  if (!result) Top::clear_pending_exception();
#ifdef ENABLE_DEBUGGER_SUPPORT
  Debugger::set_compiling_natives(false);
#endif
  return result;
}


bool Genesis::CompileScriptCached(Vector<const char> name,
                                  Handle<String> source,
                                  SourceCodeCache* cache,
                                  v8::Extension* extension,
                                  bool use_runtime_context) {
  HandleScope scope;
  Handle<JSFunction> boilerplate;

  // If we can't find the function in the cache, we compile a new
  // function and insert it into the cache.
  if (!cache->Lookup(name, &boilerplate)) {
#ifdef DEBUG
    ASSERT(StringShape(*source).IsAsciiRepresentation());
#endif
    Handle<String> script_name = Factory::NewStringFromUtf8(name);
    boilerplate =
        Compiler::Compile(source, script_name, 0, 0, extension, NULL);
    if (boilerplate.is_null()) return false;
    cache->Add(name, boilerplate);
  }

  // Setup the function context. Conceptually, we should clone the
  // function before overwriting the context but since we're in a
  // single-threaded environment it is not strictly necessary.
  ASSERT(Top::context()->IsGlobalContext());
  Handle<Context> context =
      Handle<Context>(use_runtime_context
                      ? Top::context()->runtime_context()
                      : Top::context());
  Handle<JSFunction> fun =
      Factory::NewFunctionFromBoilerplate(boilerplate, context);

  // Call function using the either the runtime object or the global
  // object as the receiver. Provide no parameters.
  Handle<Object> receiver =
      Handle<Object>(use_runtime_context
                     ? Top::context()->builtins()
                     : Top::context()->global());
  bool has_pending_exception;
  Handle<Object> result =
      Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
  if (has_pending_exception) return false;
  return PendingFixups::Process(
      Handle<JSBuiltinsObject>(Top::context()->builtins()));
}


#define INSTALL_NATIVE(Type, name, var)                                  \
  Handle<String> var##_name = Factory::LookupAsciiSymbol(name);          \
  global_context()->set_##var(Type::cast(global_context()->              \
                                           builtins()->                  \
                                             GetProperty(*var##_name)));

void Genesis::InstallNativeFunctions() {
  HandleScope scope;
  INSTALL_NATIVE(JSFunction, "CreateDate", create_date_fun);
  INSTALL_NATIVE(JSFunction, "ToNumber", to_number_fun);
  INSTALL_NATIVE(JSFunction, "ToString", to_string_fun);
  INSTALL_NATIVE(JSFunction, "ToDetailString", to_detail_string_fun);
  INSTALL_NATIVE(JSFunction, "ToObject", to_object_fun);
  INSTALL_NATIVE(JSFunction, "ToInteger", to_integer_fun);
  INSTALL_NATIVE(JSFunction, "ToUint32", to_uint32_fun);
  INSTALL_NATIVE(JSFunction, "ToInt32", to_int32_fun);
  INSTALL_NATIVE(JSFunction, "ToBoolean", to_boolean_fun);
  INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun);
  INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance",
                 configure_instance_fun);
  INSTALL_NATIVE(JSFunction, "MakeMessage", make_message_fun);
  INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun);
  INSTALL_NATIVE(JSObject, "functionCache", function_cache);
}

#undef INSTALL_NATIVE


bool Genesis::InstallNatives() {
  HandleScope scope;

  // Create a function for the builtins object. Allocate space for the
  // JavaScript builtins, a reference to the builtins object
  // (itself) and a reference to the global_context directly in the object.
  Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
  Handle<JSFunction> builtins_fun =
      Factory::NewFunction(Factory::empty_symbol(), JS_BUILTINS_OBJECT_TYPE,
                           JSBuiltinsObject::kSize, code, true);

  Handle<String> name = Factory::LookupAsciiSymbol("builtins");
  builtins_fun->shared()->set_instance_class_name(*name);
  SetExpectedNofProperties(builtins_fun, 100);

  // Allocate the builtins object.
  Handle<JSBuiltinsObject> builtins =
      Handle<JSBuiltinsObject>::cast(Factory::NewJSObject(builtins_fun,
                                                          TENURED));
  builtins->set_builtins(*builtins);
  builtins->set_global_context(*global_context());
  builtins->set_global_receiver(*builtins);

  // Setup the 'global' properties of the builtins object. The
  // 'global' property that refers to the global object is the only
  // way to get from code running in the builtins context to the
  // global object.
  static const PropertyAttributes attributes =
      static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
  SetProperty(builtins, Factory::LookupAsciiSymbol("global"),
              Handle<Object>(global_context()->global()), attributes);

  // Setup the reference from the global object to the builtins object.
  JSGlobalObject::cast(global_context()->global())->set_builtins(*builtins);

  // Create a bridge function that has context in the global context.
  Handle<JSFunction> bridge =
      Factory::NewFunction(Factory::empty_symbol(), Factory::undefined_value());
  ASSERT(bridge->context() == *Top::global_context());

  // Allocate the builtins context.
  Handle<Context> context =
    Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge);
  context->set_global(*builtins);  // override builtins global object

  global_context()->set_runtime_context(*context);

  {  // -- S c r i p t
    // Builtin functions for Script.
    Handle<JSFunction> script_fun =
        InstallFunction(builtins, "Script", JS_VALUE_TYPE, JSValue::kSize,
                        Top::initial_object_prototype(), Builtins::Illegal,
                        false);
    Handle<JSObject> prototype =
        Factory::NewJSObject(Top::object_function(), TENURED);
    SetPrototype(script_fun, prototype);
    global_context()->set_script_function(*script_fun);

    // Add 'source' and 'data' property to scripts.
    PropertyAttributes common_attributes =
        static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
    Handle<Proxy> proxy_source = Factory::NewProxy(&Accessors::ScriptSource);
    Handle<DescriptorArray> script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            Factory::empty_descriptor_array(),
            Factory::LookupAsciiSymbol("source"),
            proxy_source,
            common_attributes);
    Handle<Proxy> proxy_name = Factory::NewProxy(&Accessors::ScriptName);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("name"),
            proxy_name,
            common_attributes);
    Handle<Proxy> proxy_id = Factory::NewProxy(&Accessors::ScriptId);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("id"),
            proxy_id,
            common_attributes);
    Handle<Proxy> proxy_line_offset =
        Factory::NewProxy(&Accessors::ScriptLineOffset);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("line_offset"),
            proxy_line_offset,
            common_attributes);
    Handle<Proxy> proxy_column_offset =
        Factory::NewProxy(&Accessors::ScriptColumnOffset);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("column_offset"),
            proxy_column_offset,
            common_attributes);
    Handle<Proxy> proxy_data = Factory::NewProxy(&Accessors::ScriptData);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("data"),
            proxy_data,
            common_attributes);
    Handle<Proxy> proxy_type = Factory::NewProxy(&Accessors::ScriptType);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("type"),
            proxy_type,
            common_attributes);
    Handle<Proxy> proxy_line_ends =
        Factory::NewProxy(&Accessors::ScriptLineEnds);
    script_descriptors =
        Factory::CopyAppendProxyDescriptor(
            script_descriptors,
            Factory::LookupAsciiSymbol("line_ends"),
            proxy_line_ends,
            common_attributes);

    Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
    script_map->set_instance_descriptors(*script_descriptors);

    // Allocate the empty script.
    Handle<Script> script = Factory::NewScript(Factory::empty_string());
    script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
    global_context()->set_empty_script(*script);
  }

  if (FLAG_natives_file == NULL) {
    // Without natives file, install default natives.
    for (int i = Natives::GetDelayCount();
         i < Natives::GetBuiltinsCount();
         i++) {
      if (!CompileBuiltin(i)) return false;
    }

    // Setup natives with lazy loading.
    SetupLazy(Handle<JSFunction>(global_context()->date_function()),
              Natives::GetIndex("date"),
              Top::global_context(),
              Handle<Context>(Top::context()->runtime_context()));
    SetupLazy(Handle<JSFunction>(global_context()->regexp_function()),
              Natives::GetIndex("regexp"),
              Top::global_context(),
              Handle<Context>(Top::context()->runtime_context()));
    SetupLazy(Handle<JSObject>(global_context()->json_object()),
              Natives::GetIndex("json"),
              Top::global_context(),
              Handle<Context>(Top::context()->runtime_context()));

  } else if (strlen(FLAG_natives_file) != 0) {
    // Otherwise install natives from natives file if file exists and
    // compiles.
    bool exists;
    Vector<const char> source = ReadFile(FLAG_natives_file, &exists);
    Handle<String> source_string = Factory::NewStringFromAscii(source);
    if (source.is_empty()) return false;
    bool result = CompileNative(CStrVector(FLAG_natives_file), source_string);
    if (!result) return false;

  } else {
    // Empty natives file name - do not install any natives.
    PrintF("Warning: Running without installed natives!\n");
    return true;
  }

  InstallNativeFunctions();

  // Install Function.prototype.call and apply.
  { Handle<String> key = Factory::function_class_symbol();
    Handle<JSFunction> function =
        Handle<JSFunction>::cast(GetProperty(Top::global(), key));
    Handle<JSObject> proto =
        Handle<JSObject>(JSObject::cast(function->instance_prototype()));

    // Install the call and the apply functions.
    Handle<JSFunction> call =
        InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize,
                        Factory::NewJSObject(Top::object_function(), TENURED),
                        Builtins::FunctionCall,
                        false);
    Handle<JSFunction> apply =
        InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize,
                        Factory::NewJSObject(Top::object_function(), TENURED),
                        Builtins::FunctionApply,
                        false);

    // Make sure that Function.prototype.call appears to be compiled.
    // The code will never be called, but inline caching for call will
    // only work if it appears to be compiled.
    call->shared()->DontAdaptArguments();
    ASSERT(call->is_compiled());

    // Set the expected parameters for apply to 2; required by builtin.
    apply->shared()->set_formal_parameter_count(2);

    // Set the lengths for the functions to satisfy ECMA-262.
    call->shared()->set_length(1);
    apply->shared()->set_length(2);
  }

  // Make sure that the builtins object has fast properties.
  // If the ASSERT below fails, please increase the expected number of
  // properties for the builtins object.
  ASSERT(builtins->HasFastProperties());
#ifdef DEBUG
  builtins->Verify();
#endif
  return true;
}


bool Genesis::InstallSpecialObjects() {
  HandleScope scope;
  Handle<JSGlobalObject> js_global(
      JSGlobalObject::cast(global_context()->global()));
  // Expose the natives in global if a name for it is specified.
  if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
    Handle<String> natives_string =
        Factory::LookupAsciiSymbol(FLAG_expose_natives_as);
    SetProperty(js_global, natives_string,
                Handle<JSObject>(js_global->builtins()), DONT_ENUM);
  }

#ifdef ENABLE_DEBUGGER_SUPPORT
  // Expose the debug global object in global if a name for it is specified.
  if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) {
    // If loading fails we just bail out without installing the
    // debugger but without tanking the whole context.
    if (!Debug::Load())
      return true;
    // Set the security token for the debugger context to the same as
    // the shell global context to allow calling between these (otherwise
    // exposing debug global object doesn't make much sense).
    Debug::debug_context()->set_security_token(
        global_context()->security_token());

    Handle<String> debug_string =
        Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
    SetProperty(js_global, debug_string,
        Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
  }
#endif

  return true;
}


bool Genesis::InstallExtensions(v8::ExtensionConfiguration* extensions) {
  // Clear coloring of extension list
  v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
  while (current != NULL) {
    current->set_state(v8::UNVISITED);
    current = current->next();
  }
  // Install auto extensions
  current = v8::RegisteredExtension::first_extension();
  while (current != NULL) {
    if (current->extension()->auto_enable())
      InstallExtension(current);
    current = current->next();
  }

  if (FLAG_expose_gc) InstallExtension("v8/gc");

  if (extensions == NULL) return true;
  // Install required extensions
  int count = v8::ImplementationUtilities::GetNameCount(extensions);
  const char** names = v8::ImplementationUtilities::GetNames(extensions);
  for (int i = 0; i < count; i++) {
    if (!InstallExtension(names[i]))
      return false;
  }

  return true;
}


// Installs a named extension.  This methods is unoptimized and does
// not scale well if we want to support a large number of extensions.
bool Genesis::InstallExtension(const char* name) {
  v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
  // Loop until we find the relevant extension
  while (current != NULL) {
    if (strcmp(name, current->extension()->name()) == 0) break;
    current = current->next();
  }
  // Didn't find the extension; fail.
  if (current == NULL) {
    v8::Utils::ReportApiFailure(
        "v8::Context::New()", "Cannot find required extension");
    return false;
  }
  return InstallExtension(current);
}


bool Genesis::InstallExtension(v8::RegisteredExtension* current) {
  HandleScope scope;

  if (current->state() == v8::INSTALLED) return true;
  // The current node has already been visited so there must be a
  // cycle in the dependency graph; fail.
  if (current->state() == v8::VISITED) {
    v8::Utils::ReportApiFailure(
        "v8::Context::New()", "Circular extension dependency");
    return false;
  }
  ASSERT(current->state() == v8::UNVISITED);
  current->set_state(v8::VISITED);
  v8::Extension* extension = current->extension();
  // Install the extension's dependencies
  for (int i = 0; i < extension->dependency_count(); i++) {
    if (!InstallExtension(extension->dependencies()[i])) return false;
  }
  Vector<const char> source = CStrVector(extension->source());
  Handle<String> source_code = Factory::NewStringFromAscii(source);
  bool result = CompileScriptCached(CStrVector(extension->name()),
                                    source_code,
                                    &extensions_cache, extension,
                                    false);
  ASSERT(Top::has_pending_exception() != result);
  if (!result) {
    Top::clear_pending_exception();
    v8::Utils::ReportApiFailure(
        "v8::Context::New()", "Error installing extension");
  }
  current->set_state(v8::INSTALLED);
  return result;
}


bool Genesis::ConfigureGlobalObjects(
    v8::Handle<v8::ObjectTemplate> global_proxy_template) {
  Handle<JSObject> global_proxy(
      JSObject::cast(global_context()->global_proxy()));
  Handle<JSObject> js_global(JSObject::cast(global_context()->global()));

  if (!global_proxy_template.IsEmpty()) {
    // Configure the global proxy object.
    Handle<ObjectTemplateInfo> proxy_data =
        v8::Utils::OpenHandle(*global_proxy_template);
    if (!ConfigureApiObject(global_proxy, proxy_data)) return false;

    // Configure the inner global object.
    Handle<FunctionTemplateInfo> proxy_constructor(
        FunctionTemplateInfo::cast(proxy_data->constructor()));
    if (!proxy_constructor->prototype_template()->IsUndefined()) {
      Handle<ObjectTemplateInfo> inner_data(
          ObjectTemplateInfo::cast(proxy_constructor->prototype_template()));
      if (!ConfigureApiObject(js_global, inner_data)) return false;
    }
  }

  SetObjectPrototype(global_proxy, js_global);
  return true;
}


bool Genesis::ConfigureApiObject(Handle<JSObject> object,
    Handle<ObjectTemplateInfo> object_template) {
  ASSERT(!object_template.is_null());
  ASSERT(object->IsInstanceOf(
      FunctionTemplateInfo::cast(object_template->constructor())));

  bool pending_exception = false;
  Handle<JSObject> obj =
      Execution::InstantiateObject(object_template, &pending_exception);
  if (pending_exception) {
    ASSERT(Top::has_pending_exception());
    Top::clear_pending_exception();
    return false;
  }
  TransferObject(obj, object);
  return true;
}


void Genesis::TransferNamedProperties(Handle<JSObject> from,
                                      Handle<JSObject> to) {
  if (from->HasFastProperties()) {
    Handle<DescriptorArray> descs =
        Handle<DescriptorArray>(from->map()->instance_descriptors());
    int offset = 0;
    while (true) {
      // Iterating through the descriptors is not gc safe so we have to
      // store the value in a handle and create a new stream for each entry.
      DescriptorReader stream(*descs, offset);
      if (stream.eos()) break;
      // We have to read out the next offset before we do anything that may
      // cause a gc, since the DescriptorReader is not gc safe.
      offset = stream.next_position();
      PropertyDetails details = stream.GetDetails();
      switch (details.type()) {
        case FIELD: {
          HandleScope inner;
          Handle<String> key = Handle<String>(stream.GetKey());
          int index = stream.GetFieldIndex();
          Handle<Object> value = Handle<Object>(from->FastPropertyAt(index));
          SetProperty(to, key, value, details.attributes());
          break;
        }
        case CONSTANT_FUNCTION: {
          HandleScope inner;
          Handle<String> key = Handle<String>(stream.GetKey());
          Handle<JSFunction> fun =
              Handle<JSFunction>(stream.GetConstantFunction());
          SetProperty(to, key, fun, details.attributes());
          break;
        }
        case CALLBACKS: {
          LookupResult result;
          to->LocalLookup(stream.GetKey(), &result);
          // If the property is already there we skip it
          if (result.IsValid()) continue;
          HandleScope inner;
          Handle<DescriptorArray> inst_descs =
              Handle<DescriptorArray>(to->map()->instance_descriptors());
          Handle<String> key = Handle<String>(stream.GetKey());
          Handle<Object> entry = Handle<Object>(stream.GetCallbacksObject());
          inst_descs = Factory::CopyAppendProxyDescriptor(inst_descs,
                                                          key,
                                                          entry,
                                                          details.attributes());
          to->map()->set_instance_descriptors(*inst_descs);
          break;
        }
        case MAP_TRANSITION:
        case CONSTANT_TRANSITION:
        case NULL_DESCRIPTOR:
          // Ignore non-properties.
          break;
        case NORMAL:
          // Do not occur since the from object has fast properties.
        case INTERCEPTOR:
          // No element in instance descriptors have interceptor type.
          UNREACHABLE();
          break;
      }
    }
  } else {
    Handle<Dictionary> properties =
        Handle<Dictionary>(from->property_dictionary());
    int capacity = properties->Capacity();
    for (int i = 0; i < capacity; i++) {
      Object* raw_key(properties->KeyAt(i));
      if (properties->IsKey(raw_key)) {
        ASSERT(raw_key->IsString());
        // If the property is already there we skip it.
        LookupResult result;
        to->LocalLookup(String::cast(raw_key), &result);
        if (result.IsValid()) continue;
        // Set the property.
        Handle<String> key = Handle<String>(String::cast(raw_key));
        Handle<Object> value = Handle<Object>(properties->ValueAt(i));
        PropertyDetails details = properties->DetailsAt(i);
        SetProperty(to, key, value, details.attributes());
      }
    }
  }
}


void Genesis::TransferIndexedProperties(Handle<JSObject> from,
                                        Handle<JSObject> to) {
  // Cloning the elements array is sufficient.
  Handle<FixedArray> from_elements =
      Handle<FixedArray>(FixedArray::cast(from->elements()));
  Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements);
  to->set_elements(*to_elements);
}


void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) {
  HandleScope outer;

  ASSERT(!from->IsJSArray());
  ASSERT(!to->IsJSArray());

  TransferNamedProperties(from, to);
  TransferIndexedProperties(from, to);

  // Transfer the prototype (new map is needed).
  Handle<Map> old_to_map = Handle<Map>(to->map());
  Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
  new_to_map->set_prototype(from->map()->prototype());
  to->set_map(*new_to_map);
}


void Genesis::MakeFunctionInstancePrototypeWritable() {
  // Make a new function map so all future functions
  // will have settable and enumerable prototype properties.
  HandleScope scope;

  Handle<DescriptorArray> function_map_descriptors =
      ComputeFunctionInstanceDescriptor(false, true);
  Handle<Map> fm = Factory::CopyMapDropDescriptors(Top::function_map());
  fm->set_instance_descriptors(*function_map_descriptors);
  Top::context()->global_context()->set_function_map(*fm);
}


void Genesis::AddSpecialFunction(Handle<JSObject> prototype,
                                 const char* name,
                                 Handle<Code> code) {
  Handle<String> key = Factory::LookupAsciiSymbol(name);
  Handle<Object> value = Handle<Object>(prototype->GetProperty(*key));
  if (value->IsJSFunction()) {
    Handle<JSFunction> optimized = Factory::NewFunction(key,
                                                        JS_OBJECT_TYPE,
                                                        JSObject::kHeaderSize,
                                                        code,
                                                        false);
    optimized->shared()->DontAdaptArguments();
    int len = global_context()->special_function_table()->length();
    Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3);
    for (int index = 0; index < len; index++) {
      new_array->set(index,
                     global_context()->special_function_table()->get(index));
    }
    new_array->set(len+0, *prototype);
    new_array->set(len+1, *value);
    new_array->set(len+2, *optimized);
    global_context()->set_special_function_table(*new_array);
  }
}


void Genesis::BuildSpecialFunctionTable() {
  HandleScope scope;
  Handle<JSObject> global = Handle<JSObject>(global_context()->global());
  // Add special versions for Array.prototype.pop and push.
  Handle<JSFunction> function =
      Handle<JSFunction>(
          JSFunction::cast(global->GetProperty(Heap::Array_symbol())));
  Handle<JSObject> prototype =
      Handle<JSObject>(JSObject::cast(function->prototype()));
  AddSpecialFunction(prototype, "pop",
                     Handle<Code>(Builtins::builtin(Builtins::ArrayPop)));
  AddSpecialFunction(prototype, "push",
                     Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));
}


Genesis::Genesis(Handle<Object> global_object,
                 v8::Handle<v8::ObjectTemplate> global_template,
                 v8::ExtensionConfiguration* extensions) {
  // Link this genesis object into the stacked genesis chain. This
  // must be done before any early exits because the destructor
  // will always do unlinking.
  previous_ = current_;
  current_  = this;
  result_ = NULL;

  // If V8 hasn't been and cannot be initialized, just return.
  if (!V8::HasBeenSetup() && !V8::Initialize(NULL)) return;

  // Before creating the roots we must save the context and restore it
  // on all function exits.
  HandleScope scope;
  SaveContext context;

  CreateRoots(global_template, global_object);
  if (!InstallNatives()) return;

  MakeFunctionInstancePrototypeWritable();
  BuildSpecialFunctionTable();

  if (!ConfigureGlobalObjects(global_template)) return;

  if (!InstallExtensions(extensions)) return;

  if (!InstallSpecialObjects()) return;

  result_ = global_context_;
}


// Support for thread preemption.

// Reserve space for statics needing saving and restoring.
int Bootstrapper::ArchiveSpacePerThread() {
  return Genesis::ArchiveSpacePerThread();
}


// Archive statics that are thread local.
char* Bootstrapper::ArchiveState(char* to) {
  return Genesis::ArchiveState(to);
}


// Restore statics that are thread local.
char* Bootstrapper::RestoreState(char* from) {
  return Genesis::RestoreState(from);
}


// Reserve space for statics needing saving and restoring.
int Genesis::ArchiveSpacePerThread() {
  return sizeof(current_);
}


// Archive statics that are thread local.
char* Genesis::ArchiveState(char* to) {
  *reinterpret_cast<Genesis**>(to) = current_;
  current_ = NULL;
  return to + sizeof(current_);
}


// Restore statics that are thread local.
char* Genesis::RestoreState(char* from) {
  current_ = *reinterpret_cast<Genesis**>(from);
  return from + sizeof(current_);
}

} }  // namespace v8::internal
