// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/object.h"

#include "include/dart_api.h"
#include "platform/assert.h"
#include "vm/assembler.h"
#include "vm/bigint_operations.h"
#include "vm/bootstrap.h"
#include "vm/class_finalizer.h"
#include "vm/code_generator.h"
#include "vm/code_patcher.h"
#include "vm/compiler.h"
#include "vm/compiler_stats.h"
#include "vm/dart.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/datastream.h"
#include "vm/debuginfo.h"
#include "vm/deopt_instructions.h"
#include "vm/double_conversion.h"
#include "vm/exceptions.h"
#include "vm/growable_array.h"
#include "vm/heap.h"
#include "vm/object_store.h"
#include "vm/parser.h"
#include "vm/runtime_entry.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/timer.h"
#include "vm/unicode.h"

namespace dart {

DEFINE_FLAG(bool, generate_gdb_symbols, false,
    "Generate symbols of generated dart functions for debugging with GDB");
DEFINE_FLAG(bool, show_internal_names, false,
    "Show names of internal classes (e.g. \"OneByteString\") in error messages "
    "instead of showing the corresponding interface names (e.g. \"String\")");
DEFINE_FLAG(bool, trace_disabling_optimized_code, false,
    "Trace disabling optimized code.");
DECLARE_FLAG(bool, trace_compiler);
DECLARE_FLAG(bool, eliminate_type_checks);
DECLARE_FLAG(bool, enable_type_checks);

static const char* kGetterPrefix = "get:";
static const intptr_t kGetterPrefixLength = strlen(kGetterPrefix);
static const char* kSetterPrefix = "set:";
static const intptr_t kSetterPrefixLength = strlen(kSetterPrefix);

cpp_vtable Object::handle_vtable_ = 0;
cpp_vtable Object::builtin_vtables_[kNumPredefinedCids] = { 0 };
cpp_vtable Smi::handle_vtable_ = 0;

// These are initialized to a value that will force a illegal memory access if
// they are being used.
#if defined(RAW_NULL)
#error RAW_NULL should not be defined.
#endif
#define RAW_NULL kHeapObjectTag
RawObject* Object::null_ = reinterpret_cast<RawInstance*>(RAW_NULL);
RawArray* Object::empty_array_ = reinterpret_cast<RawArray*>(RAW_NULL);
RawInstance* Object::sentinel_ = reinterpret_cast<RawInstance*>(RAW_NULL);
RawInstance* Object::transition_sentinel_ =
    reinterpret_cast<RawInstance*>(RAW_NULL);
RawClass* Object::class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::null_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::dynamic_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::void_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::unresolved_class_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::type_arguments_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::instantiated_type_arguments_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::patch_class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::function_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::closure_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::redirection_data_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::field_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::literal_token_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::token_stream_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::script_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::library_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::library_prefix_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::namespace_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::code_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::instructions_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::pc_descriptors_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::stackmap_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::var_descriptors_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::exception_handlers_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::deopt_info_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::context_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::context_scope_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::icdata_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::subtypetestcache_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::api_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::language_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::unhandled_exception_class_ =
    reinterpret_cast<RawClass*>(RAW_NULL);
RawClass* Object::unwind_error_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
#undef RAW_NULL


// Takes a vm internal name and makes it suitable for external user.
//
// Examples:
//
// Internal getter and setter prefixes are changed:
//
//   get:foo -> foo
//   set:foo -> foo=
//
// Private name mangling is removed, possibly twice:
//
//   _ReceivePortImpl@6be832b -> _ReceivePortImpl
//   _ReceivePortImpl@6be832b._internal@6be832b -> +ReceivePortImpl._internal
//
// The trailing . on the default constructor name is dropped:
//
//   List. -> List
//
// And so forth:
//
//   get:foo@6be832b -> foo
//   _MyClass@6b3832b. -> _MyClass
//   _MyClass@6b3832b.named -> _MyClass.named
//
static RawString* IdentifierPrettyName(const String& name) {
  intptr_t len = name.Length();
  intptr_t start = 0;
  intptr_t at_pos = len;   // Position of '@' in the name.
  intptr_t dot_pos = len;  // Position of '.' in the name.
  bool is_setter = false;

  for (int i = 0; i < name.Length(); i++) {
    if (name.CharAt(i) == ':') {
      ASSERT(start == 0);
      if (name.CharAt(0) == 's') {
        is_setter = true;
      }
      start = i + 1;
    } else if (name.CharAt(i) == '@') {
      ASSERT(at_pos == len);
      at_pos = i;
    } else if (name.CharAt(i) == '.') {
      dot_pos = i;
      break;
    }
  }
  intptr_t limit = (at_pos < dot_pos ? at_pos : dot_pos);
  if (start == 0 && limit == len) {
    // This name is fine as it is.
    return name.raw();
  }

  const String& result =
      String::Handle(String::SubString(name, start, (limit - start)));

  // Look for a second '@' now to correctly handle names like
  // "_ReceivePortImpl@6be832b._internal@6be832b".
  at_pos = len;
  for (int i = dot_pos; i < name.Length(); i++) {
    if (name.CharAt(i) == '@') {
      ASSERT(at_pos == len);
      at_pos = i;
    }
  }

  intptr_t suffix_len = at_pos - dot_pos;
  if (suffix_len > 1) {
    // This is a named constructor.  Add the name back to the string.
    const String& suffix =
        String::Handle(String::SubString(name, dot_pos, suffix_len));
    return String::Concat(result, suffix);
  }

  if (is_setter) {
    // Setters need to end with '='.
    const String& suffix = String::Handle(Symbols::Equals());
    return String::Concat(result, suffix);
  }

  return result.raw();
}


template<typename type>
static bool IsSpecialCharacter(type value) {
  return ((value == '"') ||
          (value == '\n') ||
          (value == '\f') ||
          (value == '\b') ||
          (value == '\t') ||
          (value == '\v') ||
          (value == '\r'));
}


template<typename type>
static type SpecialCharacter(type value) {
  if (value == '"') {
    return '"';
  } else if (value == '\n') {
    return 'n';
  } else if (value == '\f') {
    return 'f';
  } else if (value == '\b') {
    return 'b';
  } else if (value == '\t') {
    return 't';
  } else if (value == '\v') {
    return 'v';
  } else if (value == '\r') {
    return 'r';
  }
  UNREACHABLE();
  return '\0';
}


void Object::InitOnce() {
  // TODO(iposva): NoGCScope needs to be added here.
  ASSERT(class_class() == null_);
  // Initialize the static vtable values.
  {
    Object fake_object;
    Smi fake_smi;
    Object::handle_vtable_ = fake_object.vtable();
    Smi::handle_vtable_ = fake_smi.vtable();
  }

  Isolate* isolate = Isolate::Current();
  Heap* heap = isolate->heap();
  // Allocate and initialize the null instance.
  // 'null_' must be the first object allocated as it is used in allocation to
  // clear the object.
  {
    uword address = heap->Allocate(Instance::InstanceSize(), Heap::kOld);
    null_ = reinterpret_cast<RawInstance*>(address + kHeapObjectTag);
    // The call below is using 'null_' to initialize itself.
    InitializeObject(address, kNullCid, Instance::InstanceSize());
  }

  // Initialize object_store empty array to null_ in order to be able to check
  // if the empty array was allocated (RAW_NULL is not available).
  empty_array_ = Array::null();

  Class& cls = Class::Handle();

  // Allocate and initialize the class class.
  {
    intptr_t size = Class::InstanceSize();
    uword address = heap->Allocate(size, Heap::kOld);
    class_class_ = reinterpret_cast<RawClass*>(address + kHeapObjectTag);
    InitializeObject(address, Class::kClassId, size);

    Class fake;
    // Initialization from Class::New<Class>.
    // Directly set raw_ to break a circular dependency: SetRaw will attempt
    // to lookup class class in the class table where it is not registered yet.
    cls.raw_ = class_class_;
    cls.set_handle_vtable(fake.vtable());
    cls.set_instance_size(Class::InstanceSize());
    cls.set_next_field_offset(Class::InstanceSize());
    cls.set_id(Class::kClassId);
    cls.raw_ptr()->state_bits_ = 0;
    cls.set_is_finalized();
    cls.raw_ptr()->type_arguments_instance_field_offset_ =
        Class::kNoTypeArguments;
    cls.raw_ptr()->num_native_fields_ = 0;
    cls.InitEmptyFields();
    isolate->class_table()->Register(cls);
  }

  // Allocate and initialize the null class.
  cls = Class::New<Instance>(kNullCid);
  cls.set_is_finalized();
  null_class_ = cls.raw();

  // Allocate and initialize the free list element class.
  cls = Class::New<FreeListElement::FakeInstance>(kFreeListElement);
  cls.set_is_finalized();

  // Allocate and initialize the sentinel values of Null class.
  {
    Instance& sentinel = Instance::Handle();
    sentinel ^=
        Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld);
    sentinel_ = sentinel.raw();

    Instance& transition_sentinel = Instance::Handle();
    transition_sentinel ^=
        Object::Allocate(kNullCid, Instance::InstanceSize(), Heap::kOld);
    transition_sentinel_ = transition_sentinel.raw();
  }

  cls = Class::New<Instance>(kDynamicCid);
  cls.set_is_finalized();
  cls.set_is_interface();
  dynamic_class_ = cls.raw();

  // Allocate the remaining VM internal classes.
  cls = Class::New<UnresolvedClass>();
  unresolved_class_class_ = cls.raw();

  cls = Class::New<Instance>(kVoidCid);
  cls.set_is_finalized();
  void_class_ = cls.raw();

  cls = Class::New<TypeArguments>();
  type_arguments_class_ = cls.raw();

  cls = Class::New<InstantiatedTypeArguments>();
  instantiated_type_arguments_class_ = cls.raw();

  cls = Class::New<PatchClass>();
  patch_class_class_ = cls.raw();

  cls = Class::New<Function>();
  function_class_ = cls.raw();

  cls = Class::New<ClosureData>();
  closure_data_class_ = cls.raw();

  cls = Class::New<RedirectionData>();
  redirection_data_class_ = cls.raw();

  cls = Class::New<Field>();
  field_class_ = cls.raw();

  cls = Class::New<LiteralToken>();
  literal_token_class_ = cls.raw();

  cls = Class::New<TokenStream>();
  token_stream_class_ = cls.raw();

  cls = Class::New<Script>();
  script_class_ = cls.raw();

  cls = Class::New<Library>();
  library_class_ = cls.raw();

  cls = Class::New<LibraryPrefix>();
  library_prefix_class_ = cls.raw();

  cls = Class::New<Namespace>();
  namespace_class_ = cls.raw();

  cls = Class::New<Code>();
  code_class_ = cls.raw();

  cls = Class::New<Instructions>();
  instructions_class_ = cls.raw();

  cls = Class::New<PcDescriptors>();
  pc_descriptors_class_ = cls.raw();

  cls = Class::New<Stackmap>();
  stackmap_class_ = cls.raw();

  cls = Class::New<LocalVarDescriptors>();
  var_descriptors_class_ = cls.raw();

  cls = Class::New<ExceptionHandlers>();
  exception_handlers_class_ = cls.raw();

  cls = Class::New<DeoptInfo>();
  deopt_info_class_ = cls.raw();

  cls = Class::New<Context>();
  context_class_ = cls.raw();

  cls = Class::New<ContextScope>();
  context_scope_class_ = cls.raw();

  cls = Class::New<ICData>();
  icdata_class_ = cls.raw();

  cls = Class::New<SubtypeTestCache>();
  subtypetestcache_class_ = cls.raw();

  cls = Class::New<ApiError>();
  api_error_class_ = cls.raw();

  cls = Class::New<LanguageError>();
  language_error_class_ = cls.raw();

  cls = Class::New<UnhandledException>();
  unhandled_exception_class_ = cls.raw();

  cls = Class::New<UnwindError>();
  unwind_error_class_ = cls.raw();

  ASSERT(class_class() != null_);

  // Pre-allocate the Array and OneByteString class in the vm isolate so that
  // we can create a symbol table and populate it with some frequently used
  // strings as symbols.
  cls = Class::New<Array>();
  isolate->object_store()->set_array_class(cls);
  cls = Class::NewStringClass(kOneByteStringCid);
  isolate->object_store()->set_one_byte_string_class(cls);
  cls = Class::NewStringClass(kTwoByteStringCid);
  isolate->object_store()->set_two_byte_string_class(cls);

  // Allocate and initialize the empty_array instance.
  {
    uword address = heap->Allocate(Array::InstanceSize(0), Heap::kOld);
    empty_array_ = reinterpret_cast<RawArray*>(address + kHeapObjectTag);
    InitializeObject(address, kArrayCid, Array::InstanceSize(0));
    empty_array_->ptr()->length_ = Smi::New(0);
  }
}


#define SET_CLASS_NAME(class_name, name)                                       \
  cls = class_name##_class();                                                  \
  str = Symbols::name();                                                       \
  cls.set_name(str);                                                           \

void Object::RegisterSingletonClassNames() {
  Class& cls = Class::Handle();
  String& str = String::Handle();

  // Set up names for all VM singleton classes.
  SET_CLASS_NAME(class, Class);
  SET_CLASS_NAME(null, Null);
  SET_CLASS_NAME(dynamic, Dynamic);
  SET_CLASS_NAME(void, Void);
  SET_CLASS_NAME(unresolved_class, UnresolvedClass);
  SET_CLASS_NAME(type_arguments, TypeArguments);
  SET_CLASS_NAME(instantiated_type_arguments, InstantiatedTypeArguments);
  SET_CLASS_NAME(patch_class, PatchClass);
  SET_CLASS_NAME(function, Function);
  SET_CLASS_NAME(closure_data, ClosureData);
  SET_CLASS_NAME(redirection_data, RedirectionData);
  SET_CLASS_NAME(field, Field);
  SET_CLASS_NAME(literal_token, LiteralToken);
  SET_CLASS_NAME(token_stream, TokenStream);
  SET_CLASS_NAME(script, Script);
  SET_CLASS_NAME(library, LibraryClass);
  SET_CLASS_NAME(library_prefix, LibraryPrefix);
  SET_CLASS_NAME(namespace, Namespace);
  SET_CLASS_NAME(code, Code);
  SET_CLASS_NAME(instructions, Instructions);
  SET_CLASS_NAME(pc_descriptors, PcDescriptors);
  SET_CLASS_NAME(stackmap, Stackmap);
  SET_CLASS_NAME(var_descriptors, LocalVarDescriptors);
  SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
  SET_CLASS_NAME(deopt_info, DeoptInfo);
  SET_CLASS_NAME(context, Context);
  SET_CLASS_NAME(context_scope, ContextScope);
  SET_CLASS_NAME(icdata, ICData);
  SET_CLASS_NAME(subtypetestcache, SubtypeTestCache);
  SET_CLASS_NAME(api_error, ApiError);
  SET_CLASS_NAME(language_error, LanguageError);
  SET_CLASS_NAME(unhandled_exception, UnhandledException);
  SET_CLASS_NAME(unwind_error, UnwindError);

  // Set up names for object array and one byte string class which are
  // pre-allocated in the vm isolate also.
  cls = Dart::vm_isolate()->object_store()->array_class();
  str = Symbols::ObjectArray();
  cls.set_name(str);
  cls = Dart::vm_isolate()->object_store()->one_byte_string_class();
  str = Symbols::OneByteString();
  cls.set_name(str);
}


// Make unused space in an object whose type has been transformed safe
// for traversing during GC.
// The unused part of the transformed object is marked as an Array
// object or a regular Object so that it can be traversed during garbage
// collection.
void Object::MakeUnusedSpaceTraversable(const Object& obj,
                                        intptr_t original_size,
                                        intptr_t used_size) {
  ASSERT(Isolate::Current()->no_gc_scope_depth() > 0);
  ASSERT(!obj.IsNull());
  ASSERT(original_size >= used_size);
  if (original_size > used_size) {
    intptr_t leftover_size = original_size - used_size;

    uword addr = RawObject::ToAddr(obj.raw()) + used_size;
    if (leftover_size >= Array::InstanceSize(0)) {
      // As we have enough space to use an array object, update the leftover
      // space as an Array object.
      RawArray* raw = reinterpret_cast<RawArray*>(RawObject::FromAddr(addr));
      uword tags = 0;
      tags = RawObject::SizeTag::update(leftover_size, tags);
      tags = RawObject::ClassIdTag::update(kArrayCid, tags);
      raw->ptr()->tags_ = tags;
      intptr_t leftover_len =
          ((leftover_size - Array::InstanceSize(0)) / kWordSize);
      ASSERT(Array::InstanceSize(leftover_len) == leftover_size);
      raw->ptr()->tags_ = tags;
      raw->ptr()->length_ = Smi::New(leftover_len);
    } else {
      // Update the leftover space as a basic object.
      ASSERT(leftover_size == Object::InstanceSize());
      RawObject* raw =
          reinterpret_cast<RawObject*>(RawObject::FromAddr(addr));
      uword tags = 0;
      tags = RawObject::SizeTag::update(leftover_size, tags);
      tags = RawObject::ClassIdTag::update(kInstanceCid, tags);
      raw->ptr()->tags_ = tags;
    }
  }
}


void Object::RegisterClass(const Class& cls,
                           const String& name,
                           const Library& lib) {
  ASSERT(name.Length() > 0);
  ASSERT(name.CharAt(0) != '_');
  cls.set_name(name);
  lib.AddClass(cls);
}


void Object::RegisterPrivateClass(const Class& cls,
                                  const String& public_class_name,
                                  const Library& lib) {
  ASSERT(public_class_name.Length() > 0);
  ASSERT(public_class_name.CharAt(0) == '_');
  String& str = String::Handle();
  str = lib.PrivateName(public_class_name);
  cls.set_name(str);
  lib.AddClass(cls);
}


RawError* Object::Init(Isolate* isolate) {
  TIMERSCOPE(time_bootstrap);
  ObjectStore* object_store = isolate->object_store();

  Class& cls = Class::Handle();
  Type& type = Type::Handle();
  Array& array = Array::Handle();

  // All RawArray fields will be initialized to an empty array, therefore
  // initialize array class first.
  cls = Class::New<Array>();
  object_store->set_array_class(cls);

  // Array and ImmutableArray are the only VM classes that are parameterized.
  // Since they are pre-finalized, CalculateFieldOffsets() is not called, so we
  // need to set the offset of their type_arguments_ field, which is explicitly
  // declared in RawArray.
  cls.set_type_arguments_instance_field_offset(Array::type_arguments_offset());

  // Set up the growable object array class (Has to be done after the array
  // class is setup as one of its field is an array object).
  cls = Class::New<GrowableObjectArray>();
  object_store->set_growable_object_array_class(cls);
  cls.set_type_arguments_instance_field_offset(
      GrowableObjectArray::type_arguments_offset());

  // canonical_type_arguments_ are NULL terminated.
  array = Array::New(4);
  object_store->set_canonical_type_arguments(array);

  // Setup type class early in the process.
  cls = Class::New<Type>();
  object_store->set_type_class(cls);

  cls = Class::New<TypeParameter>();
  object_store->set_type_parameter_class(cls);

  // Pre-allocate the OneByteString class needed by the symbol table.
  cls = Class::NewStringClass(kOneByteStringCid);
  object_store->set_one_byte_string_class(cls);

  // Pre-allocate the TwoByteString class needed by the symbol table.
  cls = Class::NewStringClass(kTwoByteStringCid);
  object_store->set_two_byte_string_class(cls);

  // Setup the symbol table for the symbols created in the isolate.
  Symbols::SetupSymbolTable(isolate);

  // Set up the libraries array before initializing the core library.
  const GrowableObjectArray& libraries =
      GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
  object_store->set_libraries(libraries);

  // Basic infrastructure has been setup, initialize the class dictionary.
  Library::InitCoreLibrary(isolate);
  Library& core_lib = Library::Handle(Library::CoreLibrary());
  ASSERT(!core_lib.IsNull());

  const GrowableObjectArray& pending_classes =
      GrowableObjectArray::Handle(GrowableObjectArray::New(Heap::kOld));
  object_store->set_pending_classes(pending_classes);

  Context& context = Context::Handle(Context::New(0, Heap::kOld));
  object_store->set_empty_context(context);

  // Now that the symbol table is initialized and that the core dictionary as
  // well as the core implementation dictionary have been setup, preallocate
  // remaining classes and register them by name in the dictionaries.
  String& name = String::Handle();
  cls = Class::New<Bool>();
  object_store->set_bool_class(cls);
  name = Symbols::Bool();
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = object_store->array_class();  // Was allocated above.
  name = Symbols::ObjectArray();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  // We cannot use NewNonParameterizedType(cls), because Array is parameterized.
  type ^= Type::New(Object::Handle(cls.raw()),
                    TypeArguments::Handle(),
                    Scanner::kDummyTokenIndex);
  type.set_is_finalized_instantiated();
  type ^= type.Canonicalize();
  object_store->set_array_type(type);

  cls = object_store->growable_object_array_class();  // Was allocated above.
  name = Symbols::GrowableObjectArray();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<ImmutableArray>();
  object_store->set_immutable_array_class(cls);
  cls.set_type_arguments_instance_field_offset(Array::type_arguments_offset());
  ASSERT(object_store->immutable_array_class() != object_store->array_class());
  name = Symbols::ImmutableArray();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = object_store->one_byte_string_class();  // Was allocated above.
  name = Symbols::OneByteString();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = object_store->two_byte_string_class();  // Was allocated above.
  name = Symbols::TwoByteString();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::NewStringClass(kExternalOneByteStringCid);
  object_store->set_external_one_byte_string_class(cls);
  name = Symbols::ExternalOneByteString();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::NewStringClass(kExternalTwoByteStringCid);
  object_store->set_external_two_byte_string_class(cls);
  name = Symbols::ExternalTwoByteString();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<Stacktrace>();
  object_store->set_stacktrace_class(cls);
  name = Symbols::Stacktrace();
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  // Super type set below, after Object is allocated.

  cls = Class::New<JSRegExp>();
  object_store->set_jsregexp_class(cls);
  name = Symbols::JSSyntaxRegExp();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  // Initialize the base interfaces used by the core VM classes.
  const Script& script = Script::Handle(Bootstrap::LoadCoreScript(false));

  // Allocate and initialize the pre-allocated classes in the core library.
  cls = Class::New<Instance>(kInstanceCid);
  object_store->set_object_class(cls);
  name = Symbols::Object();
  cls.set_name(name);
  cls.set_script(script);
  cls.set_is_prefinalized();
  core_lib.AddClass(cls);
  pending_classes.Add(cls, Heap::kOld);
  type = Type::NewNonParameterizedType(cls);
  object_store->set_object_type(type);

  cls = object_store->type_class();
  name = Symbols::Type();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = object_store->type_parameter_class();
  name = Symbols::TypeParameter();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<Integer>();
  object_store->set_integer_implementation_class(cls);
  name = Symbols::IntegerImplementation();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<Smi>();
  object_store->set_smi_class(cls);
  name = Symbols::Smi();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<Mint>();
  object_store->set_mint_class(cls);
  name = Symbols::Mint();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<Bigint>();
  object_store->set_bigint_class(cls);
  name = Symbols::Bigint();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<Double>();
  object_store->set_double_class(cls);
  name = Symbols::Double();
  RegisterPrivateClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);

  cls = Class::New<WeakProperty>();
  object_store->set_weak_property_class(cls);
  name = Symbols::_WeakProperty();
  RegisterPrivateClass(cls, name, core_lib);

  Library::InitScalarlistLibrary(isolate);
  Library& scalarlist_lib = Library::Handle(Library::ScalarlistLibrary());

  cls = Class::New<Int8Array>();
  object_store->set_int8_array_class(cls);
  name = Symbols::_Int8Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Uint8Array>();
  object_store->set_uint8_array_class(cls);
  name = Symbols::_Uint8Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Int16Array>();
  object_store->set_int16_array_class(cls);
  name = Symbols::_Int16Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Uint16Array>();
  object_store->set_uint16_array_class(cls);
  name = Symbols::_Uint16Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Int32Array>();
  object_store->set_int32_array_class(cls);
  name = Symbols::_Int32Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Uint32Array>();
  object_store->set_uint32_array_class(cls);
  name = Symbols::_Uint32Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Int64Array>();
  object_store->set_int64_array_class(cls);
  name = Symbols::_Int64Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Uint64Array>();
  object_store->set_uint64_array_class(cls);
  name = Symbols::_Uint64Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Float32Array>();
  object_store->set_float32_array_class(cls);
  name = Symbols::_Float32Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<Float64Array>();
  object_store->set_float64_array_class(cls);
  name = Symbols::_Float64Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalInt8Array>();
  object_store->set_external_int8_array_class(cls);
  name = Symbols::_ExternalInt8Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalUint8Array>();
  object_store->set_external_uint8_array_class(cls);
  name = Symbols::_ExternalUint8Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalInt16Array>();
  object_store->set_external_int16_array_class(cls);
  name = Symbols::_ExternalInt16Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalUint16Array>();
  object_store->set_external_uint16_array_class(cls);
  name = Symbols::_ExternalUint16Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalInt32Array>();
  object_store->set_external_int32_array_class(cls);
  name = Symbols::_ExternalInt32Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalUint32Array>();
  object_store->set_external_uint32_array_class(cls);
  name = Symbols::_ExternalUint32Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalInt64Array>();
  object_store->set_external_int64_array_class(cls);
  name = Symbols::_ExternalInt64Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalUint64Array>();
  object_store->set_external_uint64_array_class(cls);
  name = Symbols::_ExternalUint64Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalFloat32Array>();
  object_store->set_external_float32_array_class(cls);
  name = Symbols::_ExternalFloat32Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  cls = Class::New<ExternalFloat64Array>();
  object_store->set_external_float64_array_class(cls);
  name = Symbols::_ExternalFloat64Array();
  RegisterPrivateClass(cls, name, scalarlist_lib);

  // Set the super type of class Stacktrace to Object type so that the
  // 'toString' method is implemented.
  cls = object_store->stacktrace_class();
  cls.set_super_type(type);

  // Note: The abstract class Function is represented by VM class
  // DartFunction, not VM class Function.
  name = Symbols::Function();
  cls = Class::New<DartFunction>();
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  type = Type::NewNonParameterizedType(cls);
  object_store->set_function_type(type);

  cls = Class::New<Number>();
  name = Symbols::Number();
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  type = Type::NewNonParameterizedType(cls);
  object_store->set_number_type(type);

  name = Symbols::New("int");
  cls = Class::New<Instance>(name, script, Scanner::kDummyTokenIndex);
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  type = Type::NewNonParameterizedType(cls);
  object_store->set_int_type(type);

  name = Symbols::New("double");
  cls = Class::New<Instance>(name, script, Scanner::kDummyTokenIndex);
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  type = Type::NewNonParameterizedType(cls);
  object_store->set_double_type(type);

  name = Symbols::New("String");
  cls = Class::New<Instance>(name, script, Scanner::kDummyTokenIndex);
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  type = Type::NewNonParameterizedType(cls);
  object_store->set_string_type(type);

  name = Symbols::New("List");
  cls = Class::New<Instance>(name, script, Scanner::kDummyTokenIndex);
  RegisterClass(cls, name, core_lib);
  pending_classes.Add(cls, Heap::kOld);
  object_store->set_list_class(cls);

  cls = object_store->bool_class();
  type = Type::NewNonParameterizedType(cls);
  object_store->set_bool_type(type);

  cls = object_store->smi_class();
  type = Type::NewNonParameterizedType(cls);
  object_store->set_smi_type(type);

  cls = object_store->mint_class();
  type = Type::NewNonParameterizedType(cls);
  object_store->set_mint_type(type);

  // The classes 'Null' and 'void' are not registered in the class dictionary,
  // because their names are reserved keywords. Their names are not heap
  // allocated, because the classes reside in the VM isolate.
  // The corresponding types are stored in the object store.
  cls = null_class();
  type = Type::NewNonParameterizedType(cls);
  object_store->set_null_type(type);

  cls = void_class();
  type = Type::NewNonParameterizedType(cls);
  object_store->set_void_type(type);

  // The class 'dynamic' is registered in the class dictionary because its name
  // is a built-in identifier, rather than a reserved keyword. Its name is not
  // heap allocated, because the class resides in the VM isolate.
  // The corresponding type, the "unknown type", is stored in the object store.
  cls = dynamic_class();
  type = Type::NewNonParameterizedType(cls);
  object_store->set_dynamic_type(type);

  // Allocate pre-initialized values.
  Bool& bool_value = Bool::Handle();
  bool_value = Bool::New(true);
  object_store->set_true_value(bool_value);
  bool_value = Bool::New(false);
  object_store->set_false_value(bool_value);

  // Setup some default native field classes which can be extended for
  // specifying native fields in dart classes.
  Library::InitNativeWrappersLibrary(isolate);
  ASSERT(isolate->object_store()->native_wrappers_library() != Library::null());

  // Finish the initialization by compiling the bootstrap scripts containing the
  // base interfaces and the implementation of the internal classes.
  Error& error = Error::Handle();
  error = Bootstrap::Compile(core_lib, script);
  if (!error.IsNull()) {
    return error.raw();
  }
  Script& patch_script = Script::Handle(Bootstrap::LoadCoreScript(true));
  error = core_lib.Patch(patch_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  const Script& collection_script =
      Script::Handle(Bootstrap::LoadCollectionScript(false));
  const Library& collection_lib =
      Library::Handle(Library::CollectionLibrary());
  ASSERT(!collection_lib.IsNull());
  error = Bootstrap::Compile(collection_lib, collection_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  const Script& math_script = Script::Handle(Bootstrap::LoadMathScript(false));
  const Library& math_lib = Library::Handle(Library::MathLibrary());
  ASSERT(!math_lib.IsNull());
  error = Bootstrap::Compile(math_lib, math_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  patch_script = Bootstrap::LoadMathScript(true);
  error = math_lib.Patch(patch_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  const Script& isolate_script = Script::Handle(
      Bootstrap::LoadIsolateScript(false));
  Library::InitIsolateLibrary(isolate);
  const Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
  ASSERT(!isolate_lib.IsNull());
  error = Bootstrap::Compile(isolate_lib, isolate_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  patch_script = Bootstrap::LoadIsolateScript(true);
  error = isolate_lib.Patch(patch_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  const Script& mirrors_script = Script::Handle(
      Bootstrap::LoadMirrorsScript(false));
  Library::InitMirrorsLibrary(isolate);
  const Library& mirrors_lib = Library::Handle(Library::MirrorsLibrary());
  ASSERT(!mirrors_lib.IsNull());
  error = Bootstrap::Compile(mirrors_lib, mirrors_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  patch_script = Bootstrap::LoadMirrorsScript(true);
  error = mirrors_lib.Patch(patch_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  const Script& scalarlist_script = Script::Handle(
      Bootstrap::LoadScalarlistScript(false));
  ASSERT(!scalarlist_lib.IsNull());
  error = Bootstrap::Compile(scalarlist_lib, scalarlist_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  patch_script = Bootstrap::LoadScalarlistScript(true);
  error = scalarlist_lib.Patch(patch_script);
  if (!error.IsNull()) {
    return error.raw();
  }
  Bootstrap::SetupNativeResolver();

  // Remove the Object superclass cycle by setting the super type to null (not
  // to the type of null).
  cls = object_store->object_class();
  cls.set_super_type(Type::Handle());

  ClassFinalizer::VerifyBootstrapClasses();
  return Error::null();
}


void Object::InitFromSnapshot(Isolate* isolate) {
  TIMERSCOPE(time_bootstrap);
  ObjectStore* object_store = isolate->object_store();

  Class& cls = Class::Handle();

  // Set up empty classes in the object store, these will get
  // initialized correctly when we read from the snapshot.
  // This is done to allow bootstrapping of reading classes from the snapshot.
  cls = Class::New<Instance>(kInstanceCid);
  object_store->set_object_class(cls);

  cls = Class::New<Type>();
  object_store->set_type_class(cls);

  cls = Class::New<TypeParameter>();
  object_store->set_type_parameter_class(cls);

  cls = Class::New<Array>();
  object_store->set_array_class(cls);

  cls = Class::New<ImmutableArray>();
  object_store->set_immutable_array_class(cls);

  cls = Class::New<GrowableObjectArray>();
  object_store->set_growable_object_array_class(cls);

  cls = Class::New<Int8Array>();
  object_store->set_int8_array_class(cls);

  cls = Class::New<Uint8Array>();
  object_store->set_uint8_array_class(cls);

  cls = Class::New<Int16Array>();
  object_store->set_int16_array_class(cls);

  cls = Class::New<Uint16Array>();
  object_store->set_uint16_array_class(cls);

  cls = Class::New<Int32Array>();
  object_store->set_int32_array_class(cls);

  cls = Class::New<Uint32Array>();
  object_store->set_uint32_array_class(cls);

  cls = Class::New<Int64Array>();
  object_store->set_int64_array_class(cls);

  cls = Class::New<Uint64Array>();
  object_store->set_uint64_array_class(cls);

  cls = Class::New<Float32Array>();
  object_store->set_float32_array_class(cls);

  cls = Class::New<Float64Array>();
  object_store->set_float64_array_class(cls);

  cls = Class::New<ExternalInt8Array>();
  object_store->set_external_int8_array_class(cls);

  cls = Class::New<ExternalUint8Array>();
  object_store->set_external_uint8_array_class(cls);

  cls = Class::New<ExternalInt16Array>();
  object_store->set_external_int16_array_class(cls);

  cls = Class::New<ExternalUint16Array>();
  object_store->set_external_uint16_array_class(cls);

  cls = Class::New<ExternalInt32Array>();
  object_store->set_external_int32_array_class(cls);

  cls = Class::New<ExternalUint32Array>();
  object_store->set_external_uint32_array_class(cls);

  cls = Class::New<ExternalInt64Array>();
  object_store->set_external_int64_array_class(cls);

  cls = Class::New<ExternalUint64Array>();
  object_store->set_external_uint64_array_class(cls);

  cls = Class::New<ExternalFloat32Array>();
  object_store->set_external_float32_array_class(cls);

  cls = Class::New<ExternalFloat64Array>();
  object_store->set_external_float64_array_class(cls);

  cls = Class::New<Integer>();
  object_store->set_integer_implementation_class(cls);

  cls = Class::New<Smi>();
  object_store->set_smi_class(cls);

  cls = Class::New<Mint>();
  object_store->set_mint_class(cls);

  cls = Class::New<Double>();
  object_store->set_double_class(cls);

  cls = Class::New<Bigint>();
  object_store->set_bigint_class(cls);

  cls = Class::NewStringClass(kOneByteStringCid);
  object_store->set_one_byte_string_class(cls);

  cls = Class::NewStringClass(kTwoByteStringCid);
  object_store->set_two_byte_string_class(cls);

  cls = Class::NewStringClass(kExternalOneByteStringCid);
  object_store->set_external_one_byte_string_class(cls);

  cls = Class::NewStringClass(kExternalTwoByteStringCid);
  object_store->set_external_two_byte_string_class(cls);

  cls = Class::New<Bool>();
  object_store->set_bool_class(cls);

  cls = Class::New<Stacktrace>();
  object_store->set_stacktrace_class(cls);

  cls = Class::New<JSRegExp>();
  object_store->set_jsregexp_class(cls);

  // Some classes are not stored in the object store. Yet we still need to
  // create their Class object so that they get put into the class_table
  // (as a side effect of Class::New()).
  cls = Class::New<DartFunction>();
  cls = Class::New<Number>();

  cls = Class::New<WeakProperty>();
  object_store->set_weak_property_class(cls);

  // Allocate pre-initialized values.
  Bool& bool_value = Bool::Handle();
  bool_value = Bool::New(true);
  object_store->set_true_value(bool_value);
  bool_value = Bool::New(false);
  object_store->set_false_value(bool_value);
}


void Object::Print() const {
  OS::Print("%s\n", ToCString());
}


RawString* Object::DictionaryName() const {
  return String::null();
}


void Object::InitializeObject(uword address, intptr_t class_id, intptr_t size) {
  // TODO(iposva): Get a proper halt instruction from the assembler which
  // would be needed here for code objects.
  uword initial_value = reinterpret_cast<uword>(null_);
  uword cur = address;
  uword end = address + size;
  while (cur < end) {
    *reinterpret_cast<uword*>(cur) = initial_value;
    cur += kWordSize;
  }
  uword tags = 0;
  ASSERT(class_id != kIllegalCid);
  tags = RawObject::ClassIdTag::update(class_id, tags);
  tags = RawObject::SizeTag::update(size, tags);
  reinterpret_cast<RawObject*>(address)->tags_ = tags;
}


RawObject* Object::Allocate(intptr_t cls_id,
                            intptr_t size,
                            Heap::Space space) {
  ASSERT(Utils::IsAligned(size, kObjectAlignment));
  Isolate* isolate = Isolate::Current();
  Heap* heap = isolate->heap();

  uword address = heap->Allocate(size, space);
  if (address == 0) {
    // Use the preallocated out of memory exception to avoid calling
    // into dart code or allocating any code.
    const Instance& exception =
        Instance::Handle(isolate->object_store()->out_of_memory());
    Exceptions::Throw(exception);
    UNREACHABLE();
  }
  NoGCScope no_gc;
  InitializeObject(address, cls_id, size);
  RawObject* raw_obj = reinterpret_cast<RawObject*>(address + kHeapObjectTag);
  ASSERT(cls_id == RawObject::ClassIdTag::decode(raw_obj->ptr()->tags_));
  return raw_obj;
}


class StoreBufferObjectPointerVisitor : public ObjectPointerVisitor {
 public:
  explicit StoreBufferObjectPointerVisitor(Isolate* isolate) :
      ObjectPointerVisitor(isolate) {
  }
  void VisitPointers(RawObject** first, RawObject** last) {
    for (RawObject** curr = first; curr <= last; ++curr) {
      if ((*curr)->IsNewObject()) {
        uword ptr = reinterpret_cast<uword>(curr);
        isolate()->store_buffer()->AddPointer(ptr);
      }
    }
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(StoreBufferObjectPointerVisitor);
};


RawObject* Object::Clone(const Object& src, Heap::Space space) {
  const Class& cls = Class::Handle(src.clazz());
  intptr_t size = src.raw()->Size();
  RawObject* raw_obj = Object::Allocate(cls.id(), size, space);
  NoGCScope no_gc;
  memmove(raw_obj->ptr(), src.raw()->ptr(), size);
  if (space == Heap::kOld) {
    StoreBufferObjectPointerVisitor visitor(Isolate::Current());
    raw_obj->VisitPointers(&visitor);
  }
  return raw_obj;
}


RawString* Class::Name() const {
  ASSERT(raw_ptr()->name_ != String::null());
  return raw_ptr()->name_;
}


RawString* Class::UserVisibleName() const {
  if (FLAG_show_internal_names) {
    return Name();
  }
  switch (id()) {
    case kIntegerCid:
    case kSmiCid:
    case kMintCid:
    case kBigintCid:
      return Symbols::New("int");
    case kDoubleCid:
      return Symbols::New("double");
    case kOneByteStringCid:
    case kTwoByteStringCid:
    case kExternalOneByteStringCid:
    case kExternalTwoByteStringCid:
      return Symbols::New("String");
    case kArrayCid:
    case kImmutableArrayCid:
    case kGrowableObjectArrayCid:
      return Symbols::New("List");
    case kInt8ArrayCid:
    case kExternalInt8ArrayCid:
      return Symbols::New("Int8List");
    case kUint8ArrayCid:
    case kExternalUint8ArrayCid:
      return Symbols::New("Uint8List");
    case kInt16ArrayCid:
    case kExternalInt16ArrayCid:
      return Symbols::New("Int16List");
    case kUint16ArrayCid:
    case kExternalUint16ArrayCid:
      return Symbols::New("Uint16List");
    case kInt32ArrayCid:
    case kExternalInt32ArrayCid:
      return Symbols::New("Int32List");
    case kUint32ArrayCid:
    case kExternalUint32ArrayCid:
      return Symbols::New("Uint32List");
    case kInt64ArrayCid:
    case kExternalInt64ArrayCid:
      return Symbols::New("Int64List");
    case kUint64ArrayCid:
    case kExternalUint64ArrayCid:
      return Symbols::New("Uint64List");
    case kFloat32ArrayCid:
    case kExternalFloat32ArrayCid:
      return Symbols::New("Float32List");
    case kFloat64ArrayCid:
    case kExternalFloat64ArrayCid:
      return Symbols::New("Float64List");
    default:
      if (!IsSignatureClass()) {
        const String& name = String::Handle(Name());
        return IdentifierPrettyName(name);
      } else {
        return Name();
      }
  }
  UNREACHABLE();
}


RawType* Class::SignatureType() const {
  ASSERT(IsSignatureClass());
  const Function& function = Function::Handle(signature_function());
  ASSERT(!function.IsNull());
  if (function.signature_class() != raw()) {
    // This class is a function type alias. Return the canonical signature type.
    const Class& canonical_class = Class::Handle(function.signature_class());
    return canonical_class.SignatureType();
  }
  // Return the first canonical signature type if already computed.
  const Array& signature_types = Array::Handle(canonical_types());
  // The canonical_types array is initialized to the empty array.
  ASSERT(!signature_types.IsNull());
  if (signature_types.Length() > 0) {
    // At most one signature type per signature class.
    ASSERT(signature_types.Length() == 1);
    Type& signature_type = Type::Handle();
    signature_type ^= signature_types.At(0);
    ASSERT(!signature_type.IsNull());
    return signature_type.raw();
  }
  // A signature class extends class Instance and is parameterized in the same
  // way as the owner class of its non-static signature function.
  // It is not type parameterized if its signature function is static.
  // See Class::NewSignatureClass() for the setup of its type parameters.
  // During type finalization, the type arguments of the super class of the
  // owner class of its signature function will be prepended to the type
  // argument vector. Therefore, we only need to set the type arguments
  // matching the type parameters here.
  const TypeArguments& signature_type_arguments =
      TypeArguments::Handle(type_parameters());
  const Type& signature_type = Type::Handle(
      Type::New(*this, signature_type_arguments, token_pos()));

  // Return the still unfinalized signature type.
  ASSERT(!signature_type.IsFinalized());
  return signature_type.raw();
}


template <class FakeObject>
RawClass* Class::New() {
  ASSERT(Object::class_class() != Class::null());
  Class& result = Class::Handle();
  {
    RawObject* raw = Object::Allocate(Class::kClassId,
                                      Class::InstanceSize(),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
  }
  FakeObject fake;
  result.set_handle_vtable(fake.vtable());
  result.set_instance_size(FakeObject::InstanceSize());
  result.set_next_field_offset(FakeObject::InstanceSize());
  ASSERT((FakeObject::kClassId != kInstanceCid));
  result.set_id(FakeObject::kClassId);
  result.raw_ptr()->state_bits_ = 0;
  // VM backed classes are almost ready: run checks and resolve class
  // references, but do not recompute size.
  result.set_is_prefinalized();
  result.raw_ptr()->type_arguments_instance_field_offset_ = kNoTypeArguments;
  result.raw_ptr()->num_native_fields_ = 0;
  result.raw_ptr()->token_pos_ = Scanner::kDummyTokenIndex;
  result.InitEmptyFields();
  Isolate::Current()->class_table()->Register(result);
  return result.raw();
}


// Initialize class fields of type Array with empty array.
void Class::InitEmptyFields() {
  if (Object::empty_array() == Array::null()) {
    // The empty array has not been initialized yet.
    return;
  }
  StorePointer(&raw_ptr()->interfaces_, Object::empty_array());
  StorePointer(&raw_ptr()->constants_, Object::empty_array());
  StorePointer(&raw_ptr()->canonical_types_, Object::empty_array());
  StorePointer(&raw_ptr()->functions_, Object::empty_array());
  StorePointer(&raw_ptr()->fields_, Object::empty_array());
}


bool Class::HasInstanceFields() const {
  const Array& field_array = Array::Handle(fields());
  Field& field = Field::Handle();
  for (intptr_t i = 0; i < field_array.Length(); ++i) {
    field ^= field_array.At(i);
    if (!field.is_static()) {
      return true;
    }
  }
  return false;
}

void Class::SetFunctions(const Array& value) const {
  ASSERT(!value.IsNull());
#if defined(DEBUG)
  // Verify that all the functions in the array have this class as owner.
  Function& func = Function::Handle();
  intptr_t len = value.Length();
  for (intptr_t i = 0; i < len; i++) {
    func ^= value.At(i);
    ASSERT(func.Owner() == raw());
  }
#endif
  StorePointer(&raw_ptr()->functions_, value.raw());
}


void Class::AddClosureFunction(const Function& function) const {
  GrowableObjectArray& closures =
      GrowableObjectArray::Handle(raw_ptr()->closure_functions_);
  if (closures.IsNull()) {
    closures = GrowableObjectArray::New(4);
    StorePointer(&raw_ptr()->closure_functions_, closures.raw());
  }
  ASSERT(function.IsNonImplicitClosureFunction());
  closures.Add(function);
}


// Lookup the innermost closure function that contains token at token_pos.
RawFunction* Class::LookupClosureFunction(intptr_t token_pos) const {
  if (raw_ptr()->closure_functions_ == GrowableObjectArray::null()) {
    return Function::null();
  }
  const GrowableObjectArray& closures =
      GrowableObjectArray::Handle(raw_ptr()->closure_functions_);
  Function& closure = Function::Handle();
  intptr_t num_closures = closures.Length();
  intptr_t best_fit_token_pos = -1;
  intptr_t best_fit_index = -1;
  for (intptr_t i = 0; i < num_closures; i++) {
    closure ^= closures.At(i);
    ASSERT(!closure.IsNull());
    if ((closure.token_pos() <= token_pos) &&
        (token_pos < closure.end_token_pos()) &&
        (best_fit_token_pos < closure.token_pos())) {
      best_fit_index = i;
      best_fit_token_pos = closure.token_pos();
    }
  }
  closure = Function::null();
  if (best_fit_index >= 0) {
    closure ^= closures.At(best_fit_index);
  }
  return closure.raw();
}


void Class::set_signature_function(const Function& value) const {
  ASSERT(value.IsClosureFunction() || value.IsSignatureFunction());
  StorePointer(&raw_ptr()->signature_function_, value.raw());
}


void Class::set_class_state(RawClass::ClassState state) const {
  ASSERT((state == RawClass::kAllocated) ||
         (state == RawClass::kPreFinalized) ||
         (state == RawClass::kFinalized));
  set_state_bits(StateBits::update(state, raw_ptr()->state_bits_));
}


void Class::set_state_bits(intptr_t bits) const {
  raw_ptr()->state_bits_ = static_cast<uint8_t>(bits);
}


void Class::set_library(const Library& value) const {
  StorePointer(&raw_ptr()->library_, value.raw());
}


void Class::set_type_parameters(const TypeArguments& value) const {
  StorePointer(&raw_ptr()->type_parameters_, value.raw());
}


intptr_t Class::NumTypeParameters() const {
  const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
  if (type_params.IsNull()) {
    return 0;
  } else {
    return type_params.Length();
  }
}


intptr_t Class::NumTypeArguments() const {
  // To work properly, this call requires the super class of this class to be
  // resolved, which is checked by the SuperClass() call.
  Class& cls = Class::Handle(raw());
  if (IsSignatureClass()) {
    const Function& signature_fun = Function::Handle(signature_function());
    if (!signature_fun.is_static() &&
        !signature_fun.HasInstantiatedSignature()) {
      cls = signature_fun.Owner();
    }
  }
  intptr_t num_type_args = NumTypeParameters();
  const Class& superclass = Class::Handle(cls.SuperClass());
  // Object is its own super class during bootstrap.
  if (!superclass.IsNull() && (superclass.raw() != raw())) {
    num_type_args += superclass.NumTypeArguments();
  }
  return num_type_args;
}


bool Class::HasTypeArguments() const {
  if (!IsSignatureClass() && (is_finalized() || is_prefinalized())) {
    // More efficient than calling NumTypeArguments().
    return type_arguments_instance_field_offset() != kNoTypeArguments;
  } else {
    // No need to check NumTypeArguments() if class has type parameters.
    return (NumTypeParameters() > 0) || (NumTypeArguments() > 0);
  }
}


RawClass* Class::SuperClass() const {
  const Type& sup_type = Type::Handle(super_type());
  if (sup_type.IsNull()) {
    return Class::null();
  }
  return sup_type.type_class();
}


void Class::set_super_type(const Type& value) const {
  StorePointer(&raw_ptr()->super_type_, value.raw());
}


bool Class::HasFactoryClass() const {
  const Object& factory_class = Object::Handle(raw_ptr()->factory_class_);
  return !factory_class.IsNull();
}


bool Class::HasResolvedFactoryClass() const {
  ASSERT(HasFactoryClass());
  const Object& factory_class = Object::Handle(raw_ptr()->factory_class_);
  return factory_class.IsClass();
}


RawClass* Class::FactoryClass() const {
  ASSERT(HasResolvedFactoryClass());
  Class& type_class = Class::Handle();
  type_class ^= raw_ptr()->factory_class_;
  return type_class.raw();
}


RawUnresolvedClass* Class::UnresolvedFactoryClass() const {
  ASSERT(!HasResolvedFactoryClass());
  UnresolvedClass& unresolved_factory_class = UnresolvedClass::Handle();
  unresolved_factory_class ^= raw_ptr()->factory_class_;
  return unresolved_factory_class.raw();
}


void Class::set_factory_class(const Object& value) const {
  StorePointer(&raw_ptr()->factory_class_, value.raw());
}


// Return a TypeParameter if the type_name is a type parameter of this class.
// Return null otherwise.
RawTypeParameter* Class::LookupTypeParameter(const String& type_name,
                                             intptr_t token_pos) const {
  ASSERT(!type_name.IsNull());
  const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
  if (!type_params.IsNull()) {
    intptr_t num_type_params = type_params.Length();
    TypeParameter& type_param = TypeParameter::Handle();
    String& type_param_name = String::Handle();
    // TODO(regis): We do not copy the bound (= type_param.bound()), since
    // we are not able to finalize the bounds of type parameter references
    // without getting into cycles. Revisit.
    const AbstractType& bound = AbstractType::Handle(
        Isolate::Current()->object_store()->object_type());
    for (intptr_t i = 0; i < num_type_params; i++) {
      type_param ^= type_params.TypeAt(i);
      type_param_name = type_param.name();
      if (type_param_name.Equals(type_name)) {
        intptr_t index = type_param.index();
        // Create a non-finalized new TypeParameter with the given token_pos.
        if (type_param.IsFinalized()) {
          // The index was adjusted during finalization. Revert.
          index -= NumTypeArguments() - num_type_params;
        } else {
          ASSERT(type_param.index() == i);
        }
        return TypeParameter::New(*this, index, type_name, bound, token_pos);
      }
    }
  }
  return TypeParameter::null();
}


void Class::CalculateFieldOffsets() const {
  Array& flds = Array::Handle(fields());
  const Class& super = Class::Handle(SuperClass());
  intptr_t offset = 0;
  intptr_t type_args_field_offset = kNoTypeArguments;
  if (super.IsNull()) {
    offset = sizeof(RawObject);
  } else {
    type_args_field_offset = super.type_arguments_instance_field_offset();
    offset = super.next_field_offset();
    ASSERT(offset > 0);
    // We should never call CalculateFieldOffsets for native wrapper
    // classes, assert this.
    ASSERT(num_native_fields() == 0);
    set_num_native_fields(super.num_native_fields());
  }
  // If the super class is parameterized, use the same type_arguments field.
  if (type_args_field_offset == kNoTypeArguments) {
    const TypeArguments& type_params = TypeArguments::Handle(type_parameters());
    if (!type_params.IsNull()) {
      ASSERT(type_params.Length() > 0);
      // The instance needs a type_arguments field.
      type_args_field_offset = offset;
      offset += kWordSize;
    }
  }
  set_type_arguments_instance_field_offset(type_args_field_offset);
  ASSERT(offset != 0);
  Field& field = Field::Handle();
  intptr_t len = flds.Length();
  for (intptr_t i = 0; i < len; i++) {
    field ^= flds.At(i);
    // Offset is computed only for instance fields.
    if (!field.is_static()) {
      ASSERT(field.Offset() == 0);
      field.SetOffset(offset);
      offset += kWordSize;
    }
  }
  set_instance_size(RoundedAllocationSize(offset));
  set_next_field_offset(offset);
}


void Class::Finalize() const {
  ASSERT(!is_finalized());
  // Prefinalized classes have a VM internal representation and no Dart fields.
  // Their instance size  is precomputed and field offsets are known.
  if (!is_prefinalized()) {
    // Compute offsets of instance fields and instance size.
    CalculateFieldOffsets();
  }
  set_is_finalized();
}


static const char* FormatPatchError(const char* format, const Object& obj) {
  const char* msg = obj.ToCString();
  intptr_t len = OS::SNPrint(NULL, 0, format, msg) + 1;
  char* result = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(result, len, format, msg);
  return result;
}


// Apply the members from the patch class to the original class.
const char* Class::ApplyPatch(const Class& patch) const {
  ASSERT(!is_finalized());
  // Shared handles used during the iteration.
  String& member_name = String::Handle();

  const Script& patch_script = Script::Handle(patch.script());
  const PatchClass& patch_class = PatchClass::Handle(
      PatchClass::New(*this, patch_script));

  Array& orig_list = Array::Handle(functions());
  intptr_t orig_len = orig_list.Length();
  Array& patch_list = Array::Handle(patch.functions());
  intptr_t patch_len = patch_list.Length();

  // TODO(iposva): Verify that only patching existing methods and adding only
  // new private methods.
  Function& func = Function::Handle();
  Function& orig_func = Function::Handle();
  const GrowableObjectArray& new_functions = GrowableObjectArray::Handle(
      GrowableObjectArray::New(orig_len));
  for (intptr_t i = 0; i < orig_len; i++) {
    orig_func ^= orig_list.At(i);
    member_name = orig_func.name();
    func = patch.LookupFunction(member_name);
    if (func.IsNull()) {
      // Non-patched function is preserved, all patched functions are added in
      // the loop below.
      new_functions.Add(orig_func);
    } else if (!func.HasCompatibleParametersWith(orig_func) &&
               !(func.IsFactory() && orig_func.IsConstructor() &&
                 (func.num_fixed_parameters() + 1 ==
                  orig_func.num_fixed_parameters()))) {
      return FormatPatchError("mismatched parameters: %s", member_name);
    }
  }
  for (intptr_t i = 0; i < patch_len; i++) {
    func ^= patch_list.At(i);
    func.set_owner(patch_class);
    new_functions.Add(func);
  }
  Array& new_list = Array::Handle(Array::MakeArray(new_functions));
  SetFunctions(new_list);

  // Merge the two list of fields. Raise an error when duplicates are found or
  // when a public field is being added.
  orig_list = fields();
  orig_len = orig_list.Length();
  patch_list = patch.fields();
  patch_len = patch_list.Length();

  Field& field = Field::Handle();
  Field& orig_field = Field::Handle();
  new_list = Array::New(patch_len + orig_len);
  for (intptr_t i = 0; i < patch_len; i++) {
    field ^= patch_list.At(i);
    field.set_owner(*this);
    member_name = field.name();
    // TODO(iposva): Verify non-public fields only.

    // Verify no duplicate additions.
    orig_field = LookupField(member_name);
    if (!orig_field.IsNull()) {
      return FormatPatchError("duplicate field: %s", member_name);
    }
    new_list.SetAt(i, field);
  }
  for (intptr_t i = 0; i < orig_len; i++) {
    field ^= orig_list.At(i);
    new_list.SetAt(patch_len + i, field);
  }
  SetFields(new_list);
  return NULL;
}


void Class::SetFields(const Array& value) const {
  ASSERT(!value.IsNull());
#if defined(DEBUG)
  // Verify that all the fields in the array have this class as owner.
  Field& field = Field::Handle();
  intptr_t len = value.Length();
  for (intptr_t i = 0; i < len; i++) {
    field ^= value.At(i);
    ASSERT(field.owner() == raw());
  }
#endif
  // The value of static fields is already initialized to null.
  StorePointer(&raw_ptr()->fields_, value.raw());
}


template <class FakeInstance>
RawClass* Class::New(intptr_t index) {
  ASSERT(Object::class_class() != Class::null());
  Class& result = Class::Handle();
  {
    RawObject* raw = Object::Allocate(Class::kClassId,
                                      Class::InstanceSize(),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
  }
  FakeInstance fake;
  ASSERT(fake.IsInstance());
  result.set_handle_vtable(fake.vtable());
  result.set_instance_size(FakeInstance::InstanceSize());
  result.set_next_field_offset(FakeInstance::InstanceSize());
  result.set_id(index);
  result.raw_ptr()->state_bits_ = 0;
  result.raw_ptr()->type_arguments_instance_field_offset_ = kNoTypeArguments;
  result.raw_ptr()->num_native_fields_ = 0;
  result.raw_ptr()->token_pos_ = Scanner::kDummyTokenIndex;
  result.InitEmptyFields();
  Isolate::Current()->class_table()->Register(result);
  return result.raw();
}


template <class FakeInstance>
RawClass* Class::New(const String& name,
                     const Script& script,
                     intptr_t token_pos) {
  Class& result = Class::Handle(New<FakeInstance>(kIllegalCid));
  result.set_name(name);
  result.set_script(script);
  result.set_token_pos(token_pos);
  return result.raw();
}


RawClass* Class::New(const String& name,
                     const Script& script,
                     intptr_t token_pos) {
  Class& result = Class::Handle(New<Instance>(name, script, token_pos));
  return result.raw();
}


RawClass* Class::NewInterface(const String& name,
                              const Script& script,
                              intptr_t token_pos) {
  Class& result = Class::Handle(New<Instance>(name, script, token_pos));
  result.set_is_interface();
  return result.raw();
}


RawClass* Class::NewSignatureClass(const String& name,
                                   const Function& signature_function,
                                   const Script& script) {
  ASSERT(!signature_function.IsNull());
  const Class& owner_class = Class::Handle(signature_function.Owner());
  ASSERT(!owner_class.IsNull());
  TypeArguments& type_parameters = TypeArguments::Handle();
  // A signature class extends class Instance and is parameterized in the same
  // way as the owner class of its non-static signature function.
  // It is not type parameterized if its signature function is static.
  if (!signature_function.is_static() &&
      (owner_class.NumTypeParameters() > 0) &&
      !signature_function.HasInstantiatedSignature()) {
    type_parameters = owner_class.type_parameters();
  }
  const intptr_t token_pos = signature_function.token_pos();
  Class& result = Class::Handle(New<Instance>(name, script, token_pos));
  const Type& super_type = Type::Handle(Type::ObjectType());
  const Array& empty_array = Array::Handle(Object::empty_array());
  ASSERT(!super_type.IsNull());
  result.set_instance_size(Closure::InstanceSize());
  result.set_next_field_offset(Closure::InstanceSize());
  result.set_super_type(super_type);
  result.set_signature_function(signature_function);
  result.set_type_parameters(type_parameters);
  result.SetFields(empty_array);
  result.SetFunctions(empty_array);
  result.set_type_arguments_instance_field_offset(
      Closure::type_arguments_offset());
  // Implements interface "Function".
  const Type& function_type = Type::Handle(Type::Function());
  const Array& interfaces = Array::Handle(Array::New(1, Heap::kOld));
  interfaces.SetAt(0, function_type);
  result.set_interfaces(interfaces);
  // Unless the signature function already has a signature class, create a
  // canonical signature class by having the signature function point back to
  // the signature class.
  if (signature_function.signature_class() == Object::null()) {
    signature_function.set_signature_class(result);
    result.set_is_finalized();
  } else {
    // This new signature class is an alias.
    ASSERT(!result.IsCanonicalSignatureClass());
    // Do not yet mark it as finalized, so that the class finalizer can check it
    // for illegal self references.
    result.set_is_prefinalized();
  }
  // Instances of a signature class can only be closures.
  ASSERT(result.instance_size() == Closure::InstanceSize());
  // Cache the signature type as the first canonicalized type in result.
  const Type& signature_type = Type::Handle(result.SignatureType());
  ASSERT(!signature_type.IsFinalized());
  const Array& new_canonical_types = Array::Handle(Array::New(1, Heap::kOld));
  new_canonical_types.SetAt(0, signature_type);
  result.set_canonical_types(new_canonical_types);
  return result.raw();
}


RawClass* Class::NewNativeWrapper(const Library& library,
                                  const String& name,
                                  int field_count) {
  Class& cls = Class::Handle(library.LookupClass(name));
  if (cls.IsNull()) {
    const Array& empty_array = Array::Handle(Object::empty_array());
    cls = New<Instance>(name, Script::Handle(), Scanner::kDummyTokenIndex);
    cls.SetFields(empty_array);
    cls.SetFunctions(empty_array);
    // Set super class to Object.
    cls.set_super_type(Type::Handle(Type::ObjectType()));
    // Compute instance size. First word contains a pointer to a properly
    // sized typed array once the first native field has been set.
    intptr_t instance_size = sizeof(RawObject) + kWordSize;
    cls.set_instance_size(RoundedAllocationSize(instance_size));
    cls.set_next_field_offset(instance_size);
    cls.set_num_native_fields(field_count);
    cls.set_is_finalized();
    library.AddClass(cls);
    return cls.raw();
  } else {
    return Class::null();
  }
}


RawClass* Class::NewStringClass(intptr_t class_id) {
  intptr_t instance_size;
  if (class_id == kOneByteStringCid) {
    instance_size = OneByteString::InstanceSize();
  } else if (class_id == kTwoByteStringCid) {
    instance_size = TwoByteString::InstanceSize();
  } else if (class_id == kExternalOneByteStringCid) {
    instance_size = ExternalOneByteString::InstanceSize();
  } else {
    ASSERT(class_id == kExternalTwoByteStringCid);
    instance_size = ExternalTwoByteString::InstanceSize();
  }
  Class& result = Class::Handle(New<String>(class_id));
  result.set_instance_size(instance_size);
  result.set_next_field_offset(instance_size);
  result.set_is_prefinalized();
  return result.raw();
}


void Class::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  StorePointer(&raw_ptr()->name_, value.raw());
}


void Class::set_script(const Script& value) const {
  StorePointer(&raw_ptr()->script_, value.raw());
}


void Class::set_token_pos(intptr_t token_pos) const {
  ASSERT(token_pos >= 0);
  raw_ptr()->token_pos_ = token_pos;
}


void Class::set_is_interface() const {
  set_state_bits(InterfaceBit::update(true, raw_ptr()->state_bits_));
}

void Class::set_is_abstract() const {
  set_state_bits(AbstractBit::update(true, raw_ptr()->state_bits_));
}


void Class::set_is_const() const {
  set_state_bits(ConstBit::update(true, raw_ptr()->state_bits_));
}


void Class::set_is_finalized() const {
  ASSERT(!is_finalized());
  set_state_bits(StateBits::update(RawClass::kFinalized,
                                   raw_ptr()->state_bits_));
}


void Class::set_is_prefinalized() const {
  ASSERT(!is_finalized());
  set_state_bits(StateBits::update(RawClass::kPreFinalized,
                                   raw_ptr()->state_bits_));
}


void Class::set_interfaces(const Array& value) const {
  // Verification and resolving of interfaces occurs in finalizer.
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->interfaces_, value.raw());
}


void Class::AddDirectSubclass(const Class& subclass) const {
  ASSERT(!subclass.IsNull());
  ASSERT(subclass.SuperClass() == raw());
  // Do not keep track of the direct subclasses of class Object.
  ASSERT(!IsObjectClass());
  GrowableObjectArray& direct_subclasses =
      GrowableObjectArray::Handle(raw_ptr()->direct_subclasses_);
  if (direct_subclasses.IsNull()) {
    direct_subclasses = GrowableObjectArray::New(4, Heap::kOld);
    StorePointer(&raw_ptr()->direct_subclasses_, direct_subclasses.raw());
  }
#if defined(DEBUG)
  // Verify that the same class is not added twice.
  for (intptr_t i = 0; i < direct_subclasses.Length(); i++) {
    ASSERT(direct_subclasses.At(i) != subclass.raw());
  }
#endif
  direct_subclasses.Add(subclass);
}


RawArray* Class::constants() const {
  return raw_ptr()->constants_;
}

void Class::set_constants(const Array& value) const {
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->constants_, value.raw());
}


RawArray* Class::canonical_types() const {
  return raw_ptr()->canonical_types_;
}

void Class::set_canonical_types(const Array& value) const {
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->canonical_types_, value.raw());
}


void Class::set_allocation_stub(const Code& value) const {
  ASSERT(!value.IsNull());
  ASSERT(raw_ptr()->allocation_stub_ == Code::null());
  StorePointer(&raw_ptr()->allocation_stub_, value.raw());
}


bool Class::IsListClass() const {
  return raw() == Isolate::Current()->object_store()->list_class();
}


bool Class::IsCanonicalSignatureClass() const {
  const Function& function = Function::Handle(signature_function());
  return (!function.IsNull() && (function.signature_class() == raw()));
}


// If test_kind == kIsSubtypeOf, checks if type S is a subtype of type T.
// If test_kind == kIsMoreSpecificThan, checks if S is more specific than T.
// Type S is specified by this class parameterized with 'type_arguments', and
// type T by class 'other' parameterized with 'other_type_arguments'.
// This class and class 'other' do not need to be finalized, however, they must
// be resolved as well as their interfaces.
bool Class::TypeTest(
    TypeTestKind test_kind,
    const AbstractTypeArguments& type_arguments,
    const Class& other,
    const AbstractTypeArguments& other_type_arguments,
    Error* malformed_error) const {
  ASSERT(!IsVoidClass());
  // Check for DynamicType.
  // Each occurrence of DynamicType in type T is interpreted as the dynamic
  // type, a supertype of all types.
  if (other.IsDynamicClass()) {
    return true;
  }
  // In the case of a subtype test, each occurrence of DynamicType in type S is
  // interpreted as the bottom type, a subtype of all types.
  // However, DynamicType is not more specific than any type.
  if (IsDynamicClass()) {
    return test_kind == kIsSubtypeOf;
  }
  // Check for NullType, which is not a subtype of any type, but is more
  // specific than any type.
  if (IsNullClass()) {
    // User code cannot refer to class Null, therefore, we can only encounter
    // NullType here as the type of the null constant, which must be treated
    // separately in 'instance of' checks. Therefore, the NullType can only
    // be encountered here during optimizations in 'more specific than' tests.
    ASSERT(test_kind == kIsMoreSpecificThan);
    return true;
  }
  // Check for reflexivity.
  if (raw() == other.raw()) {
    const intptr_t len = NumTypeArguments();
    if (len == 0) {
      return true;
    }
    // Since we do not truncate the type argument vector of a subclass (see
    // below), we only check a prefix of the proper length.
    // Check for covariance.
    if (other_type_arguments.IsNull() ||
        other_type_arguments.IsRawInstantiatedRaw(len)) {
      return true;
    }
    if (type_arguments.IsNull() ||
        type_arguments.IsRawInstantiatedRaw(len)) {
      return test_kind == kIsSubtypeOf;
    }
    return type_arguments.TypeTest(test_kind,
                                   other_type_arguments,
                                   len,
                                   malformed_error);
  }
  // TODO(regis): Check for interface type S implementing method call() of
  // function type T.
  // Check for two function types.
  if (IsSignatureClass() && other.IsSignatureClass()) {
    const Function& fun = Function::Handle(signature_function());
    const Function& other_fun = Function::Handle(other.signature_function());
    return fun.TypeTest(test_kind,
                        type_arguments,
                        other_fun,
                        other_type_arguments,
                        malformed_error);
  }
  // Check for 'direct super type' in the case of an interface
  // (i.e. other.is_interface()) or implicit interface (i.e.
  // !other.is_interface()) and check for transitivity at the same time.
  Array& interfaces = Array::Handle(this->interfaces());
  AbstractType& interface = AbstractType::Handle();
  Class& interface_class = Class::Handle();
  AbstractTypeArguments& interface_args = AbstractTypeArguments::Handle();
  for (intptr_t i = 0; i < interfaces.Length(); i++) {
    interface ^= interfaces.At(i);
    interface_class = interface.type_class();
    interface_args = interface.arguments();
    if (!interface_args.IsNull() && !interface_args.IsInstantiated()) {
      // This type class implements an interface that is parameterized with
      // generic type(s), e.g. it implements List<T>.
      // The uninstantiated type T must be instantiated using the type
      // parameters of this type before performing the type test.
      // The type arguments of this type that are referred to by the type
      // parameters of the interface are at the end of the type vector,
      // after the type arguments of the super type of this type.
      // The index of the type parameters is adjusted upon finalization.
      ASSERT(interface.IsFinalized());
      interface_args = interface_args.InstantiateFrom(type_arguments);
      // In checked mode, verify that the instantiated interface type
      // arguments are within the bounds specified by the interface class.
      // Note that the additional bounds check in checked mode may lead to a
      // dynamic type error, but it will never change the result of the type
      // check from true in production mode to false in checked mode.
      if (FLAG_enable_type_checks && !interface_args.IsNull()) {
        // Pass type_arguments as bounds instantiator.
        if (!interface_args.IsWithinBoundsOf(interface_class,
                                             type_arguments,
                                             malformed_error)) {
          continue;
        }
      }
    }
    if (interface_class.TypeTest(test_kind,
                                 interface_args,
                                 other,
                                 other_type_arguments,
                                 malformed_error)) {
      return true;
    }
  }
  // Check the interface case.
  if (is_interface()) {
    // We already checked the case where 'other' is an interface. Now, 'this',
    // an interface, cannot be more specific than a class, except class Object,
    // because although Object is not considered an interface by the vm, it is
    // one. In other words, all classes implementing this interface also extend
    // class Object. An interface is also more specific than the DynamicType.
    return (other.IsDynamicClass() || other.IsObjectClass());
  }
  const Class& super_class = Class::Handle(SuperClass());
  if (super_class.IsNull()) {
    return false;
  }
  // Instead of truncating the type argument vector to the length of the super
  // type argument vector, we make sure that the code works with a vector that
  // is longer than necessary.
  return super_class.TypeTest(test_kind,
                              type_arguments,
                              other,
                              other_type_arguments,
                              malformed_error);
}


bool Class::IsTopLevel() const {
  return String::Handle(Name()).Equals("::");
}


RawFunction* Class::LookupDynamicFunction(const String& name) const {
  Function& function = Function::Handle(LookupFunction(name));
  if (function.IsNull() || !function.IsDynamicFunction()) {
    return Function::null();
  }
  return function.raw();
}


RawFunction* Class::LookupStaticFunction(const String& name) const {
  Function& function = Function::Handle(LookupFunction(name));
  if (function.IsNull() || !function.IsStaticFunction()) {
    return Function::null();
  }
  return function.raw();
}


RawFunction* Class::LookupConstructor(const String& name) const {
  Function& function = Function::Handle(LookupFunction(name));
  if (function.IsNull() || !function.IsConstructor()) {
    return Function::null();
  }
  ASSERT(!function.is_static());
  return function.raw();
}


RawFunction* Class::LookupFactory(const String& name) const {
  Function& function = Function::Handle(LookupFunction(name));
  if (function.IsNull() || !function.IsFactory()) {
    return Function::null();
  }
  ASSERT(function.is_static());
  return function.raw();
}


static bool MatchesAccessorName(const String& name,
                                const char* prefix,
                                intptr_t prefix_length,
                                const String& accessor_name) {
  intptr_t name_len = name.Length();
  intptr_t accessor_name_len = accessor_name.Length();

  if (name_len != (accessor_name_len + prefix_length)) {
    return false;
  }
  for (intptr_t i = 0; i < prefix_length; i++) {
    if (name.CharAt(i) != prefix[i]) {
      return false;
    }
  }
  for (intptr_t i = 0, j = prefix_length; i < accessor_name_len; i++, j++) {
    if (name.CharAt(j) != accessor_name.CharAt(i)) {
      return false;
    }
  }
  return true;
}


RawFunction* Class::LookupFunction(const String& name) const {
  Isolate* isolate = Isolate::Current();
  ASSERT(name.IsOneByteString());
  Array& funcs = Array::Handle(isolate, functions());
  if (funcs.IsNull()) {
    // This can occur, e.g., for Null classes.
    return Function::null();
  }
  Function& function = Function::Handle(isolate, Function::null());
  String& function_name = String::Handle(isolate, String::null());
  intptr_t len = funcs.Length();
  for (intptr_t i = 0; i < len; i++) {
    function ^= funcs.At(i);
    function_name ^= function.name();
    if (OneByteString::EqualsIgnoringPrivateKey(function_name, name)) {
      return function.raw();
    }
  }

  // No function found.
  return Function::null();
}


RawFunction* Class::LookupGetterFunction(const String& name) const {
  return LookupAccessorFunction(kGetterPrefix, kGetterPrefixLength, name);
}


RawFunction* Class::LookupSetterFunction(const String& name) const {
  return LookupAccessorFunction(kSetterPrefix, kSetterPrefixLength, name);
}


RawFunction* Class::LookupAccessorFunction(const char* prefix,
                                           intptr_t prefix_length,
                                           const String& name) const {
  Isolate* isolate = Isolate::Current();
  Array& funcs = Array::Handle(isolate, functions());
  Function& function = Function::Handle(isolate, Function::null());
  String& function_name = String::Handle(isolate, String::null());
  intptr_t len = funcs.Length();
  for (intptr_t i = 0; i < len; i++) {
    function ^= funcs.At(i);
    function_name ^= function.name();
    if (MatchesAccessorName(function_name, prefix, prefix_length, name)) {
      return function.raw();
    }
  }

  // No function found.
  return Function::null();
}


RawFunction* Class::LookupFunctionAtToken(intptr_t token_pos) const {
  // TODO(hausner): we can shortcut the negative case if we knew the
  // beginning and end token position of the class.
  Function& func = Function::Handle();
  func = LookupClosureFunction(token_pos);
  if (!func.IsNull()) {
    return func.raw();
  }
  Array& funcs = Array::Handle(functions());
  intptr_t len = funcs.Length();
  for (intptr_t i = 0; i < len; i++) {
    func ^= funcs.At(i);
    if ((func.token_pos() <= token_pos) &&
        (token_pos < func.end_token_pos())) {
      return func.raw();
    }
  }
  // No function found.
  return Function::null();
}


RawField* Class::LookupInstanceField(const String& name) const {
  ASSERT(is_finalized());
  const Field& field = Field::Handle(LookupField(name));
  if (!field.IsNull()) {
    if (field.is_static()) {
      // Name matches but it is not of the correct kind, return NULL.
      return Field::null();
    }
    return field.raw();
  }
  // No field found.
  return Field::null();
}


RawField* Class::LookupStaticField(const String& name) const {
  ASSERT(is_finalized());
  const Field& field = Field::Handle(LookupField(name));
  if (!field.IsNull()) {
    if (!field.is_static()) {
      // Name matches but it is not of the correct kind, return NULL.
      return Field::null();
    }
    return field.raw();
  }
  // No field found.
  return Field::null();
}


RawField* Class::LookupField(const String& name) const {
  Isolate* isolate = Isolate::Current();
  ASSERT(name.IsOneByteString());
  const Array& flds = Array::Handle(isolate, fields());
  Field& field = Field::Handle(isolate, Field::null());
  String& field_name = String::Handle(isolate, String::null());
  intptr_t len = flds.Length();
  for (intptr_t i = 0; i < len; i++) {
    field ^= flds.At(i);
    field_name ^= field.name();
    if (OneByteString::EqualsIgnoringPrivateKey(field_name, name)) {
      return field.raw();
    }
  }
  // No field found.
  return Field::null();
}


RawLibraryPrefix* Class::LookupLibraryPrefix(const String& name) const {
  Isolate* isolate = Isolate::Current();
  const Library& lib = Library::Handle(isolate, library());
  const Object& obj = Object::Handle(isolate, lib.LookupLocalObject(name));
  if (!obj.IsNull() && obj.IsLibraryPrefix()) {
    const LibraryPrefix& lib_prefix = LibraryPrefix::Cast(obj);
    return lib_prefix.raw();
  }
  return LibraryPrefix::null();
}


const char* Class::ToCString() const {
  const char* format = is_interface()
      ? "%s Interface: %s" : "%s Class: %s";
  const Library& lib = Library::Handle(library());
  const char* library_name = lib.IsNull() ? "" : lib.ToCString();
  const char* class_name = String::Handle(Name()).ToCString();
  intptr_t len = OS::SNPrint(NULL, 0, format, library_name, class_name) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, format, library_name, class_name);
  return chars;
}


void Class::InsertCanonicalConstant(intptr_t index,
                                    const Instance& constant) const {
  // The constant needs to be added to the list. Grow the list if it is full.
  Array& canonical_list = Array::Handle(constants());
  const intptr_t list_len = canonical_list.Length();
  if (index >= list_len) {
    const intptr_t new_length = (list_len == 0) ? 4 : list_len + 4;
    const Array& new_canonical_list =
        Array::Handle(Array::Grow(canonical_list, new_length, Heap::kOld));
    set_constants(new_canonical_list);
    new_canonical_list.SetAt(index, constant);
  } else {
    canonical_list.SetAt(index, constant);
  }
}


RawUnresolvedClass* UnresolvedClass::New(const LibraryPrefix& library_prefix,
                                         const String& ident,
                                         intptr_t token_pos) {
  const UnresolvedClass& type = UnresolvedClass::Handle(UnresolvedClass::New());
  type.set_library_prefix(library_prefix);
  type.set_ident(ident);
  type.set_token_pos(token_pos);
  return type.raw();
}


RawUnresolvedClass* UnresolvedClass::New() {
  ASSERT(Object::unresolved_class_class() != Class::null());
  RawObject* raw = Object::Allocate(UnresolvedClass::kClassId,
                                    UnresolvedClass::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawUnresolvedClass*>(raw);
}


void UnresolvedClass::set_token_pos(intptr_t token_pos) const {
  ASSERT(token_pos >= 0);
  raw_ptr()->token_pos_ = token_pos;
}


void UnresolvedClass::set_ident(const String& ident) const {
  StorePointer(&raw_ptr()->ident_, ident.raw());
}


void UnresolvedClass::set_library_prefix(
    const LibraryPrefix& library_prefix) const {
  StorePointer(&raw_ptr()->library_prefix_, library_prefix.raw());
}


void UnresolvedClass::set_factory_signature_class(const Class& value) const {
  StorePointer(&raw_ptr()->factory_signature_class_, value.raw());
}


RawString* UnresolvedClass::Name() const {
  if (library_prefix() != LibraryPrefix::null()) {
    const LibraryPrefix& lib_prefix = LibraryPrefix::Handle(library_prefix());
    String& name = String::Handle();
    String& str = String::Handle();
    name = lib_prefix.name();  // Qualifier.
    str = Symbols::Dot();
    name = String::Concat(name, str);
    str = ident();
    name = String::Concat(name, str);
    return name.raw();
  } else {
    return ident();
  }
}


const char* UnresolvedClass::ToCString() const {
  const char* format = "unresolved class '%s'";
  const char* cname =  String::Handle(Name()).ToCString();
  intptr_t len = OS::SNPrint(NULL, 0, format, cname) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, format, cname);
  return chars;
}


intptr_t AbstractTypeArguments::Length() const  {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
  return -1;
}


RawAbstractType* AbstractTypeArguments::TypeAt(intptr_t index) const {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
  return NULL;
}


void AbstractTypeArguments::SetTypeAt(intptr_t index,
                                      const AbstractType& value) const {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
}


bool AbstractTypeArguments::IsResolved() const {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractTypeArguments::IsInstantiated() const {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractTypeArguments::IsUninstantiatedIdentity() const {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
  return false;
}


RawString* AbstractTypeArguments::SubvectorName(
    intptr_t from_index,
    intptr_t len,
    NameVisibility name_visibility) const {
  ASSERT(from_index + len <= Length());
  String& name = String::Handle();
  const intptr_t num_strings = 2*len + 1;  // "<""T"", ""T"">".
  const Array& strings = Array::Handle(Array::New(num_strings));
  intptr_t s = 0;
  strings.SetAt(s++, String::Handle(Symbols::New("<")));
  const String& kCommaSpace = String::Handle(Symbols::New(", "));
  AbstractType& type = AbstractType::Handle();
  for (intptr_t i = 0; i < len; i++) {
    type = TypeAt(from_index + i);
    name = type.BuildName(name_visibility);
    strings.SetAt(s++, name);
    if (i < len - 1) {
      strings.SetAt(s++, kCommaSpace);
    }
  }
  strings.SetAt(s++, String::Handle(Symbols::New(">")));
  ASSERT(s == num_strings);
  name = String::ConcatAll(strings);
  return Symbols::New(name);
}


bool AbstractTypeArguments::Equals(const AbstractTypeArguments& other) const {
  ASSERT(!IsNull());  // Use AbstractTypeArguments::AreEqual().
  if (this->raw() == other.raw()) {
    return true;
  }
  if (other.IsNull()) {
    return false;
  }
  intptr_t num_types = Length();
  if (num_types != other.Length()) {
    return false;
  }
  AbstractType& type = AbstractType::Handle();
  AbstractType& other_type = AbstractType::Handle();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    other_type = other.TypeAt(i);
    if (!type.Equals(other_type)) {
      return false;
    }
  }
  return true;
}


bool AbstractTypeArguments::AreEqual(
    const AbstractTypeArguments& arguments,
    const AbstractTypeArguments& other_arguments) {
  if (arguments.raw() == other_arguments.raw()) {
    return true;
  }
  if (arguments.IsNull()) {
    return other_arguments.IsDynamicTypes(false, other_arguments.Length());
  }
  if (other_arguments.IsNull()) {
    return arguments.IsDynamicTypes(false, arguments.Length());
  }
  return arguments.Equals(other_arguments);
}


bool AbstractTypeArguments::AreIdentical(
    const AbstractTypeArguments& arguments,
    const AbstractTypeArguments& other_arguments,
    bool check_type_parameter_bounds) {
  if (arguments.raw() == other_arguments.raw()) {
    return true;
  }
  if (arguments.IsNull() || other_arguments.IsNull()) {
    return false;
  }
  intptr_t num_types = arguments.Length();
  if (num_types != other_arguments.Length()) {
    return false;
  }
  AbstractType& type = AbstractType::Handle();
  AbstractType& other_type = AbstractType::Handle();
  for (intptr_t i = 0; i < num_types; i++) {
    type = arguments.TypeAt(i);
    ASSERT(!type.IsNull());
    other_type = other_arguments.TypeAt(i);
    if (!type.IsIdentical(other_type, check_type_parameter_bounds)) {
      return false;
    }
  }
  return true;
}


RawAbstractTypeArguments* AbstractTypeArguments::InstantiateFrom(
    const AbstractTypeArguments& instantiator_type_arguments) const {
  // AbstractTypeArguments is an abstract class.
  UNREACHABLE();
  return NULL;
}


bool AbstractTypeArguments::IsDynamicTypes(bool raw_instantiated,
                                           intptr_t len) const {
  ASSERT(Length() >= len);
  AbstractType& type = AbstractType::Handle();
  Class& type_class = Class::Handle();
  for (intptr_t i = 0; i < len; i++) {
    type = TypeAt(i);
    ASSERT(!type.IsNull());
    if (!type.HasResolvedTypeClass()) {
      if (raw_instantiated && type.IsTypeParameter()) {
        // An uninstantiated type parameter is equivalent to dynamic.
        continue;
      }
      ASSERT((!raw_instantiated && type.IsTypeParameter()) ||
             type.IsMalformed());
      return false;
    }
    type_class = type.type_class();
    if (!type_class.IsDynamicClass()) {
      return false;
    }
  }
  return true;
}


static RawError* FormatError(const Error& prev_error,
                             const Script& script,
                             intptr_t token_pos,
                             const char* format, ...) {
  va_list args;
  va_start(args, format);
  if (prev_error.IsNull()) {
    return Parser::FormatError(script, token_pos, "Error", format, args);
  } else {
    return Parser::FormatErrorWithAppend(prev_error, script, token_pos,
                                         "Error", format, args);
  }
}


bool AbstractTypeArguments::IsWithinBoundsOf(
    const Class& cls,
    const AbstractTypeArguments& bounds_instantiator,
    Error* malformed_error) const {
  ASSERT(FLAG_enable_type_checks);
  // This function may be called at compile time on (partially) uninstantiated
  // type arguments and may return true, in which case a run time bounds check
  // can be avoided.
  ASSERT(Length() >= cls.NumTypeArguments());
  const intptr_t num_type_params = cls.NumTypeParameters();
  const intptr_t offset = cls.NumTypeArguments() - num_type_params;
  AbstractType& this_type_arg = AbstractType::Handle();
  AbstractType& cls_type_arg = AbstractType::Handle();
  AbstractType& bound = AbstractType::Handle();
  const TypeArguments& cls_type_params =
      TypeArguments::Handle(cls.type_parameters());
  ASSERT((cls_type_params.IsNull() && (num_type_params == 0)) ||
         (cls_type_params.Length() == num_type_params));
  for (intptr_t i = 0; i < num_type_params; i++) {
    cls_type_arg = cls_type_params.TypeAt(i);
    const TypeParameter& cls_type_param = TypeParameter::Cast(cls_type_arg);
    bound = cls_type_param.bound();
    if (!bound.IsDynamicType()) {
      this_type_arg = TypeAt(offset + i);
      Error& malformed_bound_error = Error::Handle();
      if (bound.IsMalformed()) {
        malformed_bound_error = bound.malformed_error();
      } else if (!bound.IsInstantiated()) {
        bound = bound.InstantiateFrom(bounds_instantiator);
      }
      if (!malformed_bound_error.IsNull() ||
          !this_type_arg.IsSubtypeOf(bound, malformed_error)) {
        // Ignore this bound error if another malformed error was already
        // reported for this type test.
        if ((malformed_error != NULL) && malformed_error->IsNull()) {
          const String& type_arg_name =
              String::Handle(this_type_arg.UserVisibleName());
          const String& class_name = String::Handle(cls.Name());
          const String& bound_name = String::Handle(bound.UserVisibleName());
          const Script& script = Script::Handle(cls.script());
          // Since the bound was canonicalized, its token index was lost,
          // therefore, use the token index of the corresponding type parameter.
          *malformed_error ^= FormatError(malformed_bound_error,
                                          script, cls_type_param.token_pos(),
                                          "type argument '%s' does not "
                                          "extend bound '%s' of '%s'\n",
                                          type_arg_name.ToCString(),
                                          bound_name.ToCString(),
                                          class_name.ToCString());
        }
        return false;
      }
    }
  }
  const Class& super_class = Class::Handle(cls.SuperClass());
  if (!super_class.IsNull() &&
      !IsWithinBoundsOf(super_class, bounds_instantiator, malformed_error)) {
    return false;
  }
  return true;
}


bool AbstractTypeArguments::TypeTest(TypeTestKind test_kind,
                                     const AbstractTypeArguments& other,
                                     intptr_t len,
                                     Error* malformed_error) const {
  ASSERT(Length() >= len);
  ASSERT(!other.IsNull());
  ASSERT(other.Length() >= len);
  AbstractType& type = AbstractType::Handle();
  AbstractType& other_type = AbstractType::Handle();
  for (intptr_t i = 0; i < len; i++) {
    type = TypeAt(i);
    ASSERT(!type.IsNull());
    other_type = other.TypeAt(i);
    ASSERT(!other_type.IsNull());
    if (!type.TypeTest(test_kind, other_type, malformed_error)) {
      return false;
    }
  }
  return true;
}


const char* AbstractTypeArguments::ToCString() const {
  // AbstractTypeArguments is an abstract class, valid only for representing
  // null.
  if (IsNull()) {
    return "NULL AbstractTypeArguments";
  }
  UNREACHABLE();
  return "AbstractTypeArguments";
}


intptr_t TypeArguments::Length() const {
  ASSERT(!IsNull());
  return Smi::Value(raw_ptr()->length_);
}


RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
  return *TypeAddr(index);
}


void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
  ASSERT(!IsCanonical());
  StorePointer(TypeAddr(index), value.raw());
}


bool TypeArguments::IsResolved() const {
  AbstractType& type = AbstractType::Handle();
  intptr_t num_types = Length();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    if (!type.IsResolved()) {
      return false;
    }
  }
  return true;
}


bool TypeArguments::IsInstantiated() const {
  AbstractType& type = AbstractType::Handle();
  intptr_t num_types = Length();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    ASSERT(!type.IsNull());
    if (!type.IsInstantiated()) {
      return false;
    }
  }
  return true;
}


bool TypeArguments::IsUninstantiatedIdentity() const {
  ASSERT(!IsInstantiated());
  AbstractType& type = AbstractType::Handle();
  intptr_t num_types = Length();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    if (!type.IsTypeParameter()) {
      return false;
    }
    const TypeParameter& type_param = TypeParameter::Cast(type);
    if ((type_param.index() != i)) {
      return false;
    }
  }
  return true;
}


RawAbstractTypeArguments* TypeArguments::InstantiateFrom(
    const AbstractTypeArguments& instantiator_type_arguments) const {
  ASSERT(!IsInstantiated());
  if (!instantiator_type_arguments.IsNull() &&
      IsUninstantiatedIdentity() &&
      (instantiator_type_arguments.Length() == Length())) {
    return instantiator_type_arguments.raw();
  }
  const intptr_t num_types = Length();
  TypeArguments& instantiated_array =
      TypeArguments::Handle(TypeArguments::New(num_types, Heap::kNew));
  AbstractType& type = AbstractType::Handle();
  for (intptr_t i = 0; i < num_types; i++) {
    type = TypeAt(i);
    if (!type.IsInstantiated()) {
      type = type.InstantiateFrom(instantiator_type_arguments);
    }
    instantiated_array.SetTypeAt(i, type);
  }
  return instantiated_array.raw();
}


RawTypeArguments* TypeArguments::New(intptr_t len, Heap::Space space) {
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in TypeArguments::New: invalid len %"Pd"\n", len);
  }
  TypeArguments& result = TypeArguments::Handle();
  {
    RawObject* raw = Object::Allocate(TypeArguments::kClassId,
                                      TypeArguments::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    // Length must be set before we start storing into the array.
    result.SetLength(len);
  }
  return result.raw();
}



RawAbstractType** TypeArguments::TypeAddr(intptr_t index) const {
  // TODO(iposva): Determine if we should throw an exception here.
  ASSERT((index >= 0) && (index < Length()));
  return &raw_ptr()->types_[index];
}


void TypeArguments::SetLength(intptr_t value) const {
  ASSERT(!IsCanonical());
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  raw_ptr()->length_ = Smi::New(value);
}


RawAbstractTypeArguments* TypeArguments::Canonicalize() const {
  if (IsNull() || IsCanonical()) {
    ASSERT(IsOld());
    return this->raw();
  }
  ObjectStore* object_store = Isolate::Current()->object_store();
  // 'table' must be null terminated.
  Array& table = Array::Handle(object_store->canonical_type_arguments());
  ASSERT(table.Length() > 0);
  intptr_t index = 0;
  TypeArguments& result = TypeArguments::Handle();
  result ^= table.At(index);
  while (!result.IsNull()) {
    if (this->Equals(result)) {
      return result.raw();
    }
    result ^= table.At(++index);
  }
  // Not found. Add 'this' to table.
  result ^= this->raw();
  if (result.IsNew()) {
    result ^= Object::Clone(result, Heap::kOld);
  }
  ASSERT(result.IsOld());
  if (index == table.Length() - 1) {
    table = Array::Grow(table, table.Length() + 4, Heap::kOld);
    object_store->set_canonical_type_arguments(table);
  }
  table.SetAt(index, result);
  result.SetCanonical();
  return result.raw();
}


const char* TypeArguments::ToCString() const {
  if (IsNull()) {
    return "NULL TypeArguments";
  }
  const char* format = "%s [%s]";
  const char* prev_cstr = "TypeArguments:";
  for (int i = 0; i < Length(); i++) {
    const AbstractType& type_at = AbstractType::Handle(TypeAt(i));
    const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString();
    intptr_t len = OS::SNPrint(NULL, 0, format, prev_cstr, type_cstr) + 1;
    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
    OS::SNPrint(chars, len, format, prev_cstr, type_cstr);
    prev_cstr = chars;
  }
  return prev_cstr;
}


intptr_t InstantiatedTypeArguments::Length() const {
  return AbstractTypeArguments::Handle(
      uninstantiated_type_arguments()).Length();
}


RawAbstractType* InstantiatedTypeArguments::TypeAt(intptr_t index) const {
  const AbstractType& type = AbstractType::Handle(
      AbstractTypeArguments::Handle(
          uninstantiated_type_arguments()).TypeAt(index));
  if (!type.IsInstantiated()) {
    const AbstractTypeArguments& instantiator_type_args =
        AbstractTypeArguments::Handle(instantiator_type_arguments());
    return type.InstantiateFrom(instantiator_type_args);
  }
  return type.raw();
}


void InstantiatedTypeArguments::SetTypeAt(intptr_t index,
                                          const AbstractType& value) const {
  // We only replace individual argument types during resolution at compile
  // time, when no type parameters are instantiated yet.
  UNREACHABLE();
}


void InstantiatedTypeArguments::set_uninstantiated_type_arguments(
    const AbstractTypeArguments& value) const {
  StorePointer(&raw_ptr()->uninstantiated_type_arguments_, value.raw());
}


void InstantiatedTypeArguments::set_instantiator_type_arguments(
    const AbstractTypeArguments& value) const {
  StorePointer(&raw_ptr()->instantiator_type_arguments_, value.raw());
}


RawInstantiatedTypeArguments* InstantiatedTypeArguments::New() {
  ASSERT(Object::instantiated_type_arguments_class() != Class::null());
  RawObject* raw = Object::Allocate(InstantiatedTypeArguments::kClassId,
                                    InstantiatedTypeArguments::InstanceSize(),
                                    Heap::kNew);
  return reinterpret_cast<RawInstantiatedTypeArguments*>(raw);
}


RawInstantiatedTypeArguments* InstantiatedTypeArguments::New(
    const AbstractTypeArguments& uninstantiated_type_arguments,
    const AbstractTypeArguments& instantiator_type_arguments) {
  const InstantiatedTypeArguments& result =
      InstantiatedTypeArguments::Handle(InstantiatedTypeArguments::New());
  result.set_uninstantiated_type_arguments(uninstantiated_type_arguments);
  result.set_instantiator_type_arguments(instantiator_type_arguments);
  return result.raw();
}


const char* InstantiatedTypeArguments::ToCString() const {
  if (IsNull()) {
    return "NULL InstantiatedTypeArguments";
  }
  const char* format = "InstantiatedTypeArguments: [%s] instantiator: [%s]";
  const char* arg_cstr =
      AbstractTypeArguments::Handle(
          uninstantiated_type_arguments()).ToCString();
  const char* instantiator_cstr =
      AbstractTypeArguments::Handle(instantiator_type_arguments()).ToCString();
  intptr_t len =
      OS::SNPrint(NULL, 0, format, arg_cstr, instantiator_cstr) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, format, arg_cstr, instantiator_cstr);
  return chars;
}


const char* PatchClass::ToCString() const {
  const char* kFormat = "PatchClass for %s";
  const Class& cls = Class::Handle(patched_class());
  const char* cls_name = cls.ToCString();
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, cls_name) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, cls_name);
  return chars;
}


RawPatchClass* PatchClass::New(const Class& patched_class,
                               const Script& script) {
  const PatchClass& result = PatchClass::Handle(PatchClass::New());
  result.set_patched_class(patched_class);
  result.set_script(script);
  return result.raw();
}


RawPatchClass* PatchClass::New() {
  ASSERT(Object::patch_class_class() != Class::null());
  RawObject* raw = Object::Allocate(PatchClass::kClassId,
                                    PatchClass::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawPatchClass*>(raw);
}


void PatchClass::set_patched_class(const Class& value) const {
  StorePointer(&raw_ptr()->patched_class_, value.raw());
}


void PatchClass::set_script(const Script& value) const {
  StorePointer(&raw_ptr()->script_, value.raw());
}


void Function::SetCode(const Code& value) const {
  StorePointer(&raw_ptr()->code_, value.raw());
  ASSERT(Function::Handle(value.function()).IsNull() ||
    (value.function() == this->raw()));
  value.set_function(*this);
}


void Function::SwitchToUnoptimizedCode() const {
  ASSERT(HasOptimizedCode());
  const Code& current_code = Code::Handle(CurrentCode());
  if (FLAG_trace_disabling_optimized_code) {
    OS::Print("Disabling optimized code: '%s' entry: %#"Px"\n",
      ToFullyQualifiedCString(),
      current_code.EntryPoint());
  }
  // Patch entry of the optimized code.
  CodePatcher::PatchEntry(current_code);
  // Use previously compiled unoptimized code.
  SetCode(Code::Handle(unoptimized_code()));
  CodePatcher::RestoreEntry(Code::Handle(unoptimized_code()));
}


void Function::set_unoptimized_code(const Code& value) const {
  StorePointer(&raw_ptr()->unoptimized_code_, value.raw());
}


RawContextScope* Function::context_scope() const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).context_scope();
  }
  return ContextScope::null();
}


void Function::set_context_scope(const ContextScope& value) const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_context_scope(value);
    return;
  }
  UNREACHABLE();
}


RawInstance* Function::implicit_static_closure() const {
  if (IsImplicitStaticClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).implicit_static_closure();
  }
  return Instance::null();
}


void Function::set_implicit_static_closure(const Instance& closure) const {
  if (IsImplicitStaticClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_implicit_static_closure(closure);
    return;
  }
  UNREACHABLE();
}


RawCode* Function::closure_allocation_stub() const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).closure_allocation_stub();
  }
  return Code::null();
}


void Function::set_closure_allocation_stub(const Code& value) const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_closure_allocation_stub(value);
    return;
  }
  UNREACHABLE();
}


RawFunction* Function::parent_function() const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).parent_function();
  }
  return Function::null();
}


void Function::set_parent_function(const Function& value) const {
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_parent_function(value);
    return;
  }
  UNREACHABLE();
}


RawFunction* Function::implicit_closure_function() const {
  if (IsClosureFunction() || IsSignatureFunction()) {
    return Function::null();
  }
  const Object& obj = Object::Handle(raw_ptr()->data_);
  ASSERT(obj.IsNull() || obj.IsFunction());
  return (obj.IsNull()) ? Function::null() : Function::Cast(obj).raw();
}


void Function::set_implicit_closure_function(const Function& value) const {
  ASSERT(!IsClosureFunction() && !IsSignatureFunction());
  set_data(value);
}


RawClass* Function::signature_class() const {
  if (IsSignatureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(obj.IsNull() || obj.IsClass());
    return (obj.IsNull()) ? Class::null() : Class::Cast(obj).raw();
  }
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    return ClosureData::Cast(obj).signature_class();
  }
  return Class::null();
}


void Function::set_signature_class(const Class& value) const {
  if (IsSignatureFunction()) {
    set_data(value);
    return;
  }
  if (IsClosureFunction()) {
    const Object& obj = Object::Handle(raw_ptr()->data_);
    ASSERT(!obj.IsNull());
    ClosureData::Cast(obj).set_signature_class(value);
    return;
  }
  UNREACHABLE();
}


bool Function::IsRedirectingFactory() const {
  if (!IsFactory() || (raw_ptr()->data_ == Object::null())) {
    return false;
  }
  ASSERT(!IsClosureFunction());  // A factory cannot also be a closure.
  return true;
}


RawType* Function::RedirectionType() const {
  ASSERT(IsRedirectingFactory());
  const Object& obj = Object::Handle(raw_ptr()->data_);
  ASSERT(!obj.IsNull());
  return RedirectionData::Cast(obj).type();
}


void Function::SetRedirectionType(const Type& type) const {
  ASSERT(IsFactory());
  Object& obj = Object::Handle(raw_ptr()->data_);
  if (obj.IsNull()) {
    obj = RedirectionData::New();
    set_data(obj);
  }
  RedirectionData::Cast(obj).set_type(type);
}


RawString* Function::RedirectionIdentifier() const {
  ASSERT(IsRedirectingFactory());
  const Object& obj = Object::Handle(raw_ptr()->data_);
  ASSERT(!obj.IsNull());
  return RedirectionData::Cast(obj).identifier();
}


void Function::SetRedirectionIdentifier(const String& identifier) const {
  ASSERT(IsFactory());
  Object& obj = Object::Handle(raw_ptr()->data_);
  if (obj.IsNull()) {
    obj = RedirectionData::New();
    set_data(obj);
  }
  RedirectionData::Cast(obj).set_identifier(identifier);
}


RawFunction* Function::RedirectionTarget() const {
  ASSERT(IsRedirectingFactory());
  const Object& obj = Object::Handle(raw_ptr()->data_);
  ASSERT(!obj.IsNull());
  return RedirectionData::Cast(obj).target();
}


void Function::SetRedirectionTarget(const Function& target) const {
  ASSERT(IsFactory());
  Object& obj = Object::Handle(raw_ptr()->data_);
  if (obj.IsNull()) {
    obj = RedirectionData::New();
    set_data(obj);
  }
  RedirectionData::Cast(obj).set_target(target);
}


void Function::set_data(const Object& value) const {
  StorePointer(&raw_ptr()->data_, value.raw());
}


bool Function::IsInFactoryScope() const {
  if (!IsLocalFunction()) {
    return IsFactory();
  }
  Function& outer_function = Function::Handle(parent_function());
  while (outer_function.IsLocalFunction()) {
    outer_function = outer_function.parent_function();
  }
  return outer_function.IsFactory();
}


void Function::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  StorePointer(&raw_ptr()->name_, value.raw());
}


void Function::set_owner(const Object& value) const {
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->owner_, value.raw());
}


void Function::set_result_type(const AbstractType& value) const {
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->result_type_, value.raw());
}


RawAbstractType* Function::ParameterTypeAt(intptr_t index) const {
  const Array& parameter_types = Array::Handle(raw_ptr()->parameter_types_);
  AbstractType& parameter_type = AbstractType::Handle();
  parameter_type ^= parameter_types.At(index);
  return parameter_type.raw();
}


void Function::SetParameterTypeAt(
    intptr_t index, const AbstractType& value) const {
  ASSERT(!value.IsNull());
  const Array& parameter_types = Array::Handle(raw_ptr()->parameter_types_);
  parameter_types.SetAt(index, value);
}


void Function::set_parameter_types(const Array& value) const {
  StorePointer(&raw_ptr()->parameter_types_, value.raw());
}


RawString* Function::ParameterNameAt(intptr_t index) const {
  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names_);
  String& parameter_name = String::Handle();
  parameter_name ^= parameter_names.At(index);
  return parameter_name.raw();
}


void Function::SetParameterNameAt(intptr_t index, const String& value) const {
  ASSERT(!value.IsNull() && value.IsSymbol());
  const Array& parameter_names = Array::Handle(raw_ptr()->parameter_names_);
  parameter_names.SetAt(index, value);
}


void Function::set_parameter_names(const Array& value) const {
  StorePointer(&raw_ptr()->parameter_names_, value.raw());
}


void Function::set_kind(RawFunction::Kind value) const {
  set_kind_tag(KindBits::update(value, raw_ptr()->kind_tag_));
}


void Function::set_intrinsic_kind(IntrinsicKind value) const {
  set_kind_tag(IntrinsicKindBits::update(value, raw_ptr()->kind_tag_));
}


void Function::set_is_static(bool value) const {
  set_kind_tag(StaticBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_is_const(bool value) const {
  set_kind_tag(ConstBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_is_external(bool value) const {
  set_kind_tag(ExternalBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_token_pos(intptr_t value) const {
  ASSERT(value >= 0);
  raw_ptr()->token_pos_ = value;
}


void Function::set_kind_tag(intptr_t value) const {
  raw_ptr()->kind_tag_ = static_cast<uint16_t>(value);
}


void Function::set_num_fixed_parameters(intptr_t value) const {
  ASSERT(value >= 0);
  ASSERT(Utils::IsInt(16, value));
  raw_ptr()->num_fixed_parameters_ = static_cast<int16_t>(value);
}


void Function::set_num_optional_parameters(intptr_t value) const {
  // A positive value indicates positional params, a negative one named params.
  ASSERT(Utils::IsInt(16, value));
  raw_ptr()->num_optional_parameters_ = static_cast<int16_t>(value);
}


void Function::SetNumOptionalParameters(intptr_t num_optional_parameters,
                                        bool are_optional_positional) const {
  ASSERT(num_optional_parameters >= 0);
  set_num_optional_parameters(are_optional_positional ?
                              num_optional_parameters :
                              -num_optional_parameters);
}


bool Function::is_optimizable() const {
  return OptimizableBit::decode(raw_ptr()->kind_tag_) &&
         (script() != Script::null()) &&
         !is_native();
}


void Function::set_is_optimizable(bool value) const {
  set_kind_tag(OptimizableBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_has_finally(bool value) const {
  set_kind_tag(HasFinallyBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_is_native(bool value) const {
  set_kind_tag(NativeBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_is_abstract(bool value) const {
  set_kind_tag(AbstractBit::update(value, raw_ptr()->kind_tag_));
}


void Function::set_is_inlinable(bool value) const {
  set_kind_tag(InlinableBit::update(value, raw_ptr()->kind_tag_));
}


bool Function::IsInlineable() const {
  // '==' call is handled specially.
  const String& equality_name = String::Handle(Symbols::EqualOperator());
  return InlinableBit::decode(raw_ptr()->kind_tag_) &&
         HasCode() &&
         name() != equality_name.raw();
}


intptr_t Function::NumParameters() const {
  return num_fixed_parameters() + NumOptionalParameters();
}


intptr_t Function::NumImplicitParameters() const {
  if (kind() == RawFunction::kConstructor) {
    if (is_static()) {
      ASSERT(IsFactory());
      return 1;  // Type arguments.
    } else {
      ASSERT(IsConstructor());
      return 2;  // Instance, phase.
    }
  }
  if ((kind() == RawFunction::kClosureFunction) ||
      (kind() == RawFunction::kSignatureFunction)) {
    return 1;  // Closure object.
  }
  if (!is_static()) {
    // Closure functions defined inside instance (i.e. non-static) functions are
    // marked as non-static, but they do not have a receiver.
    // Closures are handled above.
    ASSERT((kind() != RawFunction::kClosureFunction) &&
           (kind() != RawFunction::kSignatureFunction));
    return 1;  // Receiver.
  }
  return 0;  // No implicit parameters.
}


bool Function::AreValidArgumentCounts(int num_arguments,
                                      int num_named_arguments,
                                      String* error_message) const {
  if (num_named_arguments > NumOptionalNamedParameters()) {
    if (error_message != NULL) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      OS::SNPrint(message_buffer,
                  kMessageBufferSize,
                  "%d named passed, at most %"Pd" expected",
                  num_named_arguments,
                  NumOptionalNamedParameters());
      *error_message = String::New(message_buffer);
    }
    return false;  // Too many named arguments.
  }
  const int num_pos_args = num_arguments - num_named_arguments;
  const int num_opt_pos_params = NumOptionalPositionalParameters();
  const int num_pos_params = num_fixed_parameters() + num_opt_pos_params;
  if (num_pos_args > num_pos_params) {
    if (error_message != NULL) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      // Hide implicit parameters to the user.
      const intptr_t num_hidden_params = NumImplicitParameters();
      OS::SNPrint(message_buffer,
                  kMessageBufferSize,
                  "%"Pd"%s passed, %s%"Pd" expected",
                  num_pos_args - num_hidden_params,
                  num_opt_pos_params > 0 ? " positional" : "",
                  num_opt_pos_params > 0 ? "at most " : "",
                  num_pos_params - num_hidden_params);
      *error_message = String::New(message_buffer);
    }
    return false;  // Too many fixed and/or positional arguments.
  }
  if (num_pos_args < num_fixed_parameters()) {
    if (error_message != NULL) {
      const intptr_t kMessageBufferSize = 64;
      char message_buffer[kMessageBufferSize];
      // Hide implicit parameters to the user.
      const intptr_t num_hidden_params = NumImplicitParameters();
      OS::SNPrint(message_buffer,
                  kMessageBufferSize,
                  "%"Pd"%s passed, %s%"Pd" expected",
                  num_pos_args - num_hidden_params,
                  num_opt_pos_params > 0 ? " positional" : "",
                  num_opt_pos_params > 0 ? "at least " : "",
                  num_fixed_parameters() - num_hidden_params);
      *error_message = String::New(message_buffer);
    }
    return false;  // Too few fixed and/or positional arguments.
  }
  return true;
}


bool Function::AreValidArguments(int num_arguments,
                                 const Array& argument_names,
                                 String* error_message) const {
  const int num_named_arguments =
      argument_names.IsNull() ? 0 : argument_names.Length();
  if (!AreValidArgumentCounts(num_arguments,
                              num_named_arguments,
                              error_message)) {
    return false;
  }
  // Verify that all argument names are valid parameter names.
  String& argument_name = String::Handle();
  String& parameter_name = String::Handle();
  for (int i = 0; i < num_named_arguments; i++) {
    argument_name ^= argument_names.At(i);
    ASSERT(argument_name.IsSymbol());
    bool found = false;
    const int num_positional_args = num_arguments - num_named_arguments;
    const int num_parameters = NumParameters();
    for (int j = num_positional_args; !found && (j < num_parameters); j++) {
      parameter_name ^= ParameterNameAt(j);
      ASSERT(argument_name.IsSymbol());
      if (argument_name.Equals(parameter_name)) {
        found = true;
      }
    }
    if (!found) {
      if (error_message != NULL) {
        const intptr_t kMessageBufferSize = 64;
        char message_buffer[kMessageBufferSize];
        OS::SNPrint(message_buffer,
                    kMessageBufferSize,
                    "no optional formal parameter named '%s'",
                    argument_name.ToCString());
        *error_message = String::New(message_buffer);
      }
      return false;
    }
  }
  return true;
}


// Helper allocating a C string buffer in the zone, printing the fully qualified
// name of a function in it, and replacing ':' by '_' to make sure the
// constructed name is a valid C++ identifier for debugging purpose.
// Set 'chars' to allocated buffer and return number of written characters.
static intptr_t ConstructFunctionFullyQualifiedCString(const Function& function,
                                                       char** chars,
                                                       intptr_t reserve_len) {
  const char* name = String::Handle(function.name()).ToCString();
  const char* function_format = (reserve_len == 0) ? "%s" : "%s_";
  reserve_len += OS::SNPrint(NULL, 0, function_format, name);
  const Function& parent = Function::Handle(function.parent_function());
  intptr_t written = 0;
  if (parent.IsNull()) {
    const Class& function_class = Class::Handle(function.Owner());
    ASSERT(!function_class.IsNull());
    const char* class_name = String::Handle(function_class.Name()).ToCString();
    ASSERT(class_name != NULL);
    const Library& library = Library::Handle(function_class.library());
    ASSERT(!library.IsNull());
    const char* library_name = String::Handle(library.url()).ToCString();
    ASSERT(library_name != NULL);
    const char* lib_class_format =
        (library_name[0] == '\0') ? "%s%s_" : "%s_%s_";
    reserve_len +=
        OS::SNPrint(NULL, 0, lib_class_format, library_name, class_name);
    ASSERT(chars != NULL);
    *chars = Isolate::Current()->current_zone()->Alloc<char>(reserve_len + 1);
    written = OS::SNPrint(
        *chars, reserve_len + 1, lib_class_format, library_name, class_name);
  } else {
    written = ConstructFunctionFullyQualifiedCString(parent,
                                                     chars,
                                                     reserve_len);
  }
  ASSERT(*chars != NULL);
  char* next = *chars + written;
  written += OS::SNPrint(next, reserve_len + 1, function_format, name);
  // Replace ":" with "_".
  while (true) {
    next = strchr(next, ':');
    if (next == NULL) break;
    *next = '_';
  }
  return written;
}


const char* Function::ToFullyQualifiedCString() const {
  char* chars = NULL;
  ConstructFunctionFullyQualifiedCString(*this, &chars, 0);
  return chars;
}


bool Function::HasCompatibleParametersWith(const Function& other) const {
  const intptr_t num_fixed_params = num_fixed_parameters();
  const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
  const intptr_t num_opt_named_params = NumOptionalNamedParameters();
  const intptr_t other_num_fixed_params = other.num_fixed_parameters();
  const intptr_t other_num_opt_pos_params =
      other.NumOptionalPositionalParameters();
  const intptr_t other_num_opt_named_params =
      other.NumOptionalNamedParameters();
  // A generative constructor may be compared to a redirecting factory and be
  // compatible although it has an additional phase parameter.
  const intptr_t num_ignored_params =
      (other.IsRedirectingFactory() && IsConstructor()) ? 1 : 0;
  // The default values of optional parameters can differ.
  if (((num_fixed_params - num_ignored_params) != other_num_fixed_params) ||
      (num_opt_pos_params < other_num_opt_pos_params) ||
      (num_opt_named_params < other_num_opt_named_params)) {
    return false;
  }
  if (other_num_opt_named_params == 0) {
    return true;
  }
  // Check that for each optional named parameter of the other function there
  // exists an optional named parameter of this function with an identical
  // name.
  // Note that SetParameterNameAt() guarantees that names are symbols, so we
  // can compare their raw pointers.
  const int num_params = num_fixed_params + num_opt_named_params;
  const int other_num_params =
      other_num_fixed_params + other_num_opt_named_params;
  bool found_param_name;
  String& other_param_name = String::Handle();
  for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) {
    other_param_name = other.ParameterNameAt(i);
    found_param_name = false;
    for (intptr_t j = num_fixed_params; j < num_params; j++) {
      if (ParameterNameAt(j) == other_param_name.raw()) {
        found_param_name = true;
        break;
      }
    }
    if (!found_param_name) {
      return false;
    }
  }
  return true;
}


// If test_kind == kIsSubtypeOf, checks if the type of the specified parameter
// of this function is a subtype or a supertype of the type of the specified
// parameter of the other function.
// If test_kind == kIsMoreSpecificThan, checks if the type of the specified
// parameter of this function is more specific than the type of the specified
// parameter of the other function.
// Note that we do not apply contravariance of parameter types, but covariance
// of both parameter types and result type.
bool Function::TestParameterType(
    TypeTestKind test_kind,
    intptr_t parameter_position,
    intptr_t other_parameter_position,
    const AbstractTypeArguments& type_arguments,
    const Function& other,
    const AbstractTypeArguments& other_type_arguments,
    Error* malformed_error) const {
  AbstractType& other_param_type =
      AbstractType::Handle(other.ParameterTypeAt(other_parameter_position));
  if (!other_param_type.IsInstantiated()) {
    other_param_type = other_param_type.InstantiateFrom(other_type_arguments);
  }
  if (other_param_type.IsDynamicType()) {
    return true;
  }
  AbstractType& param_type =
      AbstractType::Handle(ParameterTypeAt(parameter_position));
  if (!param_type.IsInstantiated()) {
    param_type = param_type.InstantiateFrom(type_arguments);
  }
  if (param_type.IsDynamicType()) {
    return test_kind == kIsSubtypeOf;
  }
  if (test_kind == kIsSubtypeOf) {
    if (!param_type.IsSubtypeOf(other_param_type, malformed_error) &&
        !other_param_type.IsSubtypeOf(param_type, malformed_error)) {
      return false;
    }
  } else {
    ASSERT(test_kind == kIsMoreSpecificThan);
    if (!param_type.IsMoreSpecificThan(other_param_type, malformed_error)) {
      return false;
    }
  }
  return true;
}


bool Function::TypeTest(TypeTestKind test_kind,
                        const AbstractTypeArguments& type_arguments,
                        const Function& other,
                        const AbstractTypeArguments& other_type_arguments,
                        Error* malformed_error) const {
  const intptr_t num_fixed_params = num_fixed_parameters();
  const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
  const intptr_t num_opt_named_params = NumOptionalNamedParameters();
  const intptr_t other_num_fixed_params = other.num_fixed_parameters();
  const intptr_t other_num_opt_pos_params =
      other.NumOptionalPositionalParameters();
  const intptr_t other_num_opt_named_params =
      other.NumOptionalNamedParameters();
  if ((num_fixed_params != other_num_fixed_params) ||
      (num_opt_pos_params < other_num_opt_pos_params) ||
      (num_opt_named_params < other_num_opt_named_params)) {
    return false;
  }
  // Check the result type.
  AbstractType& other_res_type = AbstractType::Handle(other.result_type());
  if (!other_res_type.IsInstantiated()) {
    other_res_type = other_res_type.InstantiateFrom(other_type_arguments);
  }
  if (!other_res_type.IsDynamicType() && !other_res_type.IsVoidType()) {
    AbstractType& res_type = AbstractType::Handle(result_type());
    if (!res_type.IsInstantiated()) {
      res_type = res_type.InstantiateFrom(type_arguments);
    }
    if (res_type.IsVoidType()) {
      return false;
    }
    if (test_kind == kIsSubtypeOf) {
      if (!res_type.IsSubtypeOf(other_res_type, malformed_error) &&
          !other_res_type.IsSubtypeOf(res_type, malformed_error)) {
        return false;
      }
    } else {
      ASSERT(test_kind == kIsMoreSpecificThan);
      if (!res_type.IsMoreSpecificThan(other_res_type, malformed_error)) {
        return false;
      }
    }
  }
  // Check the types of fixed and optional positional parameters.
  for (intptr_t i = 0; i < num_fixed_params + other_num_opt_pos_params; i++) {
    if (!TestParameterType(test_kind,
                           i, i, type_arguments, other, other_type_arguments,
                           malformed_error)) {
      return false;
    }
  }
  // Check the names and types of optional named parameters.
  if (other_num_opt_named_params == 0) {
    return true;
  }
  // Check that for each optional named parameter of type T of the other
  // function type, there exists an optional named parameter of this function
  // type with an identical name and with a type S that is a either a subtype
  // or supertype of T (if test_kind == kIsSubtypeOf) or that is more specific
  // than T (if test_kind == kIsMoreSpecificThan).
  // Note that SetParameterNameAt() guarantees that names are symbols, so we
  // can compare their raw pointers.
  const int num_params = num_fixed_params + num_opt_named_params;
  const int other_num_params =
      other_num_fixed_params + other_num_opt_named_params;
  bool found_param_name;
  String& other_param_name = String::Handle();
  for (intptr_t i = other_num_fixed_params; i < other_num_params; i++) {
    other_param_name = other.ParameterNameAt(i);
    ASSERT(other_param_name.IsSymbol());
    found_param_name = false;
    for (intptr_t j = num_fixed_params; j < num_params; j++) {
      ASSERT(String::Handle(ParameterNameAt(j)).IsSymbol());
      if (ParameterNameAt(j) == other_param_name.raw()) {
        found_param_name = true;
        if (!TestParameterType(test_kind,
                               j, i,
                               type_arguments, other, other_type_arguments,
                               malformed_error)) {
          return false;
        }
        break;
      }
    }
    if (!found_param_name) {
      return false;
    }
  }
  return true;
}


bool Function::IsImplicitClosureFunction() const {
  if (!IsClosureFunction()) {
    return false;
  }
  const Function& parent = Function::Handle(parent_function());
  return (parent.implicit_closure_function() == raw());
}


RawFunction* Function::New() {
  ASSERT(Object::function_class() != Class::null());
  RawObject* raw = Object::Allocate(Function::kClassId,
                                    Function::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawFunction*>(raw);
}


RawFunction* Function::New(const String& name,
                           RawFunction::Kind kind,
                           bool is_static,
                           bool is_const,
                           bool is_abstract,
                           bool is_external,
                           const Object& owner,
                           intptr_t token_pos) {
  ASSERT(name.IsOneByteString());
  ASSERT(!owner.IsNull());
  const Function& result = Function::Handle(Function::New());
  const Array& empty_array = Array::Handle(Object::empty_array());
  result.set_parameter_types(empty_array);
  result.set_parameter_names(empty_array);
  result.set_name(name);
  result.set_kind(kind);
  result.set_is_static(is_static);
  result.set_is_const(is_const);
  result.set_is_abstract(is_abstract);
  result.set_is_external(is_external);
  result.set_intrinsic_kind(kUnknownIntrinsic);
  result.set_owner(owner);
  result.set_token_pos(token_pos);
  result.set_end_token_pos(token_pos);
  result.set_num_fixed_parameters(0);
  result.set_num_optional_parameters(0);
  result.set_usage_counter(0);
  result.set_deoptimization_counter(0);
  result.set_is_optimizable(true);
  result.set_has_finally(false);
  result.set_is_native(false);
  result.set_is_inlinable(true);
  if (kind == RawFunction::kClosureFunction) {
    const ClosureData& data = ClosureData::Handle(ClosureData::New());
    result.set_data(data);
  }
  return result.raw();
}


RawFunction* Function::NewClosureFunction(const String& name,
                                          const Function& parent,
                                          intptr_t token_pos) {
  ASSERT(name.IsOneByteString());
  ASSERT(!parent.IsNull());
  // Use the owner defining the parent function and not the class containing it.
  const Object& parent_owner = Object::Handle(parent.raw_ptr()->owner_);
  ASSERT(!parent_owner.IsNull());
  const Function& result = Function::Handle(
      Function::New(name,
                    RawFunction::kClosureFunction,
                    /* is_static = */ parent.is_static(),
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    /* is_external = */ false,
                    parent_owner,
                    token_pos));
  result.set_parent_function(parent);
  return result.raw();
}


RawFunction* Function::ImplicitClosureFunction() const {
  // Return the existing implicit closure function if any.
  if (implicit_closure_function() != Function::null()) {
    return implicit_closure_function();
  }
  ASSERT(!IsSignatureFunction() && !IsClosureFunction());
  // Create closure function.
  const String& closure_name = String::Handle(name());
  const Function& closure_function = Function::Handle(
      NewClosureFunction(closure_name, *this, token_pos()));

  // Set closure function's context scope.
  ContextScope& context_scope = ContextScope::Handle();
  if (is_static()) {
    context_scope ^= ContextScope::New(0);
  } else {
    context_scope ^= LocalScope::CreateImplicitClosureScope(*this);
  }
  closure_function.set_context_scope(context_scope);

  // Set closure function's result type to this result type.
  closure_function.set_result_type(AbstractType::Handle(result_type()));

  // Set closure function's formal parameters to this formal parameters,
  // removing the receiver if this is an instance method and adding the closure
  // object as first parameter.
  const int kClosure = 1;
  const int has_receiver = is_static() ? 0 : 1;
  const int num_fixed_params = kClosure - has_receiver + num_fixed_parameters();
  const int num_opt_params = NumOptionalParameters();
  const bool has_opt_pos_params = HasOptionalPositionalParameters();
  const int num_params = num_fixed_params + num_opt_params;
  closure_function.set_num_fixed_parameters(num_fixed_params);
  closure_function.SetNumOptionalParameters(num_opt_params, has_opt_pos_params);
  closure_function.set_parameter_types(Array::Handle(Array::New(num_params,
                                                                Heap::kOld)));
  closure_function.set_parameter_names(Array::Handle(Array::New(num_params,
                                                                Heap::kOld)));
  AbstractType& param_type = AbstractType::Handle();
  String& param_name = String::Handle();
  // Add implicit closure object parameter.
  param_type = Type::DynamicType();
  closure_function.SetParameterTypeAt(0, param_type);
  param_name = Symbols::ClosureParameter();
  closure_function.SetParameterNameAt(0, param_name);
  for (int i = kClosure; i < num_params; i++) {
    param_type = ParameterTypeAt(has_receiver - kClosure + i);
    closure_function.SetParameterTypeAt(i, param_type);
    param_name = ParameterNameAt(has_receiver - kClosure + i);
    closure_function.SetParameterNameAt(i, param_name);
  }

  // Lookup or create a new signature class for the closure function in the
  // library of the owner class.
  const Class& owner_class = Class::Handle(Owner());
  ASSERT(!owner_class.IsNull() && (Owner() == closure_function.Owner()));
  const Library& library = Library::Handle(owner_class.library());
  ASSERT(!library.IsNull());
  const String& signature = String::Handle(closure_function.Signature());
  Class& signature_class = Class::ZoneHandle(
      library.LookupLocalClass(signature));
  if (signature_class.IsNull()) {
    const Script& script = Script::Handle(this->script());
    signature_class = Class::NewSignatureClass(signature,
                                               closure_function,
                                               script);
    library.AddClass(signature_class);
  } else {
    closure_function.set_signature_class(signature_class);
  }
  const Type& signature_type = Type::Handle(signature_class.SignatureType());
  if (!signature_type.IsFinalized()) {
    ClassFinalizer::FinalizeType(
        signature_class, signature_type, ClassFinalizer::kCanonicalize);
  }
  ASSERT(closure_function.signature_class() == signature_class.raw());
  set_implicit_closure_function(closure_function);
  ASSERT(closure_function.IsImplicitClosureFunction());
  return closure_function.raw();
}


RawString* Function::BuildSignature(
    bool instantiate,
    NameVisibility name_visibility,
    const AbstractTypeArguments& instantiator) const {
  const GrowableObjectArray& pieces =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  const String& kCommaSpace = String::Handle(Symbols::New(", "));
  const String& kColonSpace = String::Handle(Symbols::New(": "));
  const String& kLParen = String::Handle(Symbols::New("("));
  const String& kRParenArrow = String::Handle(Symbols::New(") => "));
  const String& kLBracket = String::Handle(Symbols::New("["));
  const String& kRBracket = String::Handle(Symbols::New("]"));
  const String& kLBrace = String::Handle(Symbols::New("{"));
  const String& kRBrace = String::Handle(Symbols::New("}"));
  String& name = String::Handle();
  if (!instantiate && !is_static() && (name_visibility == kInternalName)) {
    // Prefix the signature with its class and type parameters, if any (e.g.
    // "Map<K, V>(K) => bool").
    // The signature of static functions cannot be type parameterized.
    const String& kSpaceExtendsSpace =
        String::Handle(Symbols::New(" extends "));
    const String& kLAngleBracket = String::Handle(Symbols::New("<"));
    const String& kRAngleBracket = String::Handle(Symbols::New(">"));
    const Class& function_class = Class::Handle(Owner());
    ASSERT(!function_class.IsNull());
    const TypeArguments& type_parameters = TypeArguments::Handle(
        function_class.type_parameters());
    if (!type_parameters.IsNull()) {
      const String& function_class_name = String::Handle(function_class.Name());
      pieces.Add(function_class_name);
      intptr_t num_type_parameters = type_parameters.Length();
      pieces.Add(kLAngleBracket);
      TypeParameter& type_parameter = TypeParameter::Handle();
      AbstractType& bound = AbstractType::Handle();
      for (intptr_t i = 0; i < num_type_parameters; i++) {
        type_parameter ^= type_parameters.TypeAt(i);
        name = type_parameter.name();
        pieces.Add(name);
        bound = type_parameter.bound();
        if (!bound.IsNull() && !bound.IsObjectType()) {
          pieces.Add(kSpaceExtendsSpace);
          name = bound.BuildName(name_visibility);
          pieces.Add(name);
        }
        if (i < num_type_parameters - 1) {
          pieces.Add(kCommaSpace);
        }
      }
      pieces.Add(kRAngleBracket);
    }
  }
  AbstractType& param_type = AbstractType::Handle();
  const intptr_t num_params = NumParameters();
  const intptr_t num_fixed_params = num_fixed_parameters();
  const intptr_t num_opt_pos_params = NumOptionalPositionalParameters();
  const intptr_t num_opt_named_params = NumOptionalNamedParameters();
  const intptr_t num_opt_params = num_opt_pos_params + num_opt_named_params;
  ASSERT((num_fixed_params + num_opt_params) == num_params);
  pieces.Add(kLParen);
  intptr_t i = 0;
  if (name_visibility == kUserVisibleName) {
    // Hide implicit parameters.
    i = NumImplicitParameters();
  }
  while (i < num_fixed_params) {
    param_type = ParameterTypeAt(i);
    ASSERT(!param_type.IsNull());
    if (instantiate && !param_type.IsInstantiated()) {
      param_type = param_type.InstantiateFrom(instantiator);
    }
    name = param_type.BuildName(name_visibility);
    pieces.Add(name);
    if (i != (num_params - 1)) {
      pieces.Add(kCommaSpace);
    }
    i++;
  }
  if (num_opt_params > 0) {
    if (num_opt_pos_params > 0) {
      pieces.Add(kLBracket);
    } else {
      pieces.Add(kLBrace);
    }
    for (intptr_t i = num_fixed_params; i < num_params; i++) {
      // The parameter name of an optional positional parameter does not need
      // to be part of the signature, since it is not used.
      if (num_opt_named_params > 0) {
        name = ParameterNameAt(i);
        pieces.Add(name);
        pieces.Add(kColonSpace);
      }
      param_type = ParameterTypeAt(i);
      if (instantiate && !param_type.IsInstantiated()) {
        param_type = param_type.InstantiateFrom(instantiator);
      }
      ASSERT(!param_type.IsNull());
      name = param_type.BuildName(name_visibility);
      pieces.Add(name);
      if (i != (num_params - 1)) {
        pieces.Add(kCommaSpace);
      }
    }
    if (num_opt_pos_params > 0) {
      pieces.Add(kRBracket);
    } else {
      pieces.Add(kRBrace);
    }
  }
  pieces.Add(kRParenArrow);
  AbstractType& res_type = AbstractType::Handle(result_type());
  if (instantiate && !res_type.IsInstantiated()) {
    res_type = res_type.InstantiateFrom(instantiator);
  }
  name = res_type.BuildName(name_visibility);
  pieces.Add(name);
  const Array& strings = Array::Handle(Array::MakeArray(pieces));
  return Symbols::New(String::Handle(String::ConcatAll(strings)));
}


bool Function::HasInstantiatedSignature() const {
  AbstractType& type = AbstractType::Handle(result_type());
  if (!type.IsInstantiated()) {
    return false;
  }
  const intptr_t num_parameters = NumParameters();
  for (intptr_t i = 0; i < num_parameters; i++) {
    type = ParameterTypeAt(i);
    if (!type.IsInstantiated()) {
      return false;
    }
  }
  return true;
}


RawClass* Function::Owner() const {
  const Object& obj = Object::Handle(raw_ptr()->owner_);
  if (obj.IsClass()) {
    return Class::Cast(obj).raw();
  }
  ASSERT(obj.IsPatchClass());
  return PatchClass::Cast(obj).patched_class();
}


RawScript* Function::script() const {
  const Object& obj = Object::Handle(raw_ptr()->owner_);
  if (obj.IsClass()) {
    return Class::Cast(obj).script();
  }
  ASSERT(obj.IsPatchClass());
  return PatchClass::Cast(obj).script();
}


bool Function::HasOptimizedCode() const {
  return HasCode() && Code::Handle(raw_ptr()->code_).is_optimized();
}


RawString* Function::UserVisibleName() const {
  const String& str = String::Handle(name());
  return IdentifierPrettyName(str);
}


RawString* Function::QualifiedUserVisibleName() const {
  String& tmp = String::Handle();
  String& suffix = String::Handle();
  const Class& cls = Class::Handle(Owner());

  if (IsClosureFunction()) {
    if (IsLocalFunction()) {
      const Function& parent = Function::Handle(parent_function());
      tmp = parent.QualifiedUserVisibleName();
    } else {
      return UserVisibleName();
    }
  } else {
    if (cls.IsTopLevel()) {
      return UserVisibleName();
    } else {
      tmp = cls.UserVisibleName();
    }
  }
  suffix = Symbols::Dot();
  tmp = String::Concat(tmp, suffix);
  suffix = UserVisibleName();
  return String::Concat(tmp, suffix);
}


// Construct fingerprint from token stream. The token stream contains also
// arguments.
int32_t Function::SourceFingerprint() const {
  uint32_t result = String::Handle(Signature()).Hash();
  TokenStream::Iterator tokens_iterator(TokenStream::Handle(
      Script::Handle(script()).tokens()), token_pos());
  Object& obj = Object::Handle();
  String& literal = String::Handle();
  while (tokens_iterator.CurrentPosition() < end_token_pos()) {
    uint32_t val = 0;
    obj = tokens_iterator.CurrentToken();
    if (obj.IsSmi()) {
      val = Smi::Cast(obj).Value();
    } else {
      literal = tokens_iterator.MakeLiteralToken(obj);
      val = literal.Hash();
    }
    result = 31 * result + val;
    tokens_iterator.Advance();
  }
  result = result & ((static_cast<uint32_t>(1) << 31) - 1);
  ASSERT(result <= static_cast<uint32_t>(kMaxInt32));
  return result;
}


bool Function::CheckSourceFingerprint(intptr_t fp) const {
  if (SourceFingerprint() != fp) {
    OS::Print("FP mismatch while recogbnizing method %s:"
      " expecting %"Pd" found %d\n",
      ToFullyQualifiedCString(),
      fp,
      SourceFingerprint());
    return false;
  }
  return true;
}


const char* Function::ToCString() const {
  const char* static_str = is_static() ? " static" : "";
  const char* abstract_str = is_abstract() ? " abstract" : "";
  const char* kind_str = NULL;
  const char* const_str = is_const() ? " const" : "";
  switch (kind()) {
    case RawFunction::kRegularFunction:
    case RawFunction::kClosureFunction:
    case RawFunction::kGetterFunction:
    case RawFunction::kSetterFunction:
      kind_str = "";
      break;
    case RawFunction::kSignatureFunction:
      kind_str = " signature";
      break;
    case RawFunction::kConstructor:
      kind_str = is_static() ? " factory" : " constructor";
      break;
    case RawFunction::kImplicitGetter:
      kind_str = " getter";
      break;
    case RawFunction::kImplicitSetter:
      kind_str = " setter";
      break;
    case RawFunction::kConstImplicitGetter:
      kind_str = " const-getter";
      break;
    default:
      UNREACHABLE();
  }
  const char* kFormat = "Function '%s':%s%s%s%s.";
  const char* function_name = String::Handle(name()).ToCString();
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name,
                             static_str, abstract_str, kind_str, const_str) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, function_name,
              static_str, abstract_str, kind_str, const_str);
  return chars;
}


void ClosureData::set_context_scope(const ContextScope& value) const {
  StorePointer(&raw_ptr()->context_scope_, value.raw());
}


void ClosureData::set_implicit_static_closure(const Instance& closure) const {
  ASSERT(!closure.IsNull());
  ASSERT(raw_ptr()->closure_ == Instance::null());
  StorePointer(&raw_ptr()->closure_, closure.raw());
}


void ClosureData::set_closure_allocation_stub(const Code& value) const {
  ASSERT(!value.IsNull());
  ASSERT(raw_ptr()->closure_allocation_stub_ == Code::null());
  StorePointer(&raw_ptr()->closure_allocation_stub_, value.raw());
}


void ClosureData::set_parent_function(const Function& value) const {
  StorePointer(&raw_ptr()->parent_function_, value.raw());
}


void ClosureData::set_signature_class(const Class& value) const {
  StorePointer(&raw_ptr()->signature_class_, value.raw());
}


RawClosureData* ClosureData::New() {
  ASSERT(Object::closure_data_class() != Class::null());
  RawObject* raw = Object::Allocate(ClosureData::kClassId,
                                    ClosureData::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawClosureData*>(raw);
}


const char* ClosureData::ToCString() const {
  return "ClosureData class";
}


void RedirectionData::set_type(const Type& value) const {
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->type_, value.raw());
}


void RedirectionData::set_identifier(const String& value) const {
  StorePointer(&raw_ptr()->identifier_, value.raw());
}


void RedirectionData::set_target(const Function& value) const {
  StorePointer(&raw_ptr()->target_, value.raw());
}


RawRedirectionData* RedirectionData::New() {
  ASSERT(Object::redirection_data_class() != Class::null());
  RawObject* raw = Object::Allocate(RedirectionData::kClassId,
                                    RedirectionData::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawRedirectionData*>(raw);
}


const char* RedirectionData::ToCString() const {
  return "RedirectionData class";
}


RawString* Field::GetterName(const String& field_name) {
  String& str = String::Handle();
  str = String::New(kGetterPrefix);
  str = String::Concat(str, field_name);
  return str.raw();
}


RawString* Field::GetterSymbol(const String& field_name) {
  String& str = String::Handle();
  str = Field::GetterName(field_name);
  return Symbols::New(str);
}


RawString* Field::SetterName(const String& field_name) {
  String& str = String::Handle();
  str = String::New(kSetterPrefix);
  str = String::Concat(str, field_name);
  return str.raw();
}


RawString* Field::SetterSymbol(const String& field_name) {
  String& str = String::Handle();
  str = Field::SetterName(field_name);
  return Symbols::New(str);
}


RawString* Field::NameFromGetter(const String& getter_name) {
  String& str = String::Handle();
  str = String::SubString(getter_name, strlen(kGetterPrefix));
  return str.raw();
}


RawString* Field::NameFromSetter(const String& setter_name) {
  String& str = String::Handle();
  str = String::SubString(setter_name, strlen(kSetterPrefix));
  return str.raw();
}


bool Field::IsGetterName(const String& function_name) {
  return function_name.StartsWith(String::Handle(String::New(kGetterPrefix)));
}


bool Field::IsSetterName(const String& function_name) {
  return function_name.StartsWith(String::Handle(String::New(kSetterPrefix)));
}


void Field::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  StorePointer(&raw_ptr()->name_, value.raw());
}


RawInstance* Field::value() const {
  ASSERT(is_static());  // Valid only for static dart fields.
  return raw_ptr()->value_;
}


void Field::set_value(const Instance& value) const {
  ASSERT(is_static());  // Valid only for static dart fields.
  StorePointer(&raw_ptr()->value_, value.raw());
}


void Field::set_type(const AbstractType& value) const {
  ASSERT(!value.IsNull());
  StorePointer(&raw_ptr()->type_, value.raw());
}


RawField* Field::New() {
  ASSERT(Object::field_class() != Class::null());
  RawObject* raw = Object::Allocate(Field::kClassId,
                                    Field::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawField*>(raw);
}


RawField* Field::New(const String& name,
                     bool is_static,
                     bool is_final,
                     bool is_const,
                     const Class& owner,
                     intptr_t token_pos) {
  ASSERT(name.IsOneByteString());
  ASSERT(!owner.IsNull());
  const Field& result = Field::Handle(Field::New());
  result.set_name(name);
  result.set_is_static(is_static);
  if (is_static) {
    result.set_value(Instance::Handle());
  } else {
    result.SetOffset(0);
  }
  result.set_is_final(is_final);
  result.set_is_const(is_const);
  result.set_owner(owner);
  result.set_token_pos(token_pos);
  result.set_has_initializer(false);
  return result.raw();
}


RawString* Field::UserVisibleName() const {
  const String& str = String::Handle(name());
  return IdentifierPrettyName(str);
}


const char* Field::ToCString() const {
  const char* kF0 = is_static() ? " static" : "";
  const char* kF1 = is_final() ? " final" : "";
  const char* kF2 = is_const() ? " const" : "";
  const char* kFormat = "Field <%s.%s>:%s%s%s";
  const char* field_name = String::Handle(name()).ToCString();
  const Class& cls = Class::Handle(owner());
  const char* cls_name = String::Handle(cls.Name()).ToCString();
  intptr_t len =
      OS::SNPrint(NULL, 0, kFormat, cls_name, field_name, kF0, kF1, kF2) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, cls_name, field_name, kF0, kF1, kF2);
  return chars;
}


void LiteralToken::set_literal(const String& literal) const {
  StorePointer(&raw_ptr()->literal_, literal.raw());
}


void LiteralToken::set_value(const Object& value) const {
  StorePointer(&raw_ptr()->value_, value.raw());
}


RawLiteralToken* LiteralToken::New() {
  ASSERT(Object::literal_token_class() != Class::null());
  RawObject* raw = Object::Allocate(LiteralToken::kClassId,
                                    LiteralToken::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawLiteralToken*>(raw);
}


RawLiteralToken* LiteralToken::New(Token::Kind kind, const String& literal) {
  const LiteralToken& result = LiteralToken::Handle(LiteralToken::New());
  result.set_kind(kind);
  result.set_literal(literal);
  if (kind == Token::kINTEGER) {
    const Integer& value = Integer::Handle(Integer::New(literal, Heap::kOld));
    ASSERT(value.IsSmi() || value.IsOld());
    result.set_value(value);
  } else if (kind == Token::kDOUBLE) {
    const Double& value = Double::Handle(Double::NewCanonical(literal));
    result.set_value(value);
  } else {
    ASSERT(Token::NeedsLiteralToken(kind));
    result.set_value(literal);
  }
  return result.raw();
}


const char* LiteralToken::ToCString() const {
  const String& token = String::Handle(literal());
  return token.ToCString();
}


RawArray* TokenStream::TokenObjects() const {
  return raw_ptr()->token_objects_;
}


void TokenStream::SetTokenObjects(const Array& value) const {
  StorePointer(&raw_ptr()->token_objects_, value.raw());
}


RawExternalUint8Array* TokenStream::GetStream() const {
  return raw_ptr()->stream_;
}


void TokenStream::SetStream(const ExternalUint8Array& value) const {
  StorePointer(&raw_ptr()->stream_, value.raw());
}


void TokenStream::DataFinalizer(void *peer) {
  ASSERT(peer != NULL);
  ::free(peer);
}


RawString* TokenStream::PrivateKey() const {
  return raw_ptr()->private_key_;
}


void TokenStream::SetPrivateKey(const String& value) const {
  StorePointer(&raw_ptr()->private_key_, value.raw());
}


RawString* TokenStream::GenerateSource() const {
  Iterator iterator(*this, 0);
  const ExternalUint8Array& data = ExternalUint8Array::Handle(GetStream());
  const GrowableObjectArray& literals =
      GrowableObjectArray::Handle(GrowableObjectArray::New(data.Length()));
  const String& private_key = String::Handle(PrivateKey());
  intptr_t private_len = private_key.Length();

  String& blank = String::Handle(String::New(" "));
  String& newline = String::Handle(String::New("\n"));
  String& two_newlines = String::Handle(String::New("\n\n"));
  String& double_quotes = String::Handle(String::New("\""));
  String& dollar = String::Handle(String::New("$"));
  String& two_spaces = String::Handle(String::New("  "));
  String& raw_string = String::Handle(String::New("r"));

  Token::Kind curr = iterator.CurrentTokenKind();
  Token::Kind prev = Token::kILLEGAL;
  // Handles used in the loop.
  Object& obj = Object::Handle();
  String& literal = String::Handle();
  // Current indentation level.
  int indent = 0;

  while (curr != Token::kEOS) {
    // Remember current values for this token.
    obj = iterator.CurrentToken();
    literal = iterator.MakeLiteralToken(obj);
    // Advance to be able to use next token kind.
    iterator.Advance();
    Token::Kind next = iterator.CurrentTokenKind();

    // Handle the current token.
    if (curr == Token::kSTRING) {
      bool is_raw_string = false;
      bool escape_characters = false;
      for (intptr_t i = 0; i < literal.Length(); i++) {
        if (IsSpecialCharacter(literal.CharAt(i))) {
          escape_characters = true;
        }
        // TODO(4995): Temp solution for raw strings, this will break
        // if we saw a string that is not a raw string but has back slashes
        // in it.
        if ((literal.CharAt(i) == '\\')) {
          if ((next != Token::kINTERPOL_VAR) &&
              (next != Token::kINTERPOL_START) &&
              (prev != Token::kINTERPOL_VAR) &&
              (prev != Token::kINTERPOL_END)) {
            is_raw_string = true;
          } else {
            escape_characters = true;
          }
        }
      }
      if ((prev != Token::kINTERPOL_VAR) && (prev != Token::kINTERPOL_END)) {
        if (is_raw_string) {
          literals.Add(raw_string);
        }
        literals.Add(double_quotes);
      }
      if (escape_characters) {
        literal = String::EscapeSpecialCharacters(literal, is_raw_string);
        literals.Add(literal);
      } else {
        literals.Add(literal);
      }
      if ((next != Token::kINTERPOL_VAR) && (next != Token::kINTERPOL_START)) {
        literals.Add(double_quotes);
      }
    } else if (curr == Token::kINTERPOL_VAR) {
      literals.Add(dollar);
      if (literal.CharAt(0) == Scanner::kPrivateIdentifierStart) {
        literal = String::SubString(literal, 0, literal.Length() - private_len);
      }
      literals.Add(literal);
    } else if (curr == Token::kIDENT) {
      if (literal.CharAt(0) == Scanner::kPrivateIdentifierStart) {
        literal = String::SubString(literal, 0, literal.Length() - private_len);
      }
      literals.Add(literal);
    } else {
      literals.Add(literal);
    }
    // Determine the separation text based on this current token.
    const String* separator = NULL;
    switch (curr) {
      case Token::kLBRACE:
        indent++;
        separator = &newline;
        break;
      case Token::kRBRACE:
        if (indent == 0) {
          separator = &two_newlines;
        } else {
          separator = &newline;
        }
        break;
      case Token::kSEMICOLON:
        separator = &newline;
        break;
      case Token::kPERIOD:
      case Token::kLPAREN:
      case Token::kLBRACK:
      case Token::kTIGHTADD:
      case Token::kINTERPOL_VAR:
      case Token::kINTERPOL_START:
      case Token::kINTERPOL_END:
        break;
      default:
        separator = &blank;
        break;
    }
    // Determine whether the separation text needs to be updated based on the
    // next token.
    switch (next) {
      case Token::kRBRACE:
        indent--;
        break;
      case Token::kSEMICOLON:
      case Token::kPERIOD:
      case Token::kCOMMA:
      case Token::kLPAREN:
      case Token::kRPAREN:
      case Token::kLBRACK:
      case Token::kRBRACK:
      case Token::kINTERPOL_VAR:
      case Token::kINTERPOL_START:
      case Token::kINTERPOL_END:
        separator = NULL;
        break;
      case Token::kELSE:
        separator = &blank;
      default:
        // Do nothing.
        break;
    }
    // Update the few cases where both tokens need to be taken into account.
    if (((curr == Token::kIF) || (curr == Token::kFOR)) &&
        (next == Token::kLPAREN)) {
      separator = &blank;
    } else if ((curr == Token::kASSIGN) && (next == Token::kLPAREN)) {
      separator = & blank;
    } else if ((curr == Token::kLBRACE) && (next == Token::kRBRACE)) {
      separator = NULL;
    }
    if (separator != NULL) {
      literals.Add(*separator);
      if (separator == &newline) {
        for (int i = 0; i < indent; i++) {
          literals.Add(two_spaces);
        }
      }
    }
    // Setup for next iteration.
    prev = curr;
    curr = next;
  }
  const Array& source = Array::Handle(Array::MakeArray(literals));
  return String::ConcatAll(source);
}


intptr_t TokenStream::ComputeSourcePosition(intptr_t tok_pos) const {
  Iterator iterator(*this, 0);
  intptr_t src_pos = 0;
  Token::Kind kind = iterator.CurrentTokenKind();
  while (iterator.CurrentPosition() < tok_pos && kind != Token::kEOS) {
    iterator.Advance();
    kind = iterator.CurrentTokenKind();
    src_pos += 1;
  }
  return src_pos;
}


intptr_t TokenStream::ComputeTokenPosition(intptr_t src_pos) const {
  Iterator iterator(*this, 0);
  intptr_t index = 0;
  Token::Kind kind = iterator.CurrentTokenKind();
  while (index < src_pos && kind != Token::kEOS) {
    iterator.Advance();
    kind = iterator.CurrentTokenKind();
    index += 1;
  }
  return iterator.CurrentPosition();
}


RawTokenStream* TokenStream::New() {
  ASSERT(Object::token_stream_class() != Class::null());
  TokenStream& result = TokenStream::Handle();
  {
    RawObject* raw = Object::Allocate(TokenStream::kClassId,
                                      TokenStream::InstanceSize(),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
  }
  return result.raw();
}


RawTokenStream* TokenStream::New(intptr_t len) {
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in TokenStream::New: invalid len %"Pd"\n", len);
  }
  uint8_t* data = reinterpret_cast<uint8_t*>(::malloc(len));
  ASSERT(data != NULL);
  const ExternalUint8Array& stream = ExternalUint8Array::Handle(
      ExternalUint8Array::New(data, len, data, DataFinalizer, Heap::kOld));
  const TokenStream& result = TokenStream::Handle(TokenStream::New());
  result.SetStream(stream);
  return result.raw();
}


// Helper class for creation of compressed token stream data.
class CompressedTokenStreamData : public ValueObject {
 public:
  static const intptr_t kIncrementSize = 16 * KB;
  CompressedTokenStreamData() :
      buffer_(NULL),
      stream_(&buffer_, Reallocate, kIncrementSize),
      token_objects_(GrowableObjectArray::Handle(
          GrowableObjectArray::New(kInitialTokenCount, Heap::kOld))),
      token_obj_(Object::Handle()),
      literal_token_(LiteralToken::Handle()),
      literal_str_(String::Handle()) {
    const String& empty_literal = String::Handle();
    token_objects_.Add(empty_literal);
  }
  ~CompressedTokenStreamData() {
  }

  // Add an IDENT token into the stream and the token objects array.
  void AddIdentToken(String* ident) {
    if (ident != NULL) {
      // If the IDENT token is already in the tokens object array use the
      // same index instead of duplicating it.
      intptr_t index = FindIdentIndex(ident);
      if (index == -1) {
        WriteIndex(token_objects_.Length());
        ASSERT(ident != NULL);
        token_objects_.Add(*ident);
      } else {
        WriteIndex(index);
      }
    } else {
      WriteIndex(0);
    }
  }

  // Add a LITERAL token into the stream and the token objects array.
  void AddLiteralToken(Token::Kind kind, String* literal) {
    if (literal != NULL) {
      // If the literal token is already in the tokens object array use the
      // same index instead of duplicating it.
      intptr_t index = FindLiteralIndex(kind, literal);
      if (index == -1) {
        WriteIndex(token_objects_.Length());
        ASSERT(literal != NULL);
        literal_token_ = LiteralToken::New(kind, *literal);
        token_objects_.Add(literal_token_);
      } else {
        WriteIndex(index);
      }
    } else {
      WriteIndex(0);
    }
  }

  // Add a simple token into the stream.
  void AddSimpleToken(intptr_t kind) {
    stream_.WriteUnsigned(kind);
  }

  // Return the compressed token stream.
  uint8_t* GetStream() const { return buffer_; }

  // Return the compressed token stream length.
  intptr_t Length() const { return stream_.bytes_written(); }

  // Return the token objects array.
  const GrowableObjectArray& TokenObjects() const {
    return token_objects_;
  }

 private:
  intptr_t FindIdentIndex(String* ident) {
    ASSERT(ident != NULL);
    intptr_t hash_value = ident->Hash() % kTableSize;
    GrowableArray<intptr_t>& value = ident_table_[hash_value];
    for (intptr_t i = 0; i < value.length(); i++) {
      intptr_t index = value[i];
      token_obj_ = token_objects_.At(index);
      if (token_obj_.IsString()) {
        const String& ident_str = String::Cast(token_obj_);
        if (ident->Equals(ident_str)) {
          return index;
        }
      }
    }
    value.Add(token_objects_.Length());
    return -1;
  }

  intptr_t FindLiteralIndex(Token::Kind kind, String* literal) {
    ASSERT(literal != NULL);
    intptr_t hash_value = literal->Hash() % kTableSize;
    GrowableArray<intptr_t>& value = literal_table_[hash_value];
    for (intptr_t i = 0; i < value.length(); i++) {
      intptr_t index = value[i];
      token_obj_ = token_objects_.At(index);
      if (token_obj_.IsLiteralToken()) {
        const LiteralToken& token = LiteralToken::Cast(token_obj_);
        literal_str_ = token.literal();
        if (kind == token.kind() && literal->Equals(literal_str_)) {
          return index;
        }
      }
    }
    value.Add(token_objects_.Length());
    return -1;
  }

  void WriteIndex(intptr_t value) {
    stream_.WriteUnsigned(value + Token::kNumTokens);
  }

  static uint8_t* Reallocate(uint8_t* ptr,
                             intptr_t old_size,
                             intptr_t new_size) {
    void* new_ptr = ::realloc(reinterpret_cast<void*>(ptr), new_size);
    return reinterpret_cast<uint8_t*>(new_ptr);
  }

  static const int kInitialTokenCount = 32;
  static const intptr_t kTableSize = 128;

  uint8_t* buffer_;
  WriteStream stream_;
  GrowableArray<intptr_t> ident_table_[kTableSize];
  GrowableArray<intptr_t> literal_table_[kTableSize];
  const GrowableObjectArray& token_objects_;
  Object& token_obj_;
  LiteralToken& literal_token_;
  String& literal_str_;

  DISALLOW_COPY_AND_ASSIGN(CompressedTokenStreamData);
};


RawTokenStream* TokenStream::New(const Scanner::GrowableTokenStream& tokens,
                                 const String& private_key) {
  // Copy the relevant data out of the scanner into a compressed stream of
  // tokens.
  CompressedTokenStreamData data;
  intptr_t len = tokens.length();
  for (intptr_t i = 0; i < len; i++) {
    Scanner::TokenDescriptor token = tokens[i];
    if (token.kind == Token::kIDENT) {  // Identifier token.
      if (FLAG_compiler_stats) {
        CompilerStats::num_ident_tokens_total += 1;
      }
      data.AddIdentToken(token.literal);
    } else if (Token::NeedsLiteralToken(token.kind)) {  // Literal token.
      if (FLAG_compiler_stats) {
        CompilerStats::num_literal_tokens_total += 1;
      }
      data.AddLiteralToken(token.kind, token.literal);
    } else {  // Keyword, pseudo keyword etc.
      ASSERT(token.kind < Token::kNumTokens);
      data.AddSimpleToken(token.kind);
    }
  }
  if (FLAG_compiler_stats) {
    CompilerStats::num_tokens_total += len;
  }
  data.AddSimpleToken(Token::kEOS);  // End of stream.

  // Create and setup the token stream object.
  const ExternalUint8Array& stream = ExternalUint8Array::Handle(
      ExternalUint8Array::New(data.GetStream(),
                              data.Length(),
                              data.GetStream(),
                              DataFinalizer,
                              Heap::kOld));
  const TokenStream& result = TokenStream::Handle(New());
  result.SetPrivateKey(private_key);
  {
    NoGCScope no_gc;
    result.SetStream(stream);
    const Array& tokens = Array::Handle(Array::MakeArray(data.TokenObjects()));
    result.SetTokenObjects(tokens);
  }
  return result.raw();
}


const char* TokenStream::ToCString() const {
  return "TokenStream";
}


TokenStream::Iterator::Iterator(const TokenStream& tokens, intptr_t token_pos)
    : tokens_(tokens),
      data_(ExternalUint8Array::Handle(tokens.GetStream())),
      stream_(data_.ByteAddr(0), data_.Length()),
      token_objects_(Array::Handle(tokens.TokenObjects())),
      obj_(Object::Handle()),
      cur_token_pos_(token_pos),
      cur_token_kind_(Token::kILLEGAL),
      cur_token_obj_index_(-1) {
  SetCurrentPosition(token_pos);
}


bool TokenStream::Iterator::IsValid() const {
  return !tokens_.IsNull();
}


Token::Kind TokenStream::Iterator::LookaheadTokenKind(intptr_t num_tokens) {
  intptr_t saved_position = stream_.Position();
  Token::Kind kind = Token::kILLEGAL;
  intptr_t value = -1;
  intptr_t count = 0;
  while (count < num_tokens && value != Token::kEOS) {
    value = ReadToken();
    count += 1;
  }
  if (value < Token::kNumTokens) {
    kind = static_cast<Token::Kind>(value);
  } else {
    value = value - Token::kNumTokens;
    obj_ = token_objects_.At(value);
    if (obj_.IsLiteralToken()) {
      const LiteralToken& literal_token = LiteralToken::Cast(obj_);
      kind = literal_token.kind();
    } else {
      ASSERT(obj_.IsString());  // Must be an identifier.
      kind = Token::kIDENT;
    }
  }
  stream_.SetPosition(saved_position);
  return kind;
}


intptr_t TokenStream::Iterator::CurrentPosition() const {
  return cur_token_pos_;
}


void TokenStream::Iterator::SetCurrentPosition(intptr_t value) {
  stream_.SetPosition(value);
  Advance();
}


void TokenStream::Iterator::Advance() {
  cur_token_pos_ = stream_.Position();
  intptr_t value = ReadToken();
  if (value < Token::kNumTokens) {
    cur_token_kind_ = static_cast<Token::Kind>(value);
    cur_token_obj_index_ = -1;
    return;
  }
  cur_token_obj_index_ = value - Token::kNumTokens;
  obj_ = token_objects_.At(cur_token_obj_index_);
  if (obj_.IsLiteralToken()) {
    const LiteralToken& literal_token = LiteralToken::Cast(obj_);
    cur_token_kind_ = literal_token.kind();
    return;
  }
  ASSERT(obj_.IsString());  // Must be an identifier.
  cur_token_kind_ = Token::kIDENT;
}


RawObject* TokenStream::Iterator::CurrentToken() const {
  if (cur_token_obj_index_ != -1) {
    return token_objects_.At(cur_token_obj_index_);
  } else {
    return Smi::New(cur_token_kind_);
  }
}


RawString* TokenStream::Iterator::CurrentLiteral() const {
  obj_ = CurrentToken();
  return MakeLiteralToken(obj_);
}


RawString* TokenStream::Iterator::MakeLiteralToken(const Object& obj) const {
  if (obj.IsString()) {
    return reinterpret_cast<RawString*>(obj.raw());
  } else if (obj.IsSmi()) {
    Token::Kind kind = static_cast<Token::Kind>(
        Smi::Value(reinterpret_cast<RawSmi*>(obj.raw())));
    ASSERT(kind < Token::kNumTokens);
    if (Token::IsPseudoKeyword(kind) || Token::IsKeyword(kind)) {
      Isolate* isolate = Isolate::Current();
      ObjectStore* object_store = isolate->object_store();
      String& str = String::Handle(isolate, String::null());
      const Array& symbols = Array::Handle(isolate,
                                           object_store->keyword_symbols());
      ASSERT(!symbols.IsNull());
      str ^= symbols.At(kind - Token::kFirstKeyword);
      ASSERT(!str.IsNull());
      return str.raw();
    }
    return Symbols::New(Token::Str(kind));
  } else {
    ASSERT(obj.IsLiteralToken());  // Must be a literal token.
    const LiteralToken& literal_token = LiteralToken::Cast(obj);
    return literal_token.literal();
  }
}


bool Script::HasSource() const {
  return raw_ptr()->source_ != String::null();
}


RawString* Script::Source() const {
  String& source = String::Handle(raw_ptr()->source_);
  if (source.IsNull()) {
    const TokenStream& token_stream = TokenStream::Handle(tokens());
    return token_stream.GenerateSource();
  } else {
    return raw_ptr()->source_;
  }
}


void Script::set_url(const String& value) const {
  StorePointer(&raw_ptr()->url_, value.raw());
}


void Script::set_source(const String& value) const {
  StorePointer(&raw_ptr()->source_, value.raw());
}


void Script::set_kind(RawScript::Kind value) const {
  raw_ptr()->kind_ = value;
}


void Script::set_tokens(const TokenStream& value) const {
  StorePointer(&raw_ptr()->tokens_, value.raw());
}


void Script::Tokenize(const String& private_key) const {
  const TokenStream& tkns = TokenStream::Handle(tokens());
  if (!tkns.IsNull()) {
    // Already tokenized.
    return;
  }

  // Get the source, scan and allocate the token stream.
  TimerScope timer(FLAG_compiler_stats, &CompilerStats::scanner_timer);
  const String& src = String::Handle(Source());
  Scanner scanner(src, private_key);
  set_tokens(TokenStream::Handle(TokenStream::New(scanner.GetStream(),
                                                  private_key)));
  if (FLAG_compiler_stats) {
    CompilerStats::src_length += src.Length();
  }
}


void Script::GetTokenLocation(intptr_t token_pos,
                              intptr_t* line,
                              intptr_t* column) const {
  const String& src = String::Handle(Source());
  const String& dummy_key = String::Handle(Symbols::Empty());
  const TokenStream& tkns = TokenStream::Handle(tokens());
  intptr_t src_pos = tkns.ComputeSourcePosition(token_pos);
  Scanner scanner(src, dummy_key);
  scanner.ScanTo(src_pos);
  *line = scanner.CurrentPosition().line;
  *column = scanner.CurrentPosition().column;
}


void Script::TokenRangeAtLine(intptr_t line_number,
                              intptr_t* first_token_index,
                              intptr_t* last_token_index) const {
  const String& src = String::Handle(Source());
  const String& dummy_key = String::Handle(Symbols::Empty());
  const TokenStream& tkns = TokenStream::Handle(tokens());
  Scanner scanner(src, dummy_key);
  scanner.TokenRangeAtLine(line_number, first_token_index, last_token_index);
  if (*first_token_index >= 0) {
    *first_token_index = tkns.ComputeTokenPosition(*first_token_index);
  }
  if (*last_token_index >= 0) {
    *last_token_index = tkns.ComputeTokenPosition(*last_token_index);
  }
}


RawString* Script::GetLine(intptr_t line_number) const {
  const String& src = String::Handle(Source());
  intptr_t current_line = 1;
  intptr_t line_start = -1;
  intptr_t last_char = -1;
  for (intptr_t ix = 0;
       (ix < src.Length()) && (current_line <= line_number);
       ix++) {
    if ((current_line == line_number) && (line_start < 0)) {
      line_start = ix;
    }
    if (src.CharAt(ix) == '\n') {
      current_line++;
    } else if (src.CharAt(ix) == '\r') {
      if ((ix + 1 != src.Length()) && (src.CharAt(ix + 1) != '\n')) {
        current_line++;
      }
    } else {
      last_char = ix;
    }
  }
  // Guarantee that returned string is never NULL.
  String& line = String::Handle(Symbols::Empty());
  if (line_start >= 0) {
    line = String::SubString(src, line_start, last_char - line_start + 1);
  }
  return line.raw();
}


RawString* Script::GetSnippet(intptr_t from_line,
                              intptr_t from_column,
                              intptr_t to_line,
                              intptr_t to_column) const {
  const String& src = String::Handle(Source());
  intptr_t length = src.Length();
  intptr_t line = 1;
  intptr_t column = 1;
  intptr_t lookahead = 0;
  intptr_t snippet_start = -1;
  intptr_t snippet_end = -1;
  char c = src.CharAt(lookahead);
  while (lookahead != length) {
    if (snippet_start == -1) {
      if ((line == from_line) && (column == from_column)) {
        snippet_start = lookahead;
      }
    } else if ((line == to_line) && (column == to_column)) {
      snippet_end = lookahead;
      break;
    }
    if (c == '\n') {
      line++;
      column = 0;
    }
    column++;
    lookahead++;
    if (lookahead != length) {
      // Replace '\r' with '\n' and a sequence of '\r' '\n' with a single '\n'.
      if (src.CharAt(lookahead) == '\r') {
        c = '\n';
        if (lookahead + 1 != length && src.CharAt(lookahead) == '\n') {
          lookahead++;
        }
      } else {
        c = src.CharAt(lookahead);
      }
    }
  }
  String& snippet = String::Handle();
  if ((snippet_start != -1) && (snippet_end != -1)) {
    snippet =
        String::SubString(src, snippet_start, snippet_end - snippet_start);
  }
  return snippet.raw();
}


RawScript* Script::New() {
  ASSERT(Object::script_class() != Class::null());
  RawObject* raw = Object::Allocate(Script::kClassId,
                                    Script::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawScript*>(raw);
}


RawScript* Script::New(const String& url,
                       const String& source,
                       RawScript::Kind kind) {
  const Script& result = Script::Handle(Script::New());
  result.set_url(String::Handle(Symbols::New(url)));
  result.set_source(source);
  result.set_kind(kind);
  return result.raw();
}


const char* Script::ToCString() const {
  return "Script";
}


DictionaryIterator::DictionaryIterator(const Library& library)
    : array_(Array::Handle(library.dictionary())),
      // Last element in array is a Smi.
      size_(Array::Handle(library.dictionary()).Length() - 1),
      next_ix_(0) {
  MoveToNextObject();
}


RawObject* DictionaryIterator::GetNext() {
  ASSERT(HasNext());
  int ix = next_ix_++;
  MoveToNextObject();
  ASSERT(array_.At(ix) != Object::null());
  return array_.At(ix);
}


void DictionaryIterator::MoveToNextObject() {
  Object& obj = Object::Handle(array_.At(next_ix_));
  while (obj.IsNull() && HasNext()) {
    next_ix_++;
    obj = array_.At(next_ix_);
  }
}


ClassDictionaryIterator::ClassDictionaryIterator(const Library& library)
    : DictionaryIterator(library) {
  MoveToNextClass();
}


RawClass* ClassDictionaryIterator::GetNextClass() {
  ASSERT(HasNext());
  int ix = next_ix_++;
  Object& obj = Object::Handle(array_.At(ix));
  MoveToNextClass();
  return Class::Cast(obj).raw();
}


void ClassDictionaryIterator::MoveToNextClass() {
  Object& obj = Object::Handle(array_.At(next_ix_));
  while (!obj.IsClass() && HasNext()) {
    next_ix_++;
    obj = array_.At(next_ix_);
  }
}


LibraryPrefixIterator::LibraryPrefixIterator(const Library& library)
    : DictionaryIterator(library) {
  Advance();
}


RawLibraryPrefix* LibraryPrefixIterator::GetNext() {
  ASSERT(HasNext());
  int ix = next_ix_++;
  Object& obj = Object::Handle(array_.At(ix));
  Advance();
  return LibraryPrefix::Cast(obj).raw();
}


void LibraryPrefixIterator::Advance() {
  Object& obj = Object::Handle(array_.At(next_ix_));
  while (!obj.IsLibraryPrefix() && HasNext()) {
    next_ix_++;
    obj = array_.At(next_ix_);
  }
}


void Library::SetName(const String& name) const {
  // Only set name once.
  ASSERT(!Loaded());
  ASSERT(name.IsSymbol());
  StorePointer(&raw_ptr()->name_, name.raw());
}


void Library::SetLoadInProgress() const {
  // Should not be already loaded.
  ASSERT(raw_ptr()->load_state_ == RawLibrary::kAllocated);
  raw_ptr()->load_state_ = RawLibrary::kLoadInProgress;
}


void Library::SetLoaded() const {
  // Should not be already loaded or just allocated.
  ASSERT(LoadInProgress());
  raw_ptr()->load_state_ = RawLibrary::kLoaded;
}


void Library::SetLoadError() const {
  // Should not be already loaded or just allocated.
  ASSERT(LoadInProgress());
  raw_ptr()->load_state_ = RawLibrary::kLoadError;
}


void Library::GrowDictionary(const Array& dict, intptr_t dict_size) const {
  // TODO(iposva): Avoid exponential growth.
  intptr_t new_dict_size = dict_size * 2;
  const Array& new_dict =
      Array::Handle(Array::New(new_dict_size + 1, Heap::kOld));
  // Rehash all elements from the original dictionary
  // to the newly allocated array.
  Object& entry = Class::Handle();
  String& entry_name = String::Handle();
  Object& new_entry = Object::Handle();
  for (intptr_t i = 0; i < dict_size; i++) {
    entry = dict.At(i);
    if (!entry.IsNull()) {
      entry_name = entry.DictionaryName();
      ASSERT(!entry_name.IsNull());
      intptr_t hash = entry_name.Hash();
      intptr_t index = hash % new_dict_size;
      new_entry = new_dict.At(index);
      while (!new_entry.IsNull()) {
        index = (index + 1) % new_dict_size;  // Move to next element.
        new_entry = new_dict.At(index);
      }
      new_dict.SetAt(index, entry);
    }
  }
  // Copy used count.
  new_entry = dict.At(dict_size);
  new_dict.SetAt(new_dict_size, new_entry);
  // Remember the new dictionary now.
  StorePointer(&raw_ptr()->dictionary_, new_dict.raw());
}


void Library::AddObject(const Object& obj, const String& name) const {
  ASSERT(obj.IsClass() ||
         obj.IsFunction() ||
         obj.IsField() ||
         obj.IsLibraryPrefix());
  ASSERT(name.Equals(String::Handle(obj.DictionaryName())));
  ASSERT(LookupLocalObject(name) == Object::null());
  const Array& dict = Array::Handle(dictionary());
  intptr_t dict_size = dict.Length() - 1;
  intptr_t index = name.Hash() % dict_size;

  Object& entry = Object::Handle();
  entry = dict.At(index);
  // An empty spot will be found because we keep the hash set at most 75% full.
  while (!entry.IsNull()) {
    index = (index + 1) % dict_size;
    entry = dict.At(index);
  }

  // Insert the object at the empty slot.
  dict.SetAt(index, obj);
  Smi& used = Smi::Handle();
  used ^= dict.At(dict_size);
  intptr_t used_elements = used.Value() + 1;  // One more element added.
  used = Smi::New(used_elements);
  dict.SetAt(dict_size, used);  // Update used count.

  // Rehash if symbol_table is 75% full.
  if (used_elements > ((dict_size / 4) * 3)) {
    GrowDictionary(dict, dict_size);
  }

  // Invalidate the cache of loaded scripts.
  if (loaded_scripts() != Array::null()) {
    StorePointer(&raw_ptr()->loaded_scripts_, Array::null());
  }
}


// Lookup a name in the library's export namespace.
RawObject* Library::LookupExport(const String& name) const {
  if (HasExports()) {
    const Array& exports = Array::Handle(this->exports());
    Namespace& ns = Namespace::Handle();
    Object& obj = Object::Handle();
    for (int i = 0; i < exports.Length(); i++) {
      ns ^= exports.At(i);
      obj = ns.Lookup(name);
      if (!obj.IsNull()) {
        return obj.raw();
      }
    }
  }
  return Object::null();
}


RawObject* Library::LookupEntry(const String& name, intptr_t *index) const {
  Isolate* isolate = Isolate::Current();
  const Array& dict = Array::Handle(isolate, dictionary());
  intptr_t dict_size = dict.Length() - 1;
  *index = name.Hash() % dict_size;

  Object& entry = Object::Handle(isolate);
  String& entry_name = String::Handle(isolate);
  entry = dict.At(*index);
  // Search the entry in the hash set.
  while (!entry.IsNull()) {
    entry_name = entry.DictionaryName();
    ASSERT(!entry_name.IsNull());
     if (entry_name.Equals(name)) {
      return entry.raw();
    }
    *index = (*index + 1) % dict_size;
    entry = dict.At(*index);
  }
  return Object::null();
}


void Library::ReplaceObject(const Object& obj, const String& name) const {
  ASSERT(obj.IsClass() || obj.IsFunction() || obj.IsField());
  ASSERT(LookupLocalObject(name) != Object::null());

  intptr_t index;
  LookupEntry(name, &index);
  // The value is guaranteed to be found.
  const Array& dict = Array::Handle(dictionary());
  dict.SetAt(index, obj);
}


void Library::AddClass(const Class& cls) const {
  AddObject(cls, String::Handle(cls.Name()));
  // Link class to this library.
  cls.set_library(*this);
}


RawArray* Library::LoadedScripts() const {
  // We compute the list of loaded scripts lazily. The result is
  // cached in loaded_scripts_.
  if (loaded_scripts() == Array::null()) {
    // Iterate over the library dictionary and collect all scripts.
    const GrowableObjectArray& scripts =
        GrowableObjectArray::Handle(GrowableObjectArray::New(8));
    Object& entry = Object::Handle();
    Class& cls = Class::Handle();
    Script& owner_script = Script::Handle();
    DictionaryIterator it(*this);
    Script& script_obj = Script::Handle();
    while (it.HasNext()) {
      entry = it.GetNext();
      if (entry.IsClass()) {
        owner_script = Class::Cast(entry).script();
      } else if (entry.IsFunction()) {
        owner_script = Function::Cast(entry).script();
      } else if (entry.IsField()) {
        cls = Field::Cast(entry).owner();
        owner_script = cls.script();
      } else {
        continue;
      }
      if (owner_script.IsNull()) {
        continue;
      }
      bool is_unique = true;
      for (int i = 0; i < scripts.Length(); i++) {
        script_obj ^= scripts.At(i);
        if (script_obj.raw() == owner_script.raw()) {
          // We already have a reference to this script.
          is_unique = false;
          break;
        }
      }
      if (is_unique) {
        // Add script to the list of scripts.
        scripts.Add(owner_script);
      }
    }

    // Create the array of scripts and cache it in loaded_scripts_.
    StorePointer(&raw_ptr()->loaded_scripts_, Array::MakeArray(scripts));
  }
  return loaded_scripts();
}


// TODO(hausner): we might want to add a script dictionary to the
// library class to make this lookup faster.
RawScript* Library::LookupScript(const String& url) const {
  const Array& scripts = Array::Handle(LoadedScripts());
  Script& script = Script::Handle();
  String& script_url = String::Handle();
  intptr_t num_scripts = scripts.Length();
  for (int i = 0; i < num_scripts; i++) {
    script ^= scripts.At(i);
    script_url = script.url();
    if (script_url.Equals(url)) {
      return script.raw();
    }
  }
  return Script::null();
}


RawFunction* Library::LookupFunctionInSource(const String& script_url,
                                             intptr_t line_number) const {
  Script& script = Script::Handle(LookupScript(script_url));
  if (script.IsNull()) {
    // The given script url is not loaded into this library.
    return Function::null();
  }

  // Determine token position at given line number.
  intptr_t first_token_pos, last_token_pos;
  script.TokenRangeAtLine(line_number, &first_token_pos, &last_token_pos);
  if (first_token_pos < 0) {
    // Script does not contain the given line number.
    return Function::null();
  }
  return LookupFunctionInScript(script, first_token_pos);
}


RawFunction* Library::LookupFunctionInScript(const Script& script,
                                             intptr_t token_pos) const {
  Class& cls = Class::Handle();
  Function& func = Function::Handle();
  ClassDictionaryIterator it(*this);
  while (it.HasNext()) {
    cls = it.GetNextClass();
    if (script.raw() == cls.script()) {
      func = cls.LookupFunctionAtToken(token_pos);
      if (!func.IsNull()) {
        return func.raw();
      }
    }
  }
  // Look in anonymous classes for toplevel functions.
  Array& anon_classes = Array::Handle(this->raw_ptr()->anonymous_classes_);
  intptr_t num_anonymous = raw_ptr()->num_anonymous_;
  for (int i = 0; i < num_anonymous; i++) {
    cls ^= anon_classes.At(i);
    ASSERT(!cls.IsNull());
    if (script.raw() == cls.script()) {
      func = cls.LookupFunctionAtToken(token_pos);
      if (!func.IsNull()) {
        return func.raw();
      }
    }
  }
  return Function::null();
}


RawObject* Library::LookupLocalObject(const String& name) const {
  intptr_t index;
  return LookupEntry(name, &index);
}


static bool ShouldBePrivate(const String& name) {
  return
      (name.Length() >= 1 &&
       name.CharAt(0) == '_') ||
      (name.Length() >= 5 &&
       (name.CharAt(4) == '_' &&
        (name.CharAt(0) == 'g' || name.CharAt(0) == 's') &&
        name.CharAt(1) == 'e' &&
        name.CharAt(2) == 't' &&
        name.CharAt(3) == ':'));
}


RawField* Library::LookupFieldAllowPrivate(const String& name) const {
  // First check if name is found in the local scope of the library.
  Field& field = Field::Handle(LookupLocalField(name));
  if (!field.IsNull()) {
    return field.raw();
  }

  // Do not look up private names in imported libraries.
  if (ShouldBePrivate(name)) {
    return Field::null();
  }

  // Now check if name is found in any imported libs.
  const Array& imports = Array::Handle(this->imports());
  Namespace& import = Namespace::Handle();
  Object& obj = Object::Handle();
  for (intptr_t j = 0; j < this->num_imports(); j++) {
    import ^= imports.At(j);
    obj = import.Lookup(name);
    if (!obj.IsNull() && obj.IsField()) {
      field ^= obj.raw();
      return field.raw();
    }
  }
  return Field::null();
}


RawField* Library::LookupLocalField(const String& name) const {
  Isolate* isolate = Isolate::Current();
  Field& field = Field::Handle(isolate, Field::null());
  Object& obj = Object::Handle(isolate, Object::null());
  obj = LookupLocalObject(name);
  if (obj.IsNull() && ShouldBePrivate(name)) {
    String& private_name = String::Handle(isolate, PrivateName(name));
    obj = LookupLocalObject(private_name);
  }
  if (!obj.IsNull()) {
    if (obj.IsField()) {
      field ^= obj.raw();
      return field.raw();
    }
  }

  // No field found.
  return Field::null();
}


RawFunction* Library::LookupFunctionAllowPrivate(const String& name) const {
  // First check if name is found in the local scope of the library.
  Function& function = Function::Handle(LookupLocalFunction(name));
  if (!function.IsNull()) {
    return function.raw();
  }

  // Do not look up private names in imported libraries.
  if (ShouldBePrivate(name)) {
    return Function::null();
  }

  // Now check if name is found in any imported libs.
  const Array& imports = Array::Handle(this->imports());
  Namespace& import = Namespace::Handle();
  Object& obj = Object::Handle();
  for (intptr_t j = 0; j < this->num_imports(); j++) {
    import ^= imports.At(j);
    obj = import.Lookup(name);
    if (!obj.IsNull() && obj.IsFunction()) {
      function ^= obj.raw();
      return function.raw();
    }
  }
  return Function::null();
}


RawFunction* Library::LookupLocalFunction(const String& name) const {
  Isolate* isolate = Isolate::Current();
  Object& obj = Object::Handle(isolate, Object::null());
  obj = LookupLocalObject(name);
  if (obj.IsNull() && ShouldBePrivate(name)) {
    String& private_name = String::Handle(isolate, PrivateName(name));
    obj = LookupLocalObject(private_name);
  }
  if (obj.IsFunction()) {
    return Function::Cast(obj).raw();
  }

  // No function found.
  return Function::null();
}


RawObject* Library::LookupObject(const String& name) const {
  // First check if name is found in the local scope of the library.
  Object& obj = Object::Handle(LookupLocalObject(name));
  if (!obj.IsNull()) {
    return obj.raw();
  }
  // Now check if name is found in any imported libs.
  const Array& imports = Array::Handle(this->imports());
  Namespace& import = Namespace::Handle();
  for (intptr_t j = 0; j < this->num_imports(); j++) {
    import ^= imports.At(j);
    obj = import.Lookup(name);
    if (!obj.IsNull()) {
      return obj.raw();
    }
  }
  return Object::null();
}


RawClass* Library::LookupClass(const String& name) const {
  Object& obj = Object::Handle(LookupObject(name));
  if (!obj.IsNull() && obj.IsClass()) {
    return Class::CheckedHandle(obj.raw()).raw();
  }
  return Class::null();
}


RawClass* Library::LookupLocalClass(const String& name) const {
  Object& obj = Object::Handle(LookupLocalObject(name));
  if (!obj.IsNull() && obj.IsClass()) {
    return Class::CheckedHandle(obj.raw()).raw();
  }
  return Class::null();
}


RawClass* Library::LookupClassAllowPrivate(const String& name) const {
  // See if the class is available in this library or in the top level
  // scope of any imported library.
  Isolate* isolate = Isolate::Current();
  const Class& cls = Class::Handle(isolate, LookupClass(name));
  if (!cls.IsNull()) {
    return cls.raw();
  }

  // Now try to lookup the class using its private name, but only in
  // this library (not in imported libraries).
  if (ShouldBePrivate(name)) {
    String& private_name = String::Handle(isolate, PrivateName(name));
    const Object& obj = Object::Handle(LookupLocalObject(private_name));
    if (obj.IsClass()) {
      return Class::Cast(obj).raw();
    }
  }

  return Class::null();
}


RawLibraryPrefix* Library::LookupLocalLibraryPrefix(const String& name) const {
  const Object& obj = Object::Handle(LookupLocalObject(name));
  if (obj.IsLibraryPrefix()) {
    return LibraryPrefix::Cast(obj).raw();
  }
  return LibraryPrefix::null();
}


void Library::AddAnonymousClass(const Class& cls) const {
  intptr_t num_anonymous = this->raw_ptr()->num_anonymous_;
  Array& anon_array = Array::Handle(this->raw_ptr()->anonymous_classes_);
  if (num_anonymous == anon_array.Length()) {
    intptr_t new_len = (num_anonymous == 0) ? 4 : num_anonymous * 2;
    anon_array = Array::Grow(anon_array, new_len);
    StorePointer(&raw_ptr()->anonymous_classes_, anon_array.raw());
  }
  anon_array.SetAt(num_anonymous, cls);
  num_anonymous++;
  raw_ptr()->num_anonymous_ = num_anonymous;
}


RawLibrary* Library::ImportLibraryAt(intptr_t index) const {
  Namespace& import = Namespace::Handle(ImportAt(index));
  if (import.IsNull()) {
    return Library::null();
  }
  return import.library();
}


RawNamespace* Library::ImportAt(intptr_t index) const {
  if ((index < 0) || index >= num_imports()) {
    return Namespace::null();
  }
  const Array& import_list = Array::Handle(imports());
  Namespace& import = Namespace::Handle();
  import ^= import_list.At(index);
  return import.raw();
}


bool Library::ImportsCorelib() const {
  Isolate* isolate = Isolate::Current();
  Library& imported = Library::Handle(isolate);
  intptr_t count = num_imports();
  for (int i = 0; i < count; i++) {
    imported = ImportLibraryAt(i);
    if (imported.IsCoreLibrary()) {
      return true;
    }
  }
  LibraryPrefix& prefix = LibraryPrefix::Handle(isolate);
  LibraryPrefixIterator it(*this);
  while (it.HasNext()) {
    prefix = it.GetNext();
    count = prefix.num_imports();
    for (int i = 0; i < count; i++) {
      imported = prefix.GetLibrary(i);
      if (imported.IsCoreLibrary()) {
        return true;
      }
    }
  }
  return false;
}


void Library::AddImport(const Namespace& ns) const {
  Array& imports = Array::Handle(this->imports());
  intptr_t capacity = imports.Length();
  if (num_imports() == capacity) {
    capacity = capacity + kImportsCapacityIncrement;
    imports = Array::Grow(imports, capacity);
    StorePointer(&raw_ptr()->imports_, imports.raw());
  }
  intptr_t index = num_imports();
  imports.SetAt(index, ns);
  set_num_imports(index + 1);
}


// Convenience function to determine whether the export list is
// non-empty.
bool Library::HasExports() const {
  return exports() != Object::empty_array();
}


// We add one namespace at a time to the exports array and don't
// pre-allocate any unused capacity. The assumption is that
// re-exports are quite rare.
void Library::AddExport(const Namespace& ns) const {
  Array &exports = Array::Handle(this->exports());
  intptr_t num_exports = exports.Length();
  exports = Array::Grow(exports, num_exports + 1);
  StorePointer(&raw_ptr()->exports_, exports.raw());
  exports.SetAt(num_exports, ns);
}


void Library::InitClassDictionary() const {
  // The last element of the dictionary specifies the number of in use slots.
  // TODO(iposva): Find reasonable initial size.
  const int kInitialElementCount = 16;

  const Array& dictionary =
      Array::Handle(Array::New(kInitialElementCount + 1, Heap::kOld));
  dictionary.SetAt(kInitialElementCount, Smi::Handle(Smi::New(0)));
  StorePointer(&raw_ptr()->dictionary_, dictionary.raw());
}


void Library::InitImportList() const {
  const Array& imports =
      Array::Handle(Array::New(kInitialImportsCapacity, Heap::kOld));
  StorePointer(&raw_ptr()->imports_, imports.raw());
  raw_ptr()->num_imports_ = 0;
}


RawLibrary* Library::New() {
  ASSERT(Object::library_class() != Class::null());
  RawObject* raw = Object::Allocate(Library::kClassId,
                                    Library::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawLibrary*>(raw);
}


RawLibrary* Library::NewLibraryHelper(const String& url,
                                      bool import_core_lib) {
  const Library& result = Library::Handle(Library::New());
  result.StorePointer(&result.raw_ptr()->name_, url.raw());
  result.StorePointer(&result.raw_ptr()->url_, url.raw());
  result.raw_ptr()->private_key_ = Scanner::AllocatePrivateKey(result);
  result.raw_ptr()->dictionary_ = Object::empty_array();
  result.raw_ptr()->anonymous_classes_ = Object::empty_array();
  result.raw_ptr()->num_anonymous_ = 0;
  result.raw_ptr()->imports_ = Object::empty_array();
  result.raw_ptr()->exports_ = Object::empty_array();
  result.raw_ptr()->loaded_scripts_ = Array::null();
  result.set_native_entry_resolver(NULL);
  result.raw_ptr()->corelib_imported_ = true;
  result.set_debuggable(false);
  result.raw_ptr()->load_state_ = RawLibrary::kAllocated;
  result.raw_ptr()->index_ = -1;
  result.InitClassDictionary();
  result.InitImportList();
  if (import_core_lib) {
    const Library& core_lib = Library::Handle(Library::CoreLibrary());
    ASSERT(!core_lib.IsNull());
    const Namespace& ns = Namespace::Handle(
        Namespace::New(core_lib, Array::Handle(), Array::Handle()));
    result.AddImport(ns);
  }
  return result.raw();
}


RawLibrary* Library::New(const String& url) {
  return NewLibraryHelper(url, false);
}


void Library::InitCoreLibrary(Isolate* isolate) {
  const String& core_lib_url = String::Handle(Symbols::New("dart:core"));
  const Library& core_lib =
      Library::Handle(Library::NewLibraryHelper(core_lib_url, false));
  core_lib.Register();
  isolate->object_store()->set_core_library(core_lib);
  Library::InitMathLibrary(isolate);
  const Library& math_lib = Library::Handle(Library::MathLibrary());
  const Namespace& math_ns = Namespace::Handle(
      Namespace::New(math_lib, Array::Handle(), Array::Handle()));
  Library::InitCollectionLibrary(isolate);
  const Library& collection_lib =
      Library::Handle(Library::CollectionLibrary());
  const Namespace& collection_ns = Namespace::Handle(
      Namespace::New(collection_lib, Array::Handle(), Array::Handle()));
  core_lib.AddImport(math_ns);
  core_lib.AddImport(collection_ns);
  isolate->object_store()->set_root_library(Library::Handle());

  // Hook up predefined classes without setting their library pointers. These
  // classes are coming from the VM isolate, and are shared between multiple
  // isolates so setting their library pointers would be wrong.
  const Class& cls = Class::Handle(Object::dynamic_class());
  core_lib.AddObject(cls, String::Handle(cls.Name()));
}


void Library::InitCollectionLibrary(Isolate* isolate) {
  const String& url = String::Handle(Symbols::New("dart:collection"));
  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
  lib.Register();
  const Library& math_lib = Library::Handle(Library::MathLibrary());
  const Namespace& math_ns = Namespace::Handle(
      Namespace::New(math_lib, Array::Handle(), Array::Handle()));
  lib.AddImport(math_ns);
  isolate->object_store()->set_collection_library(lib);
}


void Library::InitMathLibrary(Isolate* isolate) {
  const String& url = String::Handle(Symbols::New("dart:math"));
  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
  lib.Register();
  isolate->object_store()->set_math_library(lib);
}


void Library::InitIsolateLibrary(Isolate* isolate) {
  const String& url = String::Handle(Symbols::New("dart:isolate"));
  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
  lib.Register();
  isolate->object_store()->set_isolate_library(lib);
}


void Library::InitMirrorsLibrary(Isolate* isolate) {
  const String& url = String::Handle(Symbols::New("dart:mirrors"));
  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
  lib.Register();
  const Library& isolate_lib = Library::Handle(Library::IsolateLibrary());
  const Namespace& isolate_ns = Namespace::Handle(
      Namespace::New(isolate_lib, Array::Handle(), Array::Handle()));
  lib.AddImport(isolate_ns);
  const Library& wrappers_lib =
      Library::Handle(Library::NativeWrappersLibrary());
  const Namespace& wrappers_ns = Namespace::Handle(
      Namespace::New(wrappers_lib, Array::Handle(), Array::Handle()));
  lib.AddImport(wrappers_ns);
  isolate->object_store()->set_mirrors_library(lib);
}


void Library::InitScalarlistLibrary(Isolate* isolate) {
  const String& url = String::Handle(Symbols::New("dart:scalarlist"));
  const Library& lib = Library::Handle(Library::NewLibraryHelper(url, true));
  lib.Register();
  const Library& collection_lib =
      Library::Handle(Library::CollectionLibrary());
  const Namespace& collection_ns = Namespace::Handle(
      Namespace::New(collection_lib, Array::Handle(), Array::Handle()));
  lib.AddImport(collection_ns);
  isolate->object_store()->set_scalarlist_library(lib);
}


void Library::InitNativeWrappersLibrary(Isolate* isolate) {
  static const int kNumNativeWrappersClasses = 4;
  ASSERT(kNumNativeWrappersClasses > 0 && kNumNativeWrappersClasses < 10);
  const String& native_flds_lib_url = String::Handle(
      Symbols::New("dart:nativewrappers"));
  const Library& native_flds_lib = Library::Handle(
      Library::NewLibraryHelper(native_flds_lib_url, false));
  native_flds_lib.Register();
  isolate->object_store()->set_native_wrappers_library(native_flds_lib);
  static const char* const kNativeWrappersClass = "NativeFieldWrapperClass";
  static const int kNameLength = 25;
  ASSERT(kNameLength == (strlen(kNativeWrappersClass) + 1 + 1));
  char name_buffer[kNameLength];
  String& cls_name = String::Handle();
  for (int fld_cnt = 1; fld_cnt <= kNumNativeWrappersClasses; fld_cnt++) {
    OS::SNPrint(name_buffer,
                kNameLength,
                "%s%d",
                kNativeWrappersClass,
                fld_cnt);
    cls_name = Symbols::New(name_buffer);
    Class::NewNativeWrapper(native_flds_lib, cls_name, fld_cnt);
  }
}


RawLibrary* Library::LookupLibrary(const String &url) {
  Isolate* isolate = Isolate::Current();
  Library& lib = Library::Handle(isolate, Library::null());
  String& lib_url = String::Handle(isolate, String::null());
  GrowableObjectArray& libs = GrowableObjectArray::Handle(
      isolate, isolate->object_store()->libraries());
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    lib_url = lib.url();
    if (lib_url.Equals(url)) {
      return lib.raw();
    }
  }
  return Library::null();
}


RawError* Library::Patch(const Script& script) const {
  ASSERT(script.kind() == RawScript::kPatchTag);
  return Compiler::Compile(*this, script);
}


bool Library::IsKeyUsed(intptr_t key) {
  intptr_t lib_key;
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      Isolate::Current()->object_store()->libraries());
  Library& lib = Library::Handle();
  String& lib_url = String::Handle();
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    lib_url ^= lib.url();
    lib_key = lib_url.Hash();
    if (lib_key == key) {
      return true;
    }
  }
  return false;
}


RawString* Library::PrivateName(const String& name) const {
  ASSERT(ShouldBePrivate(name));
  // ASSERT(strchr(name, '@') == NULL);
  String& str = String::Handle();
  str ^= name.raw();
  str = String::Concat(str, String::Handle(this->private_key()));
  str = Symbols::New(str);
  return str.raw();
}


RawLibrary* Library::GetLibrary(intptr_t index) {
  Isolate* isolate = Isolate::Current();
  const GrowableObjectArray& libs =
      GrowableObjectArray::Handle(isolate->object_store()->libraries());
  ASSERT(!libs.IsNull());
  if ((0 <= index) && (index < libs.Length())) {
    Library& lib = Library::Handle();
    lib ^= libs.At(index);
    return lib.raw();
  }
  return Library::null();
}


void Library::Register() const {
  ASSERT(Library::LookupLibrary(String::Handle(url())) == Library::null());
  ObjectStore* object_store = Isolate::Current()->object_store();
  GrowableObjectArray& libs =
      GrowableObjectArray::Handle(object_store->libraries());
  ASSERT(!libs.IsNull());
  set_index(libs.Length());
  libs.Add(*this);
}


RawLibrary* Library::CoreLibrary() {
  return Isolate::Current()->object_store()->core_library();
}


RawLibrary* Library::CollectionLibrary() {
  return Isolate::Current()->object_store()->collection_library();
}


RawLibrary* Library::MathLibrary() {
  return Isolate::Current()->object_store()->math_library();
}


RawLibrary* Library::IsolateLibrary() {
  return Isolate::Current()->object_store()->isolate_library();
}


RawLibrary* Library::MirrorsLibrary() {
  return Isolate::Current()->object_store()->mirrors_library();
}


RawLibrary* Library::ScalarlistLibrary() {
  return Isolate::Current()->object_store()->scalarlist_library();
}


RawLibrary* Library::NativeWrappersLibrary() {
  return Isolate::Current()->object_store()->native_wrappers_library();
}


const char* Library::ToCString() const {
  const char* kFormat = "Library:'%s'";
  const String& name = String::Handle(url());
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString()) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, name.ToCString());
  return chars;
}


RawLibrary* LibraryPrefix::GetLibrary(int index) const {
  if ((index >= 0) || (index < num_imports())) {
    const Array& imports = Array::Handle(this->imports());
    const Namespace& import = Namespace::CheckedHandle(imports.At(index));
    return import.library();
  }
  return Library::null();
}


bool LibraryPrefix::ContainsLibrary(const Library& library) const {
  intptr_t num_current_imports = num_imports();
  if (num_current_imports > 0) {
    Library& lib = Library::Handle();
    const String& url = String::Handle(library.url());
    String& lib_url = String::Handle();
    for (intptr_t i = 0; i < num_current_imports; i++) {
      lib = GetLibrary(i);
      ASSERT(!lib.IsNull());
      lib_url = lib.url();
      if (url.Equals(lib_url)) {
        return true;
      }
    }
  }
  return false;
}


void LibraryPrefix::AddImport(const Namespace& import) const {
  intptr_t num_current_imports = num_imports();

  // The library needs to be added to the list.
  Array& imports = Array::Handle(this->imports());
  const intptr_t length = (imports.IsNull()) ? 0 : imports.Length();
  // Grow the list if it is full.
  if (num_current_imports >= length) {
    const intptr_t new_length = length + kIncrementSize;
    imports = Array::Grow(imports, new_length, Heap::kOld);
    set_imports(imports);
  }
  imports.SetAt(num_current_imports, import);
  set_num_imports(num_current_imports + 1);
}


RawClass* LibraryPrefix::LookupLocalClass(const String& class_name) const {
  Array& imports = Array::Handle(this->imports());
  Object& obj = Object::Handle();
  Namespace& import = Namespace::Handle();
  for (intptr_t i = 0; i < num_imports(); i++) {
    import ^= imports.At(i);
    obj = import.Lookup(class_name);
    if (!obj.IsNull() && obj.IsClass()) {
      // TODO(hausner):
      return Class::Cast(obj).raw();
    }
  }
  return Class::null();
}


RawLibraryPrefix* LibraryPrefix::New() {
  ASSERT(Object::library_prefix_class() != Class::null());
  RawObject* raw = Object::Allocate(LibraryPrefix::kClassId,
                                    LibraryPrefix::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawLibraryPrefix*>(raw);
}


RawLibraryPrefix* LibraryPrefix::New(const String& name,
                                     const Namespace& import) {
  const LibraryPrefix& result = LibraryPrefix::Handle(LibraryPrefix::New());
  result.set_name(name);
  result.set_num_imports(0);
  result.set_imports(Array::Handle(Array::New(kInitialSize)));
  result.AddImport(import);
  return result.raw();
}


void LibraryPrefix::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  StorePointer(&raw_ptr()->name_, value.raw());
}


void LibraryPrefix::set_imports(const Array& value) const {
  StorePointer(&raw_ptr()->imports_, value.raw());
}


void LibraryPrefix::set_num_imports(intptr_t value) const {
  raw_ptr()->num_imports_ = value;
}


const char* LibraryPrefix::ToCString() const {
  const char* kFormat = "LibraryPrefix:'%s'";
  const String& prefix = String::Handle(name());
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, prefix.ToCString()) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, prefix.ToCString());
  return chars;
}


const char* Namespace::ToCString() const {
  const char* kFormat = "Namespace for library '%s'";
  const Library& lib = Library::Handle(library());
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, lib.ToCString()) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, lib.ToCString());
  return chars;
}


bool Namespace::HidesName(const String& name) const {
  // Check whether the name is in the list of explicitly hidden names.
  if (hide_names() != Array::null()) {
    const Array& names = Array::Handle(hide_names());
    String& hidden = String::Handle();
    intptr_t num_names = names.Length();
    for (intptr_t i = 0; i < num_names; i++) {
      hidden ^= names.At(i);
      if (name.Equals(hidden)) {
        return true;
      }
    }
  }
  // The name is not explicitly hidden. Now check whether it is in the
  // list of explicitly visible names, if there is one.
  if (show_names() != Array::null()) {
    const Array& names = Array::Handle(show_names());
    String& shown = String::Handle();
    intptr_t num_names = names.Length();
    for (intptr_t i = 0; i < num_names; i++) {
      shown ^= names.At(i);
      if (name.Equals(shown)) {
        return false;
      }
    }
    // There is a list of visible names. The name we're looking for is not
    // contained in the list, so it is hidden.
    return true;
  }
  // The name is not filtered out.
  return false;
}


RawObject* Namespace::Lookup(const String& name) const {
  const Library& lib = Library::Handle(library());
  intptr_t ignore = 0;
  // Lookup the name in the library's symbols.
  Object& obj = Object::Handle(lib.LookupEntry(name, &ignore));
  if (obj.IsNull()) {
    // Lookup in the re-exported symbols.
    obj = lib.LookupExport(name);
  }
  if (obj.IsNull() || HidesName(name)) {
    return Object::null();
  }
  return obj.raw();
}


RawNamespace* Namespace::New() {
  ASSERT(Object::namespace_class() != Class::null());
  RawObject* raw = Object::Allocate(Namespace::kClassId,
                                    Namespace::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawNamespace*>(raw);
}


RawNamespace* Namespace::New(const Library& library,
                             const Array& show_names,
                             const Array& hide_names) {
  ASSERT(show_names.IsNull() || (show_names.Length() > 0));
  ASSERT(hide_names.IsNull() || (hide_names.Length() > 0));
  const Namespace& result = Namespace::Handle(Namespace::New());
  result.StorePointer(&result.raw_ptr()->library_, library.raw());
  result.StorePointer(&result.raw_ptr()->show_names_, show_names.raw());
  result.StorePointer(&result.raw_ptr()->hide_names_, hide_names.raw());
  return result.raw();
}


RawError* Library::CompileAll() {
  Error& error = Error::Handle();
  const GrowableObjectArray& libs = GrowableObjectArray::Handle(
      Isolate::Current()->object_store()->libraries());
  Library& lib = Library::Handle();
  Class& cls = Class::Handle();
  for (int i = 0; i < libs.Length(); i++) {
    lib ^= libs.At(i);
    ClassDictionaryIterator it(lib);
    while (it.HasNext()) {
      cls ^= it.GetNextClass();
      if (!cls.is_interface()) {
        error = Compiler::CompileAllFunctions(cls);
        if (!error.IsNull()) {
          return error.raw();
        }
      }
    }
    Array& anon_classes = Array::Handle(lib.raw_ptr()->anonymous_classes_);
    for (int i = 0; i < lib.raw_ptr()->num_anonymous_; i++) {
      cls ^= anon_classes.At(i);
      ASSERT(!cls.is_interface());
      error = Compiler::CompileAllFunctions(cls);
      if (!error.IsNull()) {
        return error.raw();
      }
    }
  }
  return error.raw();
}


RawInstructions* Instructions::New(intptr_t size) {
  ASSERT(Object::instructions_class() != Class::null());
  if (size < 0 || size > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Instructions::New: invalid size %"Pd"\n", size);
  }
  Instructions& result = Instructions::Handle();
  {
    uword aligned_size = Instructions::InstanceSize(size);
    RawObject* raw = Object::Allocate(Instructions::kClassId,
                                      aligned_size,
                                      Heap::kCode);
    NoGCScope no_gc;
    result ^= raw;
    result.set_size(size);
  }
  return result.raw();
}


const char* Instructions::ToCString() const {
  return "Instructions";
}


intptr_t PcDescriptors::Length() const {
  return Smi::Value(raw_ptr()->length_);
}


void PcDescriptors::SetLength(intptr_t value) const {
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  raw_ptr()->length_ = Smi::New(value);
}


uword PcDescriptors::PC(intptr_t index) const {
  return static_cast<uword>(*(EntryAddr(index, kPcEntry)));
}


void PcDescriptors::SetPC(intptr_t index, uword value) const {
  *(EntryAddr(index, kPcEntry)) = static_cast<intptr_t>(value);
}


PcDescriptors::Kind PcDescriptors::DescriptorKind(intptr_t index) const {
  return static_cast<PcDescriptors::Kind>(*(EntryAddr(index, kKindEntry)));
}


void PcDescriptors::SetKind(intptr_t index, PcDescriptors::Kind value) const {
  *(EntryAddr(index, kKindEntry)) = value;
}


intptr_t PcDescriptors::DeoptId(intptr_t index) const {
  return *(EntryAddr(index, kDeoptIdEntry));
}


void PcDescriptors::SetDeoptId(intptr_t index, intptr_t value) const {
  *(EntryAddr(index, kDeoptIdEntry)) = value;
}


intptr_t PcDescriptors::TokenPos(intptr_t index) const {
  return *(EntryAddr(index, kTokenPosEntry));
}


void PcDescriptors::SetTokenPos(intptr_t index, intptr_t value) const {
  *(EntryAddr(index, kTokenPosEntry)) = value;
}


intptr_t PcDescriptors::TryIndex(intptr_t index) const {
  return *(EntryAddr(index, kTryIndexEntry));
}


void PcDescriptors::SetTryIndex(intptr_t index, intptr_t value) const {
  *(EntryAddr(index, kTryIndexEntry)) = value;
}


RawPcDescriptors* PcDescriptors::New(intptr_t num_descriptors) {
  ASSERT(Object::pc_descriptors_class() != Class::null());
  if (num_descriptors < 0 || num_descriptors > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in PcDescriptors::New: "
           "invalid num_descriptors %"Pd"\n", num_descriptors);
  }
  PcDescriptors& result = PcDescriptors::Handle();
  {
    uword size = PcDescriptors::InstanceSize(num_descriptors);
    RawObject* raw = Object::Allocate(PcDescriptors::kClassId,
                                      size,
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(num_descriptors);
  }
  return result.raw();
}


const char* PcDescriptors::KindAsStr(intptr_t index) const {
  switch (DescriptorKind(index)) {
    case PcDescriptors::kDeoptBefore:   return "deopt-before ";
    case PcDescriptors::kDeoptAfter:    return "deopt-after  ";
    case PcDescriptors::kPatchCode:     return "patch        ";
    case PcDescriptors::kLazyDeoptJump: return "lazy-deopt   ";
    case PcDescriptors::kIcCall:        return "ic-call      ";
    case PcDescriptors::kFuncCall:      return "fn-call      ";
    case PcDescriptors::kReturn:        return "return       ";
    case PcDescriptors::kOther:         return "other        ";
  }
  UNREACHABLE();
  return "";
}


void PcDescriptors::PrintHeaderString() {
  // 4 bits per hex digit + 2 for "0x".
  const int addr_width = (kBitsPerWord / 4) + 2;
  // "*" in a printf format specifier tells it to read the field width from
  // the printf argument list.
  OS::Print("%-*s\tkind    \tdeopt-id\ttok-ix\ttry-ix\n",
            addr_width, "pc");
}


const char* PcDescriptors::ToCString() const {
  if (Length() == 0) {
    return "No pc descriptors\n";
  }
  // 4 bits per hex digit.
  const int addr_width = kBitsPerWord / 4;
  // "*" in a printf format specifier tells it to read the field width from
  // the printf argument list.
  const char* kFormat =
      "%#-*"Px"\t%s\t%"Pd"\t\t%"Pd"\t%"Pd"\n";
  // First compute the buffer size required.
  intptr_t len = 1;  // Trailing '\0'.
  for (intptr_t i = 0; i < Length(); i++) {
    len += OS::SNPrint(NULL, 0, kFormat, addr_width,
                       PC(i),
                       KindAsStr(i),
                       DeoptId(i),
                       TokenPos(i),
                       TryIndex(i));
  }
  // Allocate the buffer.
  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
  // Layout the fields in the buffer.
  intptr_t index = 0;
  for (intptr_t i = 0; i < Length(); i++) {
    index += OS::SNPrint((buffer + index), (len - index), kFormat, addr_width,
                         PC(i),
                         KindAsStr(i),
                         DeoptId(i),
                         TokenPos(i),
                         TryIndex(i));
  }
  return buffer;
}


// Verify assumptions (in debug mode only).
// - No two deopt descriptors have the same deoptimization id.
// - No two ic-call descriptors have the same deoptimization id (type feedback).
// A function without unique ids is marked as non-optimizable (e.g., because of
// finally blocks).
void PcDescriptors::Verify(const Function& function) const {
#if defined(DEBUG)
  // TODO(srdjan): Implement a more efficient way to check, currently drop
  // the check for too large number of descriptors.
  if (Length() > 3000) {
    if (FLAG_trace_compiler) {
      OS::Print("Not checking pc decriptors, length %"Pd"\n", Length());
    }
    return;
  }
  // Only check ids for unoptimized code that is optimizable.
  if (!function.is_optimizable()) return;
  for (intptr_t i = 0; i < Length(); i++) {
    PcDescriptors::Kind kind = DescriptorKind(i);
    // 'deopt_id' is set for kDeopt and kIcCall and must be unique for one kind.
    intptr_t deopt_id = Isolate::kNoDeoptId;
    if ((DescriptorKind(i) == PcDescriptors::kDeoptBefore) ||
        (DescriptorKind(i) == PcDescriptors::kIcCall)) {
      deopt_id = DeoptId(i);
    }
    for (intptr_t k = i + 1; k < Length(); k++) {
      if (kind == DescriptorKind(k)) {
        if (deopt_id != Isolate::kNoDeoptId) {
          ASSERT(DeoptId(k) != deopt_id);
        }
      }
    }
  }
#endif  // DEBUG
}


uword PcDescriptors::GetPcForKind(Kind kind) const {
  for (intptr_t i = 0; i < Length(); i++) {
    if (DescriptorKind(i) == kind) {
      return PC(i);
    }
  }
  return 0;
}


void Stackmap::SetCode(const dart::Code& code) const {
  StorePointer(&raw_ptr()->code_, code.raw());
}


bool Stackmap::GetBit(intptr_t bit_index) const {
  ASSERT(InRange(bit_index));
  int byte_index = bit_index >> kBitsPerByteLog2;
  int bit_remainder = bit_index & (kBitsPerByte - 1);
  uint8_t byte_mask = 1U << bit_remainder;
  uint8_t byte = raw_ptr()->data_[byte_index];
  return (byte & byte_mask);
}


void Stackmap::SetBit(intptr_t bit_index, bool value) const {
  ASSERT(InRange(bit_index));
  int byte_index = bit_index >> kBitsPerByteLog2;
  int bit_remainder = bit_index & (kBitsPerByte - 1);
  uint8_t byte_mask = 1U << bit_remainder;
  uint8_t* byte_addr = &(raw_ptr()->data_[byte_index]);
  if (value) {
    *byte_addr |= byte_mask;
  } else {
    *byte_addr &= ~byte_mask;
  }
}


RawStackmap* Stackmap::New(intptr_t pc_offset,
                           BitmapBuilder* bmap,
                           intptr_t register_bit_count) {
  ASSERT(Object::stackmap_class() != Class::null());
  ASSERT(bmap != NULL);
  Stackmap& result = Stackmap::Handle();
  // Guard against integer overflow of the instance size computation.
  intptr_t length = bmap->Length();
  intptr_t payload_size =
      Utils::RoundUp(length, kBitsPerByte) / kBitsPerByte;
  if ((payload_size < 0) ||
      (payload_size >
           (kSmiMax - static_cast<intptr_t>(sizeof(RawStackmap))))) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Stackmap::New: invalid length %"Pd"\n",
           length);
  }
  {
    // Stackmap data objects are associated with a code object, allocate them
    // in old generation.
    RawObject* raw = Object::Allocate(Stackmap::kClassId,
                                      Stackmap::InstanceSize(length),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(length);
  }
  // When constructing a stackmap we store the pc offset in the stackmap's
  // PC. StackmapTableBuilder::FinalizeStackmaps will replace it with the pc
  // address.
  ASSERT(pc_offset >= 0);
  result.SetPC(pc_offset);
  for (intptr_t i = 0; i < length; ++i) {
    result.SetBit(i, bmap->Get(i));
  }
  result.SetRegisterBitCount(register_bit_count);
  return result.raw();
}


const char* Stackmap::ToCString() const {
  if (IsNull()) {
    return "{null}";
  } else {
    const char* kFormat = "%#"Px": ";
    intptr_t fixed_length = OS::SNPrint(NULL, 0, kFormat, PC()) + 1;
    Isolate* isolate = Isolate::Current();
    // Guard against integer overflow in the computation of alloc_size.
    //
    // TODO(kmillikin): We could just truncate the string if someone
    // tries to print a 2 billion plus entry stackmap.
    if (Length() > (kIntptrMax - fixed_length)) {
      FATAL1("Length() is unexpectedly large (%"Pd")", Length());
    }
    intptr_t alloc_size = fixed_length + Length();
    char* chars = isolate->current_zone()->Alloc<char>(alloc_size);
    intptr_t index = OS::SNPrint(chars, alloc_size, kFormat, PC());
    for (intptr_t i = 0; i < Length(); i++) {
      chars[index++] = IsObject(i) ? '1' : '0';
    }
    chars[index] = '\0';
    return chars;
  }
}


RawString* LocalVarDescriptors::GetName(intptr_t var_index) const {
  ASSERT(var_index < Length());
  const Array& names = Array::Handle(raw_ptr()->names_);
  ASSERT(Length() == names.Length());
  const String& name = String::CheckedHandle(names.At(var_index));
  return name.raw();
}


void LocalVarDescriptors::SetVar(intptr_t var_index,
                                 const String& name,
                                 RawLocalVarDescriptors::VarInfo* info) const {
  ASSERT(var_index < Length());
  const Array& names = Array::Handle(raw_ptr()->names_);
  ASSERT(Length() == names.Length());
  names.SetAt(var_index, name);
  raw_ptr()->data_[var_index] = *info;
}


void LocalVarDescriptors::GetInfo(intptr_t var_index,
                                  RawLocalVarDescriptors::VarInfo* info) const {
  ASSERT(var_index < Length());
  *info = raw_ptr()->data_[var_index];
}


const char* LocalVarDescriptors::ToCString() const {
  UNIMPLEMENTED();
  return "LocalVarDescriptors";
}


RawLocalVarDescriptors* LocalVarDescriptors::New(intptr_t num_variables) {
  ASSERT(Object::var_descriptors_class() != Class::null());
  if (num_variables < 0 || num_variables > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in LocalVarDescriptors::New: "
           "invalid num_variables %"Pd"\n", num_variables);
  }
  LocalVarDescriptors& result = LocalVarDescriptors::Handle();
  {
    uword size = LocalVarDescriptors::InstanceSize(num_variables);
    RawObject* raw = Object::Allocate(LocalVarDescriptors::kClassId,
                                      size,
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.raw_ptr()->length_ = num_variables;
  }
  const Array& names = Array::Handle(Array::New(num_variables, Heap::kOld));
  result.raw_ptr()->names_ = names.raw();
  return result.raw();
}


intptr_t LocalVarDescriptors::Length() const {
  return raw_ptr()->length_;
}


intptr_t ExceptionHandlers::Length() const {
  return Smi::Value(raw_ptr()->length_);
}


void ExceptionHandlers::SetLength(intptr_t value) const {
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  raw_ptr()->length_ = Smi::New(value);
}


intptr_t ExceptionHandlers::TryIndex(intptr_t index) const {
  return *(EntryAddr(index, kTryIndexEntry));
}


void ExceptionHandlers::SetTryIndex(intptr_t index, intptr_t value) const {
  *(EntryAddr(index, kTryIndexEntry)) = value;
}


intptr_t ExceptionHandlers::HandlerPC(intptr_t index) const {
  return *(EntryAddr(index, kHandlerPcEntry));
}


void ExceptionHandlers::SetHandlerPC(intptr_t index,
                                     intptr_t value) const {
  *(EntryAddr(index, kHandlerPcEntry)) = value;
}


RawExceptionHandlers* ExceptionHandlers::New(intptr_t num_handlers) {
  ASSERT(Object::exception_handlers_class() != Class::null());
  if (num_handlers < 0 || num_handlers > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ExceptionHandlers::New: "
           "invalid num_handlers %"Pd"\n",
           num_handlers);
  }
  ExceptionHandlers& result = ExceptionHandlers::Handle();
  {
    uword size = ExceptionHandlers::InstanceSize(num_handlers);
    RawObject* raw = Object::Allocate(ExceptionHandlers::kClassId,
                                      size,
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(num_handlers);
  }
  return result.raw();
}


const char* ExceptionHandlers::ToCString() const {
  if (Length() == 0) {
    return "No exception handlers\n";
  }
  // First compute the buffer size required.
  const char* kFormat = "%"Pd" => %#"Px"\n";
  intptr_t len = 1;  // Trailing '\0'.
  for (intptr_t i = 0; i < Length(); i++) {
    len += OS::SNPrint(NULL, 0, kFormat, TryIndex(i), HandlerPC(i));
  }
  // Allocate the buffer.
  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
  // Layout the fields in the buffer.
  intptr_t index = 0;
  for (intptr_t i = 0; i < Length(); i++) {
    index += OS::SNPrint((buffer + index),
                         (len - index),
                         kFormat,
                         TryIndex(i),
                         HandlerPC(i));
  }
  return buffer;
}


intptr_t DeoptInfo::Length() const {
  return Smi::Value(raw_ptr()->length_);
}


intptr_t DeoptInfo::FromIndex(intptr_t index) const {
  return *(EntryAddr(index, kFromIndex));
}


intptr_t DeoptInfo::Instruction(intptr_t index) const {
  return *(EntryAddr(index, kInstruction));
}


intptr_t DeoptInfo::TranslationLength() const {
  intptr_t length = Length();
  if (Instruction(length - 1) != DeoptInstr::kSuffix) return length;

  // If the last command is a suffix, add in the length of the suffix and
  // do not count the suffix command as a translation command.
  intptr_t ignored = 0;
  intptr_t suffix_length =
      DeoptInstr::DecodeSuffix(FromIndex(length - 1), &ignored);
  return length + suffix_length - 1;
}


void DeoptInfo::ToInstructions(const Array& table,
                               GrowableArray<DeoptInstr*>* instructions) const {
  ASSERT(instructions->is_empty());
  Smi& offset = Smi::Handle();
  DeoptInfo& info = DeoptInfo::Handle(raw());
  Smi& reason = Smi::Handle();
  intptr_t index = 0;
  intptr_t length = TranslationLength();
  while (index < length) {
    intptr_t instruction = info.Instruction(index);
    intptr_t from_index = info.FromIndex(index);
    if (instruction == DeoptInstr::kSuffix) {
      // Suffix instructions cause us to 'jump' to another translation,
      // changing info, length and index.
      intptr_t info_number = 0;
      intptr_t suffix_length =
          DeoptInstr::DecodeSuffix(from_index, &info_number);
      DeoptTable::GetEntry(table, info_number, &offset, &info, &reason);
      length = info.TranslationLength();
      index = length - suffix_length;
    } else {
      instructions->Add(DeoptInstr::Create(instruction, from_index));
      ++index;
    }
  }
}


const char* DeoptInfo::ToCString() const {
  if (Length() == 0) {
    return "No DeoptInfo";
  }
  // Convert to DeoptInstr.
  GrowableArray<DeoptInstr*> deopt_instrs(Length());
  for (intptr_t i = 0; i < Length(); i++) {
    deopt_instrs.Add(DeoptInstr::Create(Instruction(i), FromIndex(i)));
  }
  // Compute the buffer size required.
  intptr_t len = 1;  // Trailing '\0'.
  for (intptr_t i = 0; i < Length(); i++) {
    len += OS::SNPrint(NULL, 0, "[%s]", deopt_instrs[i]->ToCString());
  }
  // Allocate the buffer.
  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len);
  // Layout the fields in the buffer.
  intptr_t index = 0;
  for (intptr_t i = 0; i < Length(); i++) {
    index += OS::SNPrint((buffer + index),
                         (len - index),
                         "[%s]",
                         deopt_instrs[i]->ToCString());
  }
  return buffer;
}


RawDeoptInfo* DeoptInfo::New(intptr_t num_commands) {
  ASSERT(Object::deopt_info_class() != Class::null());
  DeoptInfo& result = DeoptInfo::Handle();
  {
    uword size = DeoptInfo::InstanceSize(num_commands);
    RawObject* raw = Object::Allocate(DeoptInfo::kClassId,
                                      size,
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(num_commands);
  }
  return result.raw();
}


void DeoptInfo::SetLength(intptr_t value) const {
  // This is only safe because we create a new Smi, which does not cause
  // heap allocation.
  raw_ptr()->length_ = Smi::New(value);
}


void DeoptInfo::SetAt(intptr_t index,
                      intptr_t instr_kind,
                      intptr_t from_index) const {
  *(EntryAddr(index, kInstruction)) = instr_kind;
  *(EntryAddr(index, kFromIndex)) = from_index;
}


Code::Comments& Code::Comments::New(intptr_t count) {
  Comments* comments;
  if (count < 0 || count > (kIntptrMax / kNumberOfEntries)) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Code::Comments::New: invalid count %"Pd"\n", count);
  }
  if (count == 0) {
    comments = new Comments(Object::empty_array());
  } else {
    comments = new Comments(Array::New(count * kNumberOfEntries));
  }
  return *comments;
}


intptr_t Code::Comments::Length() const {
  if (comments_.IsNull()) {
    return 0;
  }
  return comments_.Length() / kNumberOfEntries;
}


intptr_t Code::Comments::PCOffsetAt(intptr_t idx) const {
  return Smi::CheckedHandle(
      comments_.At(idx * kNumberOfEntries + kPCOffsetEntry)).Value();
}


void Code::Comments::SetPCOffsetAt(intptr_t idx, intptr_t pc)  {
  comments_.SetAt(idx * kNumberOfEntries + kPCOffsetEntry,
                  Smi::Handle(Smi::New(pc)));
}


const String& Code::Comments::CommentAt(intptr_t idx) const {
  return String::CheckedHandle(
      comments_.At(idx * kNumberOfEntries + kCommentEntry));
}


void Code::Comments::SetCommentAt(intptr_t idx, const String& comment) {
  comments_.SetAt(idx * kNumberOfEntries + kCommentEntry, comment);
}


Code::Comments::Comments(RawArray* comments)
    : comments_(Array::Handle(comments)) {
}


void Code::set_stackmaps(const Array& maps) const {
  StorePointer(&raw_ptr()->stackmaps_, maps.raw());
}


void Code::set_deopt_info_array(const Array& array) const {
  StorePointer(&raw_ptr()->deopt_info_array_, array.raw());
}


void Code::set_object_table(const Array& array) const {
  StorePointer(&raw_ptr()->object_table_, array.raw());
}


void Code::set_static_calls_target_table(const Array& value) const {
  StorePointer(&raw_ptr()->static_calls_target_table_, value.raw());
}


RawFunction* Code::GetStaticCallTargetFunctionAt(uword pc) const {
  RawObject* raw_code_offset =
      reinterpret_cast<RawObject*>(Smi::New(pc - EntryPoint()));
  const Array& array =
      Array::Handle(raw_ptr()->static_calls_target_table_);
  for (intptr_t i = 0; i < array.Length(); i += kSCallTableEntryLength) {
    if (array.At(i) == raw_code_offset) {
      Function& function = Function::Handle();
      function ^= array.At(i + kSCallTableFunctionEntry);
      return function.raw();
    }
  }
  return Function::null();
}


void Code::SetStaticCallTargetCodeAt(uword pc, const Code& code) const {
  RawObject* raw_code_offset =
      reinterpret_cast<RawObject*>(Smi::New(pc - EntryPoint()));
  const Array& array =
      Array::Handle(raw_ptr()->static_calls_target_table_);
  for (intptr_t i = 0; i < array.Length(); i += kSCallTableEntryLength) {
    if (array.At(i) == raw_code_offset) {
      ASSERT(code.IsNull() ||
             (code.function() == array.At(i + kSCallTableFunctionEntry)));
      array.SetAt(i + kSCallTableCodeEntry, code);
      return;
    }
  }
  UNREACHABLE();
}


const Code::Comments& Code::comments() const  {
  Comments* comments = new Code::Comments(raw_ptr()->comments_);
  return *comments;
}


void Code::set_comments(const Code::Comments& comments) const {
  StorePointer(&raw_ptr()->comments_, comments.comments_.raw());
}


RawCode* Code::New(intptr_t pointer_offsets_length) {
  if (pointer_offsets_length < 0 || pointer_offsets_length > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Code::New: invalid pointer_offsets_length %"Pd"\n",
           pointer_offsets_length);
  }
  ASSERT(Object::code_class() != Class::null());
  Code& result = Code::Handle();
  {
    uword size = Code::InstanceSize(pointer_offsets_length);
    RawObject* raw = Object::Allocate(Code::kClassId, size, Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.set_pointer_offsets_length(pointer_offsets_length);
    result.set_is_optimized(false);
    result.set_is_alive(true);
    result.set_comments(Comments::New(0));
  }
  return result.raw();
}


RawCode* Code::FinalizeCode(const char* name,
                            Assembler* assembler,
                            bool optimized) {
  ASSERT(assembler != NULL);

  // Allocate the Instructions object.
  Instructions& instrs =
      Instructions::ZoneHandle(Instructions::New(assembler->CodeSize()));

  // Copy the instructions into the instruction area and apply all fixups.
  // Embedded pointers are still in handles at this point.
  MemoryRegion region(reinterpret_cast<void*>(instrs.EntryPoint()),
                      instrs.size());
  assembler->FinalizeInstructions(region);
  Dart_FileWriterFunction perf_events_writer = Dart::perf_events_writer();
  if (perf_events_writer != NULL) {
    const char* format = "%"Px" %"Px" %s%s\n";
    uword addr = instrs.EntryPoint();
    uword size = instrs.size();
    const char* marker = optimized ? "*" : "";
    intptr_t len = OS::SNPrint(NULL, 0, format, addr, size, marker, name);
    char* buffer = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
    OS::SNPrint(buffer, len + 1, format, addr, size, marker, name);
    (*perf_events_writer)(buffer, len);
  }
  DebugInfo* pprof_symbol_generator = Dart::pprof_symbol_generator();
  if (pprof_symbol_generator != NULL) {
    ASSERT(strlen(name) != 0);
    pprof_symbol_generator->AddCode(instrs.EntryPoint(), instrs.size());
    pprof_symbol_generator->AddCodeRegion(name,
                                          instrs.EntryPoint(),
                                          instrs.size());
  }
  if (FLAG_generate_gdb_symbols) {
    ASSERT(strlen(name) != 0);
    intptr_t prolog_offset = assembler->prolog_offset();
    if (prolog_offset > 0) {
      // In order to ensure that gdb sees the first instruction of a function
      // as the prolog sequence we register two symbols for the cases when
      // the prolog sequence is not the first instruction:
      // <name>_entry is used for code preceding the prolog sequence.
      // <name> for rest of the code (first instruction is prolog sequence).
      const char* kFormat = "%s_%s";
      intptr_t len = OS::SNPrint(NULL, 0, kFormat, name, "entry");
      char* pname = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
      OS::SNPrint(pname, (len + 1), kFormat, name, "entry");
      DebugInfo::RegisterSection(pname, instrs.EntryPoint(), prolog_offset);
      DebugInfo::RegisterSection(name,
                                 (instrs.EntryPoint() + prolog_offset),
                                 (instrs.size() - prolog_offset));
    } else {
      DebugInfo::RegisterSection(name, instrs.EntryPoint(), instrs.size());
    }
  }

  const ZoneGrowableArray<int>& pointer_offsets =
      assembler->GetPointerOffsets();

  // Allocate the code object.
  Code& code = Code::ZoneHandle(Code::New(pointer_offsets.length()));
  {
    NoGCScope no_gc;

    // Set pointer offsets list in Code object and resolve all handles in
    // the instruction stream to raw objects.
    ASSERT(code.pointer_offsets_length() == pointer_offsets.length());
    for (int i = 0; i < pointer_offsets.length(); i++) {
      int offset_in_instrs = pointer_offsets[i];
      code.SetPointerOffsetAt(i, offset_in_instrs);
      const Object* object = region.Load<const Object*>(offset_in_instrs);
      region.Store<RawObject*>(offset_in_instrs, object->raw());
    }

    // Hook up Code and Instruction objects.
    instrs.set_code(code.raw());
    code.set_instructions(instrs.raw());
  }
  return code.raw();
}


RawCode* Code::FinalizeCode(const Function& function,
                            Assembler* assembler,
                            bool optimized) {
  // Calling ToFullyQualifiedCString is very expensive, try to avoid it.
  if (FLAG_generate_gdb_symbols ||
      Dart::perf_events_writer() != NULL ||
      Dart::pprof_symbol_generator() != NULL) {
    return FinalizeCode(function.ToFullyQualifiedCString(),
                        assembler,
                        optimized);
  } else {
    return FinalizeCode("", assembler);
  }
}


// Check if object matches find condition.
bool Code::FindRawCodeVisitor::FindObject(RawObject* obj) {
  return RawInstructions::ContainsPC(obj, pc_);
}


RawCode* Code::LookupCode(uword pc) {
  Isolate* isolate = Isolate::Current();
  NoGCScope no_gc;
  FindRawCodeVisitor visitor(pc);
  RawInstructions* instr;
  instr = isolate->heap()->FindObjectInCodeSpace(&visitor);
  if (instr != Instructions::null()) {
    return instr->ptr()->code_;
  }
  return Code::null();
}


intptr_t Code::GetTokenIndexOfPC(uword pc) const {
  intptr_t token_pos = -1;
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  for (intptr_t i = 0; i < descriptors.Length(); i++) {
    if (descriptors.PC(i) == pc) {
      token_pos = descriptors.TokenPos(i);
      break;
    }
  }
  return token_pos;
}


uword Code::GetPcForDeoptId(intptr_t deopt_id, PcDescriptors::Kind kind) const {
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  for (intptr_t i = 0; i < descriptors.Length(); i++) {
    if ((descriptors.DeoptId(i) == deopt_id) &&
        (descriptors.DescriptorKind(i) == kind)) {
      uword pc = descriptors.PC(i);
      ASSERT((EntryPoint() < pc) && (pc < (EntryPoint() + Size())));
      return pc;
    }
  }
  return 0;
}


uword Code::GetDeoptBeforePcAtDeoptId(intptr_t deopt_id) const {
  ASSERT(!is_optimized());
  return GetPcForDeoptId(deopt_id, PcDescriptors::kDeoptBefore);
}


uword Code::GetDeoptAfterPcAtDeoptId(intptr_t deopt_id) const {
  ASSERT(!is_optimized());
  return GetPcForDeoptId(deopt_id, PcDescriptors::kDeoptAfter);
}


const char* Code::ToCString() const {
  const char* kFormat = "Code entry:%p";
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, EntryPoint()) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, EntryPoint());
  return chars;
}


uword Code::GetPatchCodePc() const {
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  return descriptors.GetPcForKind(PcDescriptors::kPatchCode);
}


uword Code::GetLazyDeoptPc() const {
  const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
  return descriptors.GetPcForKind(PcDescriptors::kLazyDeoptJump);
}


bool Code::ObjectExistsInArea(intptr_t start_offset,
                              intptr_t end_offset) const {
  for (intptr_t i = 0; i < this->pointer_offsets_length(); i++) {
    const intptr_t offset = this->GetPointerOffsetAt(i);
    if ((start_offset <= offset) && (offset < end_offset)) {
      return false;
    }
  }
  return true;
}


intptr_t Code::ExtractIcDataArraysAtCalls(
    GrowableArray<intptr_t>* node_ids,
    const GrowableObjectArray& ic_data_objs) const {
  ASSERT(node_ids != NULL);
  ASSERT(!ic_data_objs.IsNull());
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(this->pc_descriptors());
  ICData& ic_data_obj = ICData::Handle();
  intptr_t max_id = -1;
  for (intptr_t i = 0; i < descriptors.Length(); i++) {
    if (descriptors.DescriptorKind(i) == PcDescriptors::kIcCall) {
      intptr_t deopt_id = descriptors.DeoptId(i);
      if (deopt_id > max_id) {
        max_id = deopt_id;
      }
      node_ids->Add(deopt_id);
      ic_data_obj = CodePatcher::GetInstanceCallIcDataAt(descriptors.PC(i));
      ic_data_objs.Add(ic_data_obj);
    }
  }
  return max_id;
}


RawArray* Code::ExtractTypeFeedbackArray() const {
  ASSERT(!IsNull() && !is_optimized());
  GrowableArray<intptr_t> deopt_ids;
  const GrowableObjectArray& ic_data_objs =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  const intptr_t max_id =
      ExtractIcDataArraysAtCalls(&deopt_ids, ic_data_objs);
  const Array& result = Array::Handle(Array::New(max_id + 1));
  for (intptr_t i = 0; i < deopt_ids.length(); i++) {
    intptr_t result_index = deopt_ids[i];
    ASSERT(result.At(result_index) == Object::null());
    result.SetAt(result_index, Object::Handle(ic_data_objs.At(i)));
  }
  return result.raw();
}


void Code::ExtractUncalledStaticCallDeoptIds(
    GrowableArray<intptr_t>* deopt_ids) const {
  ASSERT(!IsNull() && !is_optimized());
  ASSERT(deopt_ids != NULL);
  deopt_ids->Clear();
  const PcDescriptors& descriptors =
      PcDescriptors::Handle(this->pc_descriptors());
  for (intptr_t i = 0; i < descriptors.Length(); i++) {
    if (descriptors.DescriptorKind(i) == PcDescriptors::kFuncCall) {
      // Static call.
      const uword target_addr =
          CodePatcher::GetStaticCallTargetAt(descriptors.PC(i));
      if (target_addr == StubCode::CallStaticFunctionEntryPoint()) {
        deopt_ids->Add(descriptors.DeoptId(i));
      }
    }
  }
}


RawStackmap* Code::GetStackmap(uword pc, Array* maps, Stackmap* map) const {
  // This code is used during iterating frames during a GC and hence it
  // should not in turn start a GC.
  NoGCScope no_gc;
  if (stackmaps() == Array::null()) {
    // No stack maps are present in the code object which means this
    // frame relies on tagged pointers.
    return Stackmap::null();
  }
  // A stack map is present in the code object, use the stack map to visit
  // frame slots which are marked as having objects.
  *maps = stackmaps();
  *map = Stackmap::null();
  for (intptr_t i = 0; i < maps->Length(); i++) {
    *map ^= maps->At(i);
    ASSERT(!map->IsNull());
    if (map->PC() == pc) {
      return map->raw();  // We found a stack map for this frame.
    }
  }
  // If the code has stackmaps, it must have them for all safepoints.
  UNREACHABLE();
  return Stackmap::null();
}


RawContext* Context::New(intptr_t num_variables, Heap::Space space) {
  ASSERT(num_variables >= 0);
  ASSERT(Object::context_class() != Class::null());

  if (num_variables < 0 || num_variables > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Context::New: invalid num_variables %"Pd"\n",
           num_variables);
  }
  Context& result = Context::Handle();
  {
    RawObject* raw = Object::Allocate(Context::kClassId,
                                      Context::InstanceSize(num_variables),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.set_num_variables(num_variables);
  }
  result.set_isolate(Isolate::Current());
  return result.raw();
}


const char* Context::ToCString() const {
  return "Context";
}


RawContextScope* ContextScope::New(intptr_t num_variables) {
  ASSERT(Object::context_scope_class() != Class::null());
  if (num_variables < 0 || num_variables > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ContextScope::New: invalid num_variables %"Pd"\n",
           num_variables);
  }
  intptr_t size = ContextScope::InstanceSize(num_variables);
  ContextScope& result = ContextScope::Handle();
  {
    RawObject* raw = Object::Allocate(ContextScope::kClassId,
                                      size,
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
    result.set_num_variables(num_variables);
  }
  return result.raw();
}


intptr_t ContextScope::TokenIndexAt(intptr_t scope_index) const {
  return Smi::Value(VariableDescAddr(scope_index)->token_pos);
}


void ContextScope::SetTokenIndexAt(intptr_t scope_index,
                                   intptr_t token_pos) const {
  VariableDescAddr(scope_index)->token_pos = Smi::New(token_pos);
}


RawString* ContextScope::NameAt(intptr_t scope_index) const {
  return VariableDescAddr(scope_index)->name;
}


void ContextScope::SetNameAt(intptr_t scope_index, const String& name) const {
  StorePointer(&(VariableDescAddr(scope_index)->name), name.raw());
}


bool ContextScope::IsFinalAt(intptr_t scope_index) const {
  return Bool::Handle(VariableDescAddr(scope_index)->is_final).value();
}


void ContextScope::SetIsFinalAt(intptr_t scope_index, bool is_final) const {
  VariableDescAddr(scope_index)->is_final = Bool::Get(is_final);
}


bool ContextScope::IsConstAt(intptr_t scope_index) const {
  return Bool::Handle(VariableDescAddr(scope_index)->is_const).value();
}


void ContextScope::SetIsConstAt(intptr_t scope_index, bool is_const) const {
  VariableDescAddr(scope_index)->is_const = Bool::Get(is_const);
}


RawAbstractType* ContextScope::TypeAt(intptr_t scope_index) const {
  ASSERT(!IsConstAt(scope_index));
  return VariableDescAddr(scope_index)->type;
}


void ContextScope::SetTypeAt(
    intptr_t scope_index, const AbstractType& type) const {
  StorePointer(&(VariableDescAddr(scope_index)->type), type.raw());
}


RawInstance* ContextScope::ConstValueAt(intptr_t scope_index) const {
  ASSERT(IsConstAt(scope_index));
  return VariableDescAddr(scope_index)->value;
}


void ContextScope::SetConstValueAt(
    intptr_t scope_index, const Instance& value) const {
  ASSERT(IsConstAt(scope_index));
  StorePointer(&(VariableDescAddr(scope_index)->value), value.raw());
}


intptr_t ContextScope::ContextIndexAt(intptr_t scope_index) const {
  return Smi::Value(VariableDescAddr(scope_index)->context_index);
}


void ContextScope::SetContextIndexAt(intptr_t scope_index,
                                     intptr_t context_index) const {
  VariableDescAddr(scope_index)->context_index = Smi::New(context_index);
}


intptr_t ContextScope::ContextLevelAt(intptr_t scope_index) const {
  return Smi::Value(VariableDescAddr(scope_index)->context_level);
}


void ContextScope::SetContextLevelAt(intptr_t scope_index,
                                     intptr_t context_level) const {
  VariableDescAddr(scope_index)->context_level = Smi::New(context_level);
}


const char* ContextScope::ToCString() const {
  return "ContextScope";
}


const char* ICData::ToCString() const {
  const char* kFormat = "ICData target:'%s' num-checks: %"Pd"";
  const String& name = String::Handle(target_name());
  const intptr_t num = NumberOfChecks();
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString(), num) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, name.ToCString(), num);
  return chars;
}


void ICData::set_function(const Function& value) const {
  StorePointer(&raw_ptr()->function_, value.raw());
}


void ICData::set_target_name(const String& value) const {
  StorePointer(&raw_ptr()->target_name_, value.raw());
}


void ICData::set_deopt_id(intptr_t value) const {
  raw_ptr()->deopt_id_ = value;
}


void ICData::set_num_args_tested(intptr_t value) const {
  raw_ptr()->num_args_tested_ = value;
}


void ICData::set_ic_data(const Array& value) const {
  StorePointer(&raw_ptr()->ic_data_, value.raw());
}


void ICData::set_deopt_reason(intptr_t deopt_reason) const {
  raw_ptr()->deopt_reason_ = deopt_reason;
}

void ICData::set_is_closure_call(bool value) const {
  raw_ptr()->is_closure_call_ = value ? 1 : 0;
}


intptr_t ICData::TestEntryLengthFor(intptr_t num_args) {
  return num_args + 1 /* target function*/ + 1 /* frequency */;
}


intptr_t ICData::TestEntryLength() const {
  return TestEntryLengthFor(num_args_tested());
}


intptr_t ICData::NumberOfChecks() const {
  // Do not count the sentinel;
  return (Array::Handle(ic_data()).Length() / TestEntryLength()) - 1;
}


void ICData::WriteSentinel() const {
  const Smi& sentinel_value = Smi::Handle(Smi::New(kIllegalCid));
  const Array& data = Array::Handle(ic_data());
  for (intptr_t i = 1; i <= TestEntryLength(); i++) {
    data.SetAt(data.Length() - i, sentinel_value);
  }
}


#if defined(DEBUG)
// Used in asserts to verify that a check is not added twice.
bool ICData::HasCheck(const GrowableArray<intptr_t>& cids) const {
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    GrowableArray<intptr_t> class_ids;
    Function& target = Function::Handle();
    GetCheckAt(i, &class_ids, &target);
    bool matches = true;
    for (intptr_t k = 0; k < class_ids.length(); k++) {
      if (class_ids[k] != cids[k]) {
        matches = false;
        break;
      }
    }
    if (matches) {
      return true;
    }
  }
  return false;
}
#endif  // DEBUG


void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids,
                      const Function& target) const {
  DEBUG_ASSERT(!HasCheck(class_ids));
  ASSERT(num_args_tested() > 1);  // Otherwise use 'AddReceiverCheck'.
  ASSERT(class_ids.length() == num_args_tested());
  const intptr_t old_num = NumberOfChecks();
  Array& data = Array::Handle(ic_data());
  const intptr_t new_len = data.Length() + TestEntryLength();
  data = Array::Grow(data, new_len, Heap::kOld);
  set_ic_data(data);
  WriteSentinel();
  intptr_t data_pos = old_num * TestEntryLength();
  for (intptr_t i = 0; i < class_ids.length(); i++) {
    // kIllegalCid is used as terminating value, do not add it.
    ASSERT(class_ids[i] != kIllegalCid);
    data.SetAt(data_pos++, Smi::Handle(Smi::New(class_ids[i])));
  }
  ASSERT(!target.IsNull());
  data.SetAt(data_pos++, target);
  data.SetAt(data_pos, Smi::Handle(Smi::New(1)));
}


void ICData::AddReceiverCheck(intptr_t receiver_class_id,
                              const Function& target) const {
#if defined(DEBUG)
  GrowableArray<intptr_t> class_ids(1);
  class_ids.Add(receiver_class_id);
  ASSERT(!HasCheck(class_ids));
#endif  // DEBUG
  ASSERT(num_args_tested() == 1);  // Otherwise use 'AddCheck'.
  ASSERT(receiver_class_id != kIllegalCid);
  ASSERT(!target.IsNull());

  const intptr_t old_num = NumberOfChecks();
  Array& data = Array::Handle(ic_data());
  const intptr_t new_len = data.Length() + TestEntryLength();
  data = Array::Grow(data, new_len, Heap::kOld);
  set_ic_data(data);
  WriteSentinel();
  intptr_t data_pos = old_num * TestEntryLength();
  if ((receiver_class_id == kSmiCid) && (data_pos > 0)) {
    ASSERT(GetReceiverClassIdAt(0) != kSmiCid);
    // Move class occupying position 0 to the data_pos.
    for (intptr_t i = 0; i < TestEntryLength(); i++) {
      data.SetAt(data_pos + i, Object::Handle(data.At(i)));
    }
    // Insert kSmiCid in position 0.
    data_pos = 0;
  }
  data.SetAt(data_pos, Smi::Handle(Smi::New(receiver_class_id)));
  data.SetAt(data_pos + 1, target);
  data.SetAt(data_pos + 2, Smi::Handle(Smi::New(1)));
}


void ICData::GetCheckAt(intptr_t index,
                        GrowableArray<intptr_t>* class_ids,
                        Function* target) const {
  ASSERT(index < NumberOfChecks());
  ASSERT(class_ids != NULL);
  ASSERT(target != NULL);
  class_ids->Clear();
  const Array& data = Array::Handle(ic_data());
  intptr_t data_pos = index * TestEntryLength();
  Smi& smi = Smi::Handle();
  for (intptr_t i = 0; i < num_args_tested(); i++) {
    smi ^= data.At(data_pos++);
    class_ids->Add(smi.Value());
  }
  (*target) ^= data.At(data_pos++);
}


void ICData::GetOneClassCheckAt(intptr_t index,
                                intptr_t* class_id,
                                Function* target) const {
  ASSERT(class_id != NULL);
  ASSERT(target != NULL);
  ASSERT(num_args_tested() == 1);
  const Array& data = Array::Handle(ic_data());
  intptr_t data_pos = index * TestEntryLength();
  Smi& smi = Smi::Handle();
  smi ^= data.At(data_pos);
  *class_id = smi.Value();
  *target ^= data.At(data_pos + 1);
}


intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const {
  GrowableArray<intptr_t> class_ids;
  Function& target = Function::Handle();
  GetCheckAt(index, &class_ids, &target);
  return class_ids[arg_nr];
}


intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const {
  ASSERT(index < NumberOfChecks());
  const Array& data = Array::Handle(ic_data());
  const intptr_t data_pos = index * TestEntryLength();
  Smi& smi = Smi::Handle();
  smi ^= data.At(data_pos);
  return smi.Value();
}


RawFunction* ICData::GetTargetAt(intptr_t index) const {
  const Array& data = Array::Handle(ic_data());
  const intptr_t data_pos = index * TestEntryLength() + num_args_tested();
  ASSERT(Object::Handle(data.At(data_pos)).IsFunction());
  return reinterpret_cast<RawFunction*>(data.At(data_pos));
}


intptr_t ICData::GetCountAt(intptr_t index) const {
  const Array& data = Array::Handle(ic_data());
  const intptr_t data_pos = index * TestEntryLength() +
      CountIndexFor(num_args_tested());
  Smi& smi = Smi::Handle();
  smi ^= data.At(data_pos);
  return smi.Value();
}


RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const {
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    if (GetReceiverClassIdAt(i) == class_id) {
      return GetTargetAt(i);
    }
  }
  return Function::null();
}


RawICData* ICData::AsUnaryClassChecksForArgNr(intptr_t arg_nr) const {
  ASSERT(!IsNull());
  ASSERT(num_args_tested() > arg_nr);
  if ((arg_nr == 0) && (num_args_tested() == 1)) {
    // Frequent case.
    return raw();
  }
  const intptr_t kNumArgsTested = 1;
  ICData& result = ICData::Handle(ICData::New(
      Function::Handle(function()),
      String::Handle(target_name()),
      deopt_id(),
      kNumArgsTested));
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    const intptr_t class_id = GetClassIdAt(i, arg_nr);
    intptr_t duplicate_class_id = -1;
    const intptr_t result_len = result.NumberOfChecks();
    for (intptr_t k = 0; k < result_len; k++) {
      if (class_id == result.GetReceiverClassIdAt(k)) {
        duplicate_class_id = k;
        break;
      }
    }
    if (duplicate_class_id >= 0) {
      // This check is valid only when checking the receiver.
      ASSERT((arg_nr != 0) ||
             (result.GetTargetAt(duplicate_class_id) == GetTargetAt(i)));
    } else {
      // This will make sure that Smi is first if it exists.
      result.AddReceiverCheck(class_id,
                              Function::Handle(GetTargetAt(i)));
    }
  }
  return result.raw();
}


bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const {
  if (NumberOfChecks() == 0) return false;
  Class& cls = Class::Handle();
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    cls = Function::Handle(GetTargetAt(i)).Owner();
    if (cls.id() != owner_cid) {
      return false;
    }
  }
  return true;
}


bool ICData::AllReceiversAreNumbers() const {
  if (NumberOfChecks() == 0) return false;
  Class& cls = Class::Handle();
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 0; i < len; i++) {
    cls = Function::Handle(GetTargetAt(i)).Owner();
    const intptr_t cid = cls.id();
    if ((cid != kSmiCid) &&
        (cid != kMintCid) &&
        (cid != kBigintCid) &&
        (cid != kDoubleCid)) {
      return false;
    }
  }
  return true;
}


// Returns true if all targets are the same.
// TODO(srdjan): if targets are native use their C_function to compare.
bool ICData::HasOneTarget() const {
  ASSERT(NumberOfChecks() > 0);
  const Function& first_target = Function::Handle(GetTargetAt(0));
  const intptr_t len = NumberOfChecks();
  for (intptr_t i = 1; i < len; i++) {
    if (GetTargetAt(i) != first_target.raw()) {
      return false;
    }
  }
  return true;
}


RawICData* ICData::New(const Function& function,
                       const String& target_name,
                       intptr_t deopt_id,
                       intptr_t num_args_tested) {
  ASSERT(Object::icdata_class() != Class::null());
  ASSERT(num_args_tested > 0);
  ICData& result = ICData::Handle();
  {
    // IC data objects are long living objects, allocate them in old generation.
    RawObject* raw = Object::Allocate(ICData::kClassId,
                                      ICData::InstanceSize(),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_function(function);
  result.set_target_name(target_name);
  result.set_deopt_id(deopt_id);
  result.set_num_args_tested(num_args_tested);
  result.set_deopt_reason(kDeoptUnknown);
  result.set_is_closure_call(false);
  // Number of array elements in one test entry.
  intptr_t len = result.TestEntryLength();
  // IC data array must be null terminated (sentinel entry).
  const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld));
  result.set_ic_data(ic_data);
  result.WriteSentinel();
  return result.raw();
}


RawSubtypeTestCache* SubtypeTestCache::New() {
  ASSERT(Object::subtypetestcache_class() != Class::null());
  SubtypeTestCache& result = SubtypeTestCache::Handle();
  {
    // SubtypeTestCache objects are long living objects, allocate them in the
    // old generation.
    RawObject* raw = Object::Allocate(SubtypeTestCache::kClassId,
                                      SubtypeTestCache::InstanceSize(),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
  }
  const Array& cache = Array::Handle(Array::New(kTestEntryLength));
  result.set_cache(cache);
  return result.raw();
}


void SubtypeTestCache::set_cache(const Array& value) const {
  StorePointer(&raw_ptr()->cache_, value.raw());
}


intptr_t SubtypeTestCache::NumberOfChecks() const {
  // Do not count the sentinel;
  return (Array::Handle(cache()).Length() / kTestEntryLength) - 1;
}


void SubtypeTestCache::AddCheck(
    intptr_t instance_class_id,
    const AbstractTypeArguments& instance_type_arguments,
    const AbstractTypeArguments& instantiator_type_arguments,
    const Bool& test_result) const {
  intptr_t old_num = NumberOfChecks();
  Array& data = Array::Handle(cache());
  intptr_t new_len = data.Length() + kTestEntryLength;
  data = Array::Grow(data, new_len);
  set_cache(data);
  intptr_t data_pos = old_num * kTestEntryLength;
  data.SetAt(data_pos + kInstanceClassId,
      Smi::Handle(Smi::New(instance_class_id)));
  data.SetAt(data_pos + kInstanceTypeArguments, instance_type_arguments);
  data.SetAt(data_pos + kInstantiatorTypeArguments,
      instantiator_type_arguments);
  data.SetAt(data_pos + kTestResult, test_result);
}


void SubtypeTestCache::GetCheck(
    intptr_t ix,
    intptr_t* instance_class_id,
    AbstractTypeArguments* instance_type_arguments,
    AbstractTypeArguments* instantiator_type_arguments,
    Bool* test_result) const {
  Array& data = Array::Handle(cache());
  intptr_t data_pos = ix * kTestEntryLength;
  Smi& instance_class_id_handle = Smi::Handle();
  instance_class_id_handle ^= data.At(data_pos + kInstanceClassId);
  *instance_class_id = instance_class_id_handle.Value();
  *instance_type_arguments ^= data.At(data_pos + kInstanceTypeArguments);
  *instantiator_type_arguments ^=
      data.At(data_pos + kInstantiatorTypeArguments);
  *test_result ^= data.At(data_pos + kTestResult);
}


const char* SubtypeTestCache::ToCString() const {
  return "SubtypeTestCache";
}


const char* Error::ToErrorCString() const {
  UNREACHABLE();
  return "Internal Error";
}


const char* Error::ToCString() const {
  // Error is an abstract class.  We should never reach here.
  UNREACHABLE();
  return "Error";
}


RawApiError* ApiError::New() {
  ASSERT(Object::api_error_class() != Class::null());
  RawObject* raw = Object::Allocate(ApiError::kClassId,
                                    ApiError::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawApiError*>(raw);
}


RawApiError* ApiError::New(const String& message, Heap::Space space) {
  ASSERT(Object::api_error_class() != Class::null());
  ApiError& result = ApiError::Handle();
  {
    RawObject* raw = Object::Allocate(ApiError::kClassId,
                                      ApiError::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_message(message);
  return result.raw();
}


void ApiError::set_message(const String& message) const {
  StorePointer(&raw_ptr()->message_, message.raw());
}


const char* ApiError::ToErrorCString() const {
  const String& msg_str = String::Handle(message());
  return msg_str.ToCString();
}


const char* ApiError::ToCString() const {
  return "ApiError";
}


RawLanguageError* LanguageError::New() {
  ASSERT(Object::language_error_class() != Class::null());
  RawObject* raw = Object::Allocate(LanguageError::kClassId,
                                    LanguageError::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawLanguageError*>(raw);
}


RawLanguageError* LanguageError::New(const String& message, Heap::Space space) {
  ASSERT(Object::language_error_class() != Class::null());
  LanguageError& result = LanguageError::Handle();
  {
    RawObject* raw = Object::Allocate(LanguageError::kClassId,
                                      LanguageError::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_message(message);
  return result.raw();
}


void LanguageError::set_message(const String& message) const {
  StorePointer(&raw_ptr()->message_, message.raw());
}


const char* LanguageError::ToErrorCString() const {
  const String& msg_str = String::Handle(message());
  return msg_str.ToCString();
}


const char* LanguageError::ToCString() const {
  return "LanguageError";
}


RawUnhandledException* UnhandledException::New(const Instance& exception,
                                               const Instance& stacktrace,
                                               Heap::Space space) {
  ASSERT(Object::unhandled_exception_class() != Class::null());
  UnhandledException& result = UnhandledException::Handle();
  {
    RawObject* raw = Object::Allocate(UnhandledException::kClassId,
                                      UnhandledException::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_exception(exception);
  result.set_stacktrace(stacktrace);
  return result.raw();
}


void UnhandledException::set_exception(const Instance& exception) const {
  StorePointer(&raw_ptr()->exception_, exception.raw());
}


void UnhandledException::set_stacktrace(const Instance& stacktrace) const {
  StorePointer(&raw_ptr()->stacktrace_, stacktrace.raw());
}


const char* UnhandledException::ToErrorCString() const {
  Isolate* isolate = Isolate::Current();
  HANDLESCOPE(isolate);
  Object& strtmp = Object::Handle();

  const Instance& exc = Instance::Handle(exception());
  strtmp = DartLibraryCalls::ToString(exc);
  const char* exc_str =
      "<Received error while converting exception to string>";
  if (!strtmp.IsError()) {
    exc_str = strtmp.ToCString();
  }
  const Instance& stack = Instance::Handle(stacktrace());
  strtmp = DartLibraryCalls::ToString(stack);
  const char* stack_str =
      "<Received error while converting stack trace to string>";
  if (!strtmp.IsError()) {
    stack_str = strtmp.ToCString();
  }

  const char* format = "Unhandled exception:\n%s\n%s";
  int len = (strlen(exc_str) + strlen(stack_str) + strlen(format)
             - 4    // Two '%s'
             + 1);  // '\0'
  char* chars = isolate->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, format, exc_str, stack_str);
  return chars;
}


const char* UnhandledException::ToCString() const {
  return "UnhandledException";
}


RawUnwindError* UnwindError::New(const String& message, Heap::Space space) {
  ASSERT(Object::unwind_error_class() != Class::null());
  UnwindError& result = UnwindError::Handle();
  {
    RawObject* raw = Object::Allocate(UnwindError::kClassId,
                                      UnwindError::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_message(message);
  return result.raw();
}


void UnwindError::set_message(const String& message) const {
  StorePointer(&raw_ptr()->message_, message.raw());
}


const char* UnwindError::ToErrorCString() const {
  const String& msg_str = String::Handle(message());
  return msg_str.ToCString();
}


const char* UnwindError::ToCString() const {
  return "UnwindError";
}


bool Instance::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    return true;  // "===".
  }

  if (other.IsNull() || (this->clazz() != other.clazz())) {
    return false;
  }

  {
    NoGCScope no_gc;
    // Raw bits compare.
    const intptr_t instance_size = Class::Handle(this->clazz()).instance_size();
    ASSERT(instance_size != 0);
    uword this_addr = reinterpret_cast<uword>(this->raw_ptr());
    uword other_addr = reinterpret_cast<uword>(other.raw_ptr());
    for (intptr_t offset = sizeof(RawObject);
         offset < instance_size;
         offset += kWordSize) {
      if ((*reinterpret_cast<RawObject**>(this_addr + offset)) !=
          (*reinterpret_cast<RawObject**>(other_addr + offset))) {
        return false;
      }
    }
  }
  return true;
}


RawInstance* Instance::Canonicalize() const {
  ASSERT(!IsNull());
  if (this->IsCanonical()) {
    return this->raw();
  }
  Instance& result = Instance::Handle();
  const Class& cls = Class::Handle(this->clazz());
  Array& constants = Array::Handle(cls.constants());
  const intptr_t constants_len = constants.Length();
  // Linear search to see whether this value is already present in the
  // list of canonicalized constants.
  intptr_t index = 0;
  while (index < constants_len) {
    result ^= constants.At(index);
    if (result.IsNull()) {
      break;
    }
    if (this->Equals(result)) {
      return result.raw();
    }
    index++;
  }
  // The value needs to be added to the list. Grow the list if
  // it is full.
  result ^= this->raw();
  if (result.IsNew()) {
    // Create a canonical object in old space.
    result ^= Object::Clone(result, Heap::kOld);
  }
  ASSERT(result.IsOld());
  cls.InsertCanonicalConstant(index, result);
  result.SetCanonical();
  return result.raw();
}


RawType* Instance::GetType() const {
  if (IsNull()) {
    return Type::NullType();
  }
  const Class& cls = Class::Handle(clazz());
  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
  if (cls.HasTypeArguments()) {
    type_arguments = GetTypeArguments();
  }
  const Type& type = Type::Handle(
      Type::New(cls, type_arguments, Scanner::kDummyTokenIndex));
  type.set_is_finalized_instantiated();
  return type.raw();
}


RawAbstractTypeArguments* Instance::GetTypeArguments() const {
  const Class& cls = Class::Handle(clazz());
  intptr_t field_offset = cls.type_arguments_instance_field_offset();
  ASSERT(field_offset != Class::kNoTypeArguments);
  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
  type_arguments ^= *FieldAddrAtOffset(field_offset);
  return type_arguments.raw();
}


void Instance::SetTypeArguments(const AbstractTypeArguments& value) const {
  const Class& cls = Class::Handle(clazz());
  intptr_t field_offset = cls.type_arguments_instance_field_offset();
  ASSERT(field_offset != Class::kNoTypeArguments);
  SetFieldAtOffset(field_offset, value);
}


bool Instance::IsInstanceOf(const AbstractType& other,
                            const AbstractTypeArguments& other_instantiator,
                            Error* malformed_error) const {
  ASSERT(other.IsFinalized());
  ASSERT(!other.IsDynamicType());
  ASSERT(!other.IsMalformed());
  const Class& cls = Class::Handle(clazz());
  if (cls.IsNullClass()) {
    if (!IsNull()) {
      // We can only encounter Object::sentinel() or
      // Object::transition_sentinel() if type checks were not eliminated at
      // compile time. Both sentinels are instances of the Null class, but they
      // are not the Object::null() instance.
      ASSERT((raw() == Object::transition_sentinel()) ||
             (raw() == Object::sentinel()));
      ASSERT(!FLAG_eliminate_type_checks);
      return true;  // We are doing an instance of test as part of a type check.
    }
    // The null instance can be returned from a void function.
    if (other.IsVoidType()) {
      return true;
    }
    // Otherwise, null is only an instance of Object and of dynamic.
    // It is not necessary to fully instantiate the other type for this test.
    Class& other_class = Class::Handle();
    if (other.IsTypeParameter()) {
      if (other_instantiator.IsNull()) {
        return true;  // Other type is uninstantiated, i.e. dynamic.
      }
      const TypeParameter& other_type_param = TypeParameter::Cast(other);
      const AbstractType& instantiated_other = AbstractType::Handle(
          other_instantiator.TypeAt(other_type_param.index()));
      ASSERT(instantiated_other.IsInstantiated());
      other_class = instantiated_other.type_class();
    } else {
      other_class = other.type_class();
    }
    return other_class.IsObjectClass() || other_class.IsDynamicClass();
  }
  if (other.IsVoidType()) {
    return false;
  }
  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
  const intptr_t num_type_arguments = cls.NumTypeArguments();
  if (num_type_arguments > 0) {
    type_arguments = GetTypeArguments();
    if (!type_arguments.IsNull() && !type_arguments.IsCanonical()) {
      type_arguments = type_arguments.Canonicalize();
      SetTypeArguments(type_arguments);
    }
    // Verify that the number of type arguments in the instance matches the
    // number of type arguments expected by the instance class.
    // A discrepancy is allowed for closures, which borrow the type argument
    // vector of their instantiator, which may be of a super class of the class
    // defining the closure. Truncating the vector to the correct length on
    // instantiation is unnecessary. The vector may therefore be longer.
    ASSERT(type_arguments.IsNull() ||
           (type_arguments.Length() == num_type_arguments) ||
           (cls.IsSignatureClass() &&
            (type_arguments.Length() > num_type_arguments)));
  }
  Class& other_class = Class::Handle();
  AbstractTypeArguments& other_type_arguments = AbstractTypeArguments::Handle();
  // In case 'other' is not instantiated, we could simply call
  // other.InstantiateFrom(other_instantiator), however, we can save the
  // allocation of a new AbstractType by inlining the code.
  if (other.IsTypeParameter()) {
    if (other_instantiator.IsNull()) {
      // An uninstantiated type parameter is equivalent to dynamic.
      return true;
    }
    const TypeParameter& other_type_param = TypeParameter::Cast(other);
    AbstractType& instantiated_other = AbstractType::Handle(
        other_instantiator.TypeAt(other_type_param.index()));
    if (instantiated_other.IsDynamicType() ||
        instantiated_other.IsTypeParameter()) {
      return true;
    }
    other_class = instantiated_other.type_class();
    other_type_arguments = instantiated_other.arguments();
  } else {
    other_class = other.type_class();
    other_type_arguments = other.arguments();
    if (!other_type_arguments.IsNull() &&
        !other_type_arguments.IsInstantiated()) {
      other_type_arguments =
          other_type_arguments.InstantiateFrom(other_instantiator);
    }
  }
  return cls.IsSubtypeOf(type_arguments, other_class, other_type_arguments,
                         malformed_error);
}


void Instance::SetNativeField(int index, intptr_t value) const {
  ASSERT(IsValidNativeIndex(index));
  Object& native_fields = Object::Handle(*NativeFieldsAddr());
  if (native_fields.IsNull()) {
    // Allocate backing storage for the native fields.
    const Class& cls = Class::Handle(clazz());
    int num_native_fields = cls.num_native_fields();
    native_fields = IntPtrArray::New(num_native_fields);
    StorePointer(NativeFieldsAddr(), native_fields.raw());
  }
  IntPtrArray::Cast(native_fields).SetAt(index, value);
}


bool Instance::IsClosure() const {
  const Class& cls = Class::Handle(clazz());
  return cls.IsSignatureClass();
}


RawInstance* Instance::New(const Class& cls, Heap::Space space) {
  Instance& result = Instance::Handle();
  {
    intptr_t instance_size = cls.instance_size();
    ASSERT(instance_size > 0);
    RawObject* raw = Object::Allocate(cls.id(), instance_size, space);
    NoGCScope no_gc;
    result ^= raw;
  }
  return result.raw();
}


bool Instance::IsValidFieldOffset(int offset) const {
  const Class& cls = Class::Handle(clazz());
  return (offset >= 0 && offset <= (cls.instance_size() - kWordSize));
}


const char* Instance::ToCString() const {
  if (IsNull()) {
    return "null";
  } else if (raw() == Object::sentinel()) {
    return "sentinel";
  } else if (raw() == Object::transition_sentinel()) {
    return "transition_sentinel";
  } else if (Isolate::Current()->no_gc_scope_depth() > 0) {
    // Can occur when running disassembler.
    return "Instance";
  } else {
    if (IsClosure()) {
      return Closure::ToCString(*this);
    }
    const char* kFormat = "Instance of '%s'";
    const Class& cls = Class::Handle(clazz());
    AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle();
    const intptr_t num_type_arguments = cls.NumTypeArguments();
    if (num_type_arguments > 0) {
      type_arguments = GetTypeArguments();
    }
    const Type& type =
        Type::Handle(Type::New(cls, type_arguments, Scanner::kDummyTokenIndex));
    const String& type_name = String::Handle(type.Name());
    // Calculate the size of the string.
    intptr_t len = OS::SNPrint(NULL, 0, kFormat, type_name.ToCString()) + 1;
    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
    OS::SNPrint(chars, len, kFormat, type_name.ToCString());
    return chars;
  }
}


bool AbstractType::IsResolved() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractType::HasResolvedTypeClass() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


RawClass* AbstractType::type_class() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return Class::null();
}


RawUnresolvedClass* AbstractType::unresolved_class() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return UnresolvedClass::null();
}


RawAbstractTypeArguments* AbstractType::arguments() const  {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return NULL;
}


intptr_t AbstractType::token_pos() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return -1;
}


bool AbstractType::IsInstantiated() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractType::IsFinalized() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractType::IsBeingFinalized() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractType::IsMalformed() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


RawError* AbstractType::malformed_error() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return Error::null();
}


void AbstractType::set_malformed_error(const Error& value) const {
  // AbstractType is an abstract class.
  UNREACHABLE();
}


bool AbstractType::Equals(const Instance& other) const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


bool AbstractType::IsIdentical(const AbstractType& other,
                               bool check_type_parameter_bound) const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return false;
}


RawAbstractType* AbstractType::InstantiateFrom(
    const AbstractTypeArguments& instantiator_type_arguments) const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return NULL;
}


RawAbstractType* AbstractType::Canonicalize() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return NULL;
}


RawString* AbstractType::BuildName(NameVisibility name_visibility) const {
  if (IsTypeParameter()) {
    return TypeParameter::Cast(*this).name();
  }
  // If the type is still being finalized, we may be reporting an error about
  // a malformed type, so proceed with caution.
  const AbstractTypeArguments& args =
      AbstractTypeArguments::Handle(arguments());
  const intptr_t num_args = args.IsNull() ? 0 : args.Length();
  String& class_name = String::Handle();
  intptr_t first_type_param_index;
  intptr_t num_type_params;  // Number of type parameters to print.
  if (HasResolvedTypeClass()) {
    const Class& cls = Class::Handle(type_class());
    num_type_params = cls.NumTypeParameters();  // Do not print the full vector.
    if (name_visibility == kInternalName) {
      class_name = cls.Name();
    } else {
      ASSERT(name_visibility == kUserVisibleName);
      // Map internal types to their corresponding public interfaces.
      class_name = cls.UserVisibleName();
    }
    if (num_type_params > num_args) {
      first_type_param_index = 0;
      if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
        // Most probably a malformed type. Do not fill up with "dynamic",
        // but use actual vector.
        num_type_params = num_args;
      } else {
        ASSERT(num_args == 0);  // Type is raw.
        // No need to fill up with "dynamic".
        num_type_params = 0;
      }
    } else {
      first_type_param_index = num_args - num_type_params;
    }
    if (cls.IsSignatureClass()) {
      // We may be reporting an error about a malformed function type. In that
      // case, avoid instantiating the signature, since it may lead to cycles.
      if (!IsFinalized() || IsBeingFinalized() || IsMalformed()) {
        return class_name.raw();
      }
      // In order to avoid cycles, print the name of a typedef (non-canonical
      // signature class) as a regular, possibly parameterized, class.
      if (cls.IsCanonicalSignatureClass()) {
        const Function& signature_function = Function::Handle(
            cls.signature_function());
        // Signature classes have no super type.
        ASSERT(first_type_param_index == 0);
        return signature_function.InstantiatedSignatureFrom(args,
                                                            name_visibility);
      }
    }
  } else {
    const UnresolvedClass& cls = UnresolvedClass::Handle(unresolved_class());
    class_name = cls.Name();
    num_type_params = num_args;
    first_type_param_index = 0;
  }
  String& type_name = String::Handle();
  if (num_type_params == 0) {
    type_name = class_name.raw();
  } else {
    const String& args_name = String::Handle(
        args.SubvectorName(first_type_param_index,
                           num_type_params,
                           name_visibility));
    type_name = String::Concat(class_name, args_name);
  }
  // The name is only used for type checking and debugging purposes.
  // Unless profiling data shows otherwise, it is not worth caching the name in
  // the type.
  return Symbols::New(type_name);
}


RawString* AbstractType::ClassName() const {
  if (HasResolvedTypeClass()) {
    return Class::Handle(type_class()).Name();
  } else {
    return UnresolvedClass::Handle(unresolved_class()).Name();
  }
}


bool AbstractType::IsBoolType() const {
  return HasResolvedTypeClass() &&
      (type_class() == Type::Handle(Type::BoolType()).type_class());
}


bool AbstractType::IsIntType() const {
  return HasResolvedTypeClass() &&
      (type_class() == Type::Handle(Type::IntType()).type_class());
}


bool AbstractType::IsDoubleType() const {
  return HasResolvedTypeClass() &&
      (type_class() == Type::Handle(Type::Double()).type_class());
}


bool AbstractType::IsNumberType() const {
  return HasResolvedTypeClass() &&
      (type_class() == Type::Handle(Type::Number()).type_class());
}


bool AbstractType::IsStringType() const {
  return HasResolvedTypeClass() &&
      (type_class() == Type::Handle(Type::StringType()).type_class());
}


bool AbstractType::IsFunctionType() const {
  return HasResolvedTypeClass() &&
      (type_class() == Type::Handle(Type::Function()).type_class());
}


bool AbstractType::TypeTest(TypeTestKind test_kind,
                            const AbstractType& other,
                            Error* malformed_error) const {
  ASSERT(IsFinalized());
  ASSERT(other.IsFinalized());
  // In case the type checked in a type test is malformed, the code generator
  // may compile a throw instead of a run time call performing the type check.
  // However, in checked mode, a function type may include malformed result type
  // and/or malformed parameter types, which will then be encountered here at
  // run time.
  if (IsMalformed()) {
    ASSERT(FLAG_enable_type_checks);
    if ((malformed_error != NULL) && malformed_error->IsNull()) {
      *malformed_error = this->malformed_error();
    }
    return false;
  }
  if (other.IsMalformed()) {
    ASSERT(FLAG_enable_type_checks);
    if ((malformed_error != NULL) && malformed_error->IsNull()) {
      *malformed_error = other.malformed_error();
    }
    return false;
  }
  // AbstractType parameters cannot be handled by Class::TypeTest().
  // When comparing two uninstantiated function types, one returning type
  // parameter K, the other returning type parameter V, we cannot assume that K
  // is a subtype of V, or vice versa. We only return true if K == V, i.e. if
  // they have the same index (both are finalized, so their indices are
  // comparable).
  // The same rule applies When checking the upper bound of a still
  // uninstantiated type at compile time. Returning false will defer the test
  // to run time. But there are cases where it can be decided at compile time.
  // For example, with class A<K, V extends K>, new A<T, T> called from within
  // a class B<T> will never require a run time bounds check, even it T is
  // uninstantiated at compile time.
  if (IsTypeParameter()) {
    const TypeParameter& type_param = TypeParameter::Cast(*this);
    if (other.IsTypeParameter()) {
      const TypeParameter& other_type_param = TypeParameter::Cast(other);
      return type_param.index() == other_type_param.index();
    } else if (FLAG_enable_type_checks) {
      // In checked mode, if the upper bound of this type is more specific than
      // the other type, then this type is more specific than the other type.
      const AbstractType& type_param_bound =
          AbstractType::Handle(type_param.bound());
      if (type_param_bound.IsMoreSpecificThan(other, malformed_error)) {
        return true;
      }
    }
    return false;
  }
  if (other.IsTypeParameter()) {
    return false;
  }
  const Class& cls = Class::Handle(type_class());
  return cls.TypeTest(test_kind,
                      AbstractTypeArguments::Handle(arguments()),
                      Class::Handle(other.type_class()),
                      AbstractTypeArguments::Handle(other.arguments()),
                      malformed_error);
}


const char* AbstractType::ToCString() const {
  // AbstractType is an abstract class.
  UNREACHABLE();
  return "AbstractType";
}


RawType* Type::NullType() {
  return Isolate::Current()->object_store()->null_type();
}


RawType* Type::DynamicType() {
  return Isolate::Current()->object_store()->dynamic_type();
}


RawType* Type::VoidType() {
  return Isolate::Current()->object_store()->void_type();
}


RawType* Type::ObjectType() {
  return Isolate::Current()->object_store()->object_type();
}


RawType* Type::BoolType() {
  return Isolate::Current()->object_store()->bool_type();
}


RawType* Type::IntType() {
  return Isolate::Current()->object_store()->int_type();
}


RawType* Type::SmiType() {
  return Isolate::Current()->object_store()->smi_type();
}


RawType* Type::MintType() {
  return Isolate::Current()->object_store()->mint_type();
}


RawType* Type::Double() {
  return Isolate::Current()->object_store()->double_type();
}


RawType* Type::Number() {
  return Isolate::Current()->object_store()->number_type();
}


RawType* Type::StringType() {
  return Isolate::Current()->object_store()->string_type();
}


RawType* Type::ArrayType() {
  return Isolate::Current()->object_store()->array_type();
}


RawType* Type::Function() {
  return Isolate::Current()->object_store()->function_type();
}


RawType* Type::NewNonParameterizedType(const Class& type_class) {
  ASSERT(!type_class.HasTypeArguments());
  const TypeArguments& no_type_arguments = TypeArguments::Handle();
  Type& type = Type::Handle();
  type ^= Type::New(Object::Handle(type_class.raw()),
                    no_type_arguments,
                    Scanner::kDummyTokenIndex);
  type.set_is_finalized_instantiated();
  type ^= type.Canonicalize();
  return type.raw();
}


void Type::set_is_finalized_instantiated() const {
  ASSERT(!IsFinalized());
  set_type_state(RawType::kFinalizedInstantiated);
}


void Type::set_is_finalized_uninstantiated() const {
  ASSERT(!IsFinalized());
  set_type_state(RawType::kFinalizedUninstantiated);
}


void Type::set_is_being_finalized() const {
  ASSERT(!IsFinalized() && !IsBeingFinalized());
  set_type_state(RawType::kBeingFinalized);
}


bool Type::IsMalformed() const {
  return raw_ptr()->malformed_error_ != Error::null();
}


void Type::set_malformed_error(const Error& value) const {
  StorePointer(&raw_ptr()->malformed_error_, value.raw());
}


RawError* Type::malformed_error() const {
  ASSERT(IsMalformed());
  return raw_ptr()->malformed_error_;
}


bool Type::IsResolved() const {
  if (IsFinalized()) {
    return true;
  }
  if (!HasResolvedTypeClass()) {
    return false;
  }
  const AbstractTypeArguments& args =
      AbstractTypeArguments::Handle(arguments());
  return args.IsNull() || args.IsResolved();
}


bool Type::HasResolvedTypeClass() const {
  const Object& type_class = Object::Handle(raw_ptr()->type_class_);
  return !type_class.IsNull() && type_class.IsClass();
}


RawClass* Type::type_class() const {
  ASSERT(HasResolvedTypeClass());
  Class& type_class = Class::Handle();
  type_class ^= raw_ptr()->type_class_;
  return type_class.raw();
}


RawUnresolvedClass* Type::unresolved_class() const {
  ASSERT(!HasResolvedTypeClass());
  UnresolvedClass& unresolved_class = UnresolvedClass::Handle();
  unresolved_class ^= raw_ptr()->type_class_;
  ASSERT(!unresolved_class.IsNull());
  return unresolved_class.raw();
}


RawString* Type::TypeClassName() const {
  if (HasResolvedTypeClass()) {
    const Class& cls = Class::Handle(type_class());
    return cls.Name();
  } else {
    const UnresolvedClass& cls = UnresolvedClass::Handle(unresolved_class());
    return cls.Name();
  }
}


RawAbstractTypeArguments* Type::arguments() const {
  return raw_ptr()->arguments_;
}


bool Type::IsInstantiated() const {
  if (raw_ptr()->type_state_ == RawType::kFinalizedInstantiated) {
    return true;
  }
  if (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated) {
    return false;
  }
  const AbstractTypeArguments& args =
      AbstractTypeArguments::Handle(arguments());
  return args.IsNull() || args.IsInstantiated();
}


RawAbstractType* Type::InstantiateFrom(
    const AbstractTypeArguments& instantiator_type_arguments) const {
  ASSERT(IsFinalized());
  ASSERT(!IsInstantiated());
  AbstractTypeArguments& type_arguments =
      AbstractTypeArguments::Handle(arguments());
  type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments);
  const Class& cls = Class::Handle(type_class());
  ASSERT(cls.is_finalized());
  Type& instantiated_type = Type::Handle(
      Type::New(cls, type_arguments, token_pos()));
  ASSERT(type_arguments.IsNull() ||
         (type_arguments.Length() == cls.NumTypeArguments()));
  instantiated_type.set_is_finalized_instantiated();
  return instantiated_type.raw();
}


bool Type::Equals(const Instance& other) const {
  if (raw() == other.raw()) {
    return true;
  }
  if (!other.IsType()) {
    return false;
  }
  const AbstractType& other_type = AbstractType::Cast(other);
  ASSERT(IsFinalized() && other_type.IsFinalized());
  if (IsMalformed() || other_type.IsMalformed()) {
    return false;
  }
  if (type_class() != other_type.type_class()) {
    return false;
  }
  return AbstractTypeArguments::AreEqual(
      AbstractTypeArguments::Handle(arguments()),
      AbstractTypeArguments::Handle(other_type.arguments()));
}


bool Type::IsIdentical(const AbstractType& other,
                       bool check_type_parameter_bounds) const {
  if (raw() == other.raw()) {
    return true;
  }
  if (!other.IsType()) {
    return false;
  }
  // Both type classes may not be resolved yet.
  String& name = String::Handle(TypeClassName());
  String& other_name = String::Handle(Type::Cast(other).TypeClassName());
  if (!name.Equals(other_name)) {
    return false;
  }
  return AbstractTypeArguments::AreIdentical(
      AbstractTypeArguments::Handle(arguments()),
      AbstractTypeArguments::Handle(other.arguments()),
      false);  // Bounds are only checked at the top level.
}


RawAbstractType* Type::Canonicalize() const {
  ASSERT(IsFinalized());
  if (IsCanonical() || IsMalformed()) {
    ASSERT(IsMalformed() || AbstractTypeArguments::Handle(arguments()).IsOld());
    return this->raw();
  }
  const Class& cls = Class::Handle(type_class());
  Array& canonical_types = Array::Handle(cls.canonical_types());
  if (canonical_types.IsNull()) {
    // Types defined in the VM isolate are canonicalized via the object store.
    return this->raw();
  }
  const intptr_t canonical_types_len = canonical_types.Length();
  // Linear search to see whether this type is already present in the
  // list of canonicalized types.
  // TODO(asiva): Try to re-factor this lookup code to make sharing
  // easy between the 4 versions of this loop.
  Type& type = Type::Handle();
  intptr_t index = 0;
  while (index < canonical_types_len) {
    type ^= canonical_types.At(index);
    if (type.IsNull()) {
      break;
    }
    if (!type.IsFinalized()) {
      ASSERT((index == 0) && cls.IsSignatureClass());
      index++;
      continue;
    }
    if (this->Equals(type)) {
      return type.raw();
    }
    index++;
  }
  // Canonicalize the type arguments.
  AbstractTypeArguments& type_args = AbstractTypeArguments::Handle(arguments());
  type_args = type_args.Canonicalize();
  set_arguments(type_args);
  // The type needs to be added to the list. Grow the list if it is full.
  if (index == canonical_types_len) {
    const intptr_t kLengthIncrement = 2;  // Raw and parameterized.
    const intptr_t new_length = canonical_types.Length() + kLengthIncrement;
    const Array& new_canonical_types =
        Array::Handle(Array::Grow(canonical_types, new_length, Heap::kOld));
    cls.set_canonical_types(new_canonical_types);
    new_canonical_types.SetAt(index, *this);
  } else {
    canonical_types.SetAt(index, *this);
  }
  ASSERT(IsOld());
  SetCanonical();
  return this->raw();
}


void Type::set_type_class(const Object& value) const {
  ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
  StorePointer(&raw_ptr()->type_class_, value.raw());
}


void Type::set_arguments(const AbstractTypeArguments& value) const {
  StorePointer(&raw_ptr()->arguments_, value.raw());
}


RawType* Type::New(Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->type_class() != Class::null());
  RawObject* raw = Object::Allocate(Type::kClassId,
                                    Type::InstanceSize(),
                                    space);
  return reinterpret_cast<RawType*>(raw);
}


RawType* Type::New(const Object& clazz,
                   const AbstractTypeArguments& arguments,
                   intptr_t token_pos,
                   Heap::Space space) {
  const Type& result = Type::Handle(Type::New(space));
  result.set_type_class(clazz);
  result.set_arguments(arguments);
  result.set_token_pos(token_pos);
  result.raw_ptr()->type_state_ = RawType::kAllocated;
  return result.raw();
}


void Type::set_token_pos(intptr_t token_pos) const {
  ASSERT(token_pos >= 0);
  raw_ptr()->token_pos_ = token_pos;
}


void Type::set_type_state(int8_t state) const {
  ASSERT((state == RawType::kAllocated) ||
         (state == RawType::kBeingFinalized) ||
         (state == RawType::kFinalizedInstantiated) ||
         (state == RawType::kFinalizedUninstantiated));
  raw_ptr()->type_state_ = state;
}


const char* Type::ToCString() const {
  if (IsResolved()) {
    const AbstractTypeArguments& type_arguments =
        AbstractTypeArguments::Handle(arguments());
    const char* class_name;
    if (HasResolvedTypeClass()) {
      class_name = String::Handle(
          Class::Handle(type_class()).Name()).ToCString();
    } else {
      class_name = UnresolvedClass::Handle(unresolved_class()).ToCString();
    }
    if (type_arguments.IsNull()) {
      const char* format = "Type: class '%s'";
      intptr_t len = OS::SNPrint(NULL, 0, format, class_name) + 1;
      char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
      OS::SNPrint(chars, len, format, class_name);
      return chars;
    } else {
      const char* format = "Type: class '%s', args:[%s]";
      const char* args_cstr =
          AbstractTypeArguments::Handle(arguments()).ToCString();
      intptr_t len = OS::SNPrint(NULL, 0, format, class_name, args_cstr) + 1;
      char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
      OS::SNPrint(chars, len, format, class_name, args_cstr);
      return chars;
    }
  } else {
    return "Unresolved Type";
  }
}


void TypeParameter::set_is_finalized() const {
  ASSERT(!IsFinalized());
  set_type_state(RawTypeParameter::kFinalizedUninstantiated);
}


bool TypeParameter::Equals(const Instance& other) const {
  if (raw() == other.raw()) {
    return true;
  }
  if (!other.IsTypeParameter()) {
    return false;
  }
  const TypeParameter& other_type_param = TypeParameter::Cast(other);
  if (IsFinalized() != other_type_param.IsFinalized()) {
    return false;
  }
  if (parameterized_class() != other_type_param.parameterized_class()) {
    return false;
  }
  if (index() != other_type_param.index()) {
    return false;
  }
  const String& type_param_name = String::Handle(name());
  const String& other_type_param_name = String::Handle(other_type_param.name());
  return type_param_name.Equals(other_type_param_name);
}


bool TypeParameter::IsIdentical(const AbstractType& other,
                                bool check_type_parameter_bound) const {
  if (raw() == other.raw()) {
    return true;
  }
  if (!other.IsTypeParameter()) {
    return false;
  }
  const TypeParameter& other_type_param = TypeParameter::Cast(other);
  // IsIdentical may be called on type parameters belonging to different
  // classes, e.g. to an interface and to its default factory class.
  // Therefore, both type parameters may have different parameterized classes
  // and different indices. Compare the type parameter names only, and their
  // bounds if requested.
  String& type_param_name = String::Handle(name());
  String& other_type_param_name = String::Handle(other_type_param.name());
  if (!type_param_name.Equals(other_type_param_name)) {
    return false;
  }
  if (check_type_parameter_bound) {
    AbstractType& this_bound = AbstractType::Handle(bound());
    AbstractType& other_bound = AbstractType::Handle(other_type_param.bound());
    // Bounds are only checked at the top level.
    const bool check_type_parameter_bounds = false;
    if (!this_bound.IsIdentical(other_bound, check_type_parameter_bounds)) {
      return false;
    }
  }
  return true;
}


void TypeParameter::set_parameterized_class(const Class& value) const {
  // Set value may be null.
  StorePointer(&raw_ptr()->parameterized_class_, value.raw());
}


void TypeParameter::set_index(intptr_t value) const {
  ASSERT(value >= 0);
  raw_ptr()->index_ = value;
}


void TypeParameter::set_name(const String& value) const {
  ASSERT(value.IsSymbol());
  StorePointer(&raw_ptr()->name_, value.raw());
}


void TypeParameter::set_bound(const AbstractType& value) const {
  StorePointer(&raw_ptr()->bound_, value.raw());
}

RawAbstractType* TypeParameter::InstantiateFrom(
    const AbstractTypeArguments& instantiator_type_arguments) const {
  ASSERT(IsFinalized());
  if (instantiator_type_arguments.IsNull()) {
    return Type::DynamicType();
  }
  return instantiator_type_arguments.TypeAt(index());
}


RawTypeParameter* TypeParameter::New() {
  ASSERT(Isolate::Current()->object_store()->type_parameter_class() !=
         Class::null());
  RawObject* raw = Object::Allocate(TypeParameter::kClassId,
                                    TypeParameter::InstanceSize(),
                                    Heap::kOld);
  return reinterpret_cast<RawTypeParameter*>(raw);
}


RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
                                     intptr_t index,
                                     const String& name,
                                     const AbstractType& bound,
                                     intptr_t token_pos) {
  const TypeParameter& result = TypeParameter::Handle(TypeParameter::New());
  result.set_parameterized_class(parameterized_class);
  result.set_index(index);
  result.set_name(name);
  result.set_bound(bound);
  result.set_token_pos(token_pos);
  result.raw_ptr()->type_state_ = RawTypeParameter::kAllocated;
  return result.raw();
}


void TypeParameter::set_token_pos(intptr_t token_pos) const {
  ASSERT(token_pos >= 0);
  raw_ptr()->token_pos_ = token_pos;
}


void TypeParameter::set_type_state(int8_t state) const {
  ASSERT((state == RawTypeParameter::kAllocated) ||
         (state == RawTypeParameter::kBeingFinalized) ||
         (state == RawTypeParameter::kFinalizedUninstantiated));
  raw_ptr()->type_state_ = state;
}


const char* TypeParameter::ToCString() const {
  const char* format = "TypeParameter: name %s; index: %d; class: %s";
  const char* name_cstr = String::Handle(Name()).ToCString();
  const Class& cls = Class::Handle(parameterized_class());
  const char* cls_cstr =
      cls.IsNull() ? " null" : String::Handle(cls.Name()).ToCString();
  intptr_t len = OS::SNPrint(NULL, 0, format, name_cstr, index(), cls_cstr) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, format, name_cstr, index(), cls_cstr);
  return chars;
}


const char* Number::ToCString() const {
  // Number is an interface. No instances of Number should exist.
  UNREACHABLE();
  return "Number";
}


const char* Integer::ToCString() const {
  // Integer is an interface. No instances of Integer should exist.
  UNREACHABLE();
  return "Integer";
}


RawInteger* Integer::New(const String& str, Heap::Space space) {
  // We are not supposed to have integers represented as two byte or
  // four byte strings.
  ASSERT(str.IsOneByteString());
  int64_t value;
  if (!OS::StringToInt64(str.ToCString(), &value)) {
    const Bigint& big = Bigint::Handle(Bigint::New(str, space));
    ASSERT(!BigintOperations::FitsIntoSmi(big));
    ASSERT(!BigintOperations::FitsIntoMint(big));
    return big.raw();
  }
  return Integer::New(value, space);
}


RawInteger* Integer::New(int64_t value, Heap::Space space) {
  if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) {
    return Smi::New(value);
  }
  return Mint::New(value, space);
}


double Integer::AsDoubleValue() const {
  UNIMPLEMENTED();
  return 0.0;
}


int64_t Integer::AsInt64Value() const {
  UNIMPLEMENTED();
  return 0;
}


int Integer::CompareWith(const Integer& other) const {
  UNIMPLEMENTED();
  return 0;
}


RawInteger* Integer::AsInteger() const {
  if (IsSmi()) return raw();
  if (IsMint()) {
    Mint& mint = Mint::Handle();
    mint ^= raw();
    if (Smi::IsValid64(mint.value())) {
      return Smi::New(mint.value());
    } else {
      return raw();
    }
  }
  ASSERT(IsBigint());
  Bigint& big_value = Bigint::Handle();
  big_value ^= raw();
  if (BigintOperations::FitsIntoSmi(big_value)) {
    return BigintOperations::ToSmi(big_value);
  } else if (BigintOperations::FitsIntoMint(big_value)) {
    return Mint::New(BigintOperations::ToMint(big_value));
  } else {
    return big_value.raw();
  }
}


RawInteger* Integer::ArithmeticOp(Token::Kind operation,
                                  const Integer& other) const {
  // In 32-bit mode, the result of any operation between two Smis will fit in a
  // 32-bit signed result, except the product of two Smis, which will be 64-bit.
  // In 64-bit mode, the result of any operation between two Smis will fit in a
  // 64-bit signed result, except the product of two Smis (unless the Smis are
  // 32-bit or less).
  if (IsSmi() && other.IsSmi()) {
    Smi& left_smi = Smi::Handle();
    Smi& right_smi = Smi::Handle();
    left_smi ^= raw();
    right_smi ^= other.raw();
    const intptr_t left_value = left_smi.Value();
    const intptr_t right_value = right_smi.Value();
    switch (operation) {
      case Token::kADD:
        return Integer::New(left_value + right_value);
      case Token::kSUB:
        return Integer::New(left_value - right_value);
      case Token::kMUL: {
        if (Smi::kBits < 32) {
          // In 32-bit mode, the product of two Smis fits in a 64-bit result.
          return Integer::New(static_cast<int64_t>(left_value) *
                              static_cast<int64_t>(right_value));
        } else {
          // In 64-bit mode, the product of two 32-bit signed integers fits in a
          // 64-bit result.
          ASSERT(sizeof(intptr_t) == sizeof(int64_t));
          if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) {
            return Integer::New(left_value * right_value);
          }
        }
        // Perform a Bigint multiplication below.
        break;
      }
      case Token::kTRUNCDIV:
        return Integer::New(left_value / right_value);
      case Token::kMOD: {
        const intptr_t remainder = left_value % right_value;
        if (remainder < 0) {
          if (right_value < 0) {
            return Integer::New(remainder - right_value);
          } else {
            return Integer::New(remainder + right_value);
          }
        }
        return Integer::New(remainder);
      }
      default:
        UNIMPLEMENTED();
    }
  }
  // In 32-bit mode, the result of any operation between two 63-bit signed
  // integers (or 32-bit for multiplication) will fit in a 64-bit signed result.
  // In 64-bit mode, 63-bit signed integers are Smis, already processed above.
  if ((Smi::kBits < 32) && !IsBigint() && !other.IsBigint()) {
    const int64_t left_value = AsInt64Value();
    if (Utils::IsInt(63, left_value)) {
      const int64_t right_value = other.AsInt64Value();
      if (Utils::IsInt(63, right_value)) {
        switch (operation) {
        case Token::kADD:
          return Integer::New(left_value + right_value);
        case Token::kSUB:
          return Integer::New(left_value - right_value);
        case Token::kMUL: {
          if (Utils::IsInt(32, left_value) && Utils::IsInt(32, right_value)) {
            return Integer::New(left_value * right_value);
          }
          // Perform a Bigint multiplication below.
          break;
        }
        case Token::kTRUNCDIV:
          return Integer::New(left_value / right_value);
        case Token::kMOD: {
          const int64_t remainder = left_value % right_value;
          if (remainder < 0) {
            if (right_value < 0) {
              return Integer::New(remainder - right_value);
            } else {
              return Integer::New(remainder + right_value);
            }
          }
          return Integer::New(remainder);
        }
        default:
          UNIMPLEMENTED();
        }
      }
    }
  }
  const Bigint& left_big = Bigint::Handle(AsBigint());
  const Bigint& right_big = Bigint::Handle(other.AsBigint());
  const Bigint& result =
      Bigint::Handle(left_big.ArithmeticOp(operation, right_big));
  return Integer::Handle(result.AsInteger()).raw();
}


static bool Are64bitOperands(const Integer& op1, const Integer& op2) {
  return !op1.IsBigint() && !op2.IsBigint();
}


RawInteger* Integer::BitOp(Token::Kind kind, const Integer& other) const {
  if (IsSmi() && other.IsSmi()) {
    Smi& op1 = Smi::Handle();
    Smi& op2 = Smi::Handle();
    op1 ^= raw();
    op2 ^= other.raw();
    intptr_t result = 0;
    switch (kind) {
      case Token::kBIT_AND:
        result = op1.Value() & op2.Value();
        break;
      case Token::kBIT_OR:
        result = op1.Value() | op2.Value();
        break;
      case Token::kBIT_XOR:
        result = op1.Value() ^ op2.Value();
        break;
      default:
        UNIMPLEMENTED();
    }
    ASSERT(Smi::IsValid(result));
    return Smi::New(result);
  } else if (Are64bitOperands(*this, other)) {
    int64_t a = AsInt64Value();
    int64_t b = other.AsInt64Value();
    switch (kind) {
      case Token::kBIT_AND:
        return Integer::New(a & b);
      case Token::kBIT_OR:
        return Integer::New(a | b);
      case Token::kBIT_XOR:
        return Integer::New(a ^ b);
      default:
        UNIMPLEMENTED();
    }
  } else {
    Bigint& op1 = Bigint::Handle(AsBigint());
    Bigint& op2 = Bigint::Handle(other.AsBigint());
    switch (kind) {
      case Token::kBIT_AND:
        return BigintOperations::BitAnd(op1, op2);
      case Token::kBIT_OR:
        return BigintOperations::BitOr(op1, op2);
      case Token::kBIT_XOR:
        return BigintOperations::BitXor(op1, op2);
      default:
        UNIMPLEMENTED();
    }
  }
  return Integer::null();
}


// TODO(srdjan): Clarify handling of negative right operand in a shift op.
RawInteger* Smi::ShiftOp(Token::Kind kind, const Smi& other) const {
  intptr_t result = 0;
  const intptr_t left_value = Value();
  const intptr_t right_value = other.Value();
  ASSERT(right_value >= 0);
  switch (kind) {
    case Token::kSHL: {
      if ((left_value == 0) || (right_value == 0)) {
        return raw();
      }
      { // Check for overflow.
        int cnt = Utils::HighestBit(left_value);
        if ((cnt + right_value) >= Smi::kBits) {
          if ((cnt + right_value) >= Mint::kBits) {
            return BigintOperations::ShiftLeft(
                Bigint::Handle(AsBigint()), right_value);
          } else {
            int64_t left_64 = left_value;
            return Integer::New(left_64 << right_value);
          }
        }
      }
      result = left_value << right_value;
      break;
    }
    case Token::kSHR: {
      const intptr_t shift_amount =
          (right_value >= kBitsPerWord) ? (kBitsPerWord - 1) : right_value;
      result = left_value >> shift_amount;
      break;
    }
    default:
      UNIMPLEMENTED();
  }
  ASSERT(Smi::IsValid(result));
  return Smi::New(result);
}


bool Smi::Equals(const Instance& other) const {
  if (other.IsNull() || !other.IsSmi()) {
    return false;
  }
  return (this->Value() == Smi::Cast(other).Value());
}


double Smi::AsDoubleValue() const {
  return static_cast<double>(this->Value());
}


int64_t Smi::AsInt64Value() const {
  return this->Value();
}


static bool FitsIntoSmi(const Integer& integer) {
  if (integer.IsSmi()) {
    return true;
  }
  if (integer.IsMint()) {
    int64_t mint_value = integer.AsInt64Value();
    return Smi::IsValid64(mint_value);
  }
  if (integer.IsBigint()) {
    return BigintOperations::FitsIntoSmi(Bigint::Cast(integer));
  }
  UNREACHABLE();
  return false;
}


int Smi::CompareWith(const Integer& other) const {
  if (other.IsSmi()) {
    const Smi& other_smi = Smi::Cast(other);
    if (this->Value() < other_smi.Value()) {
      return -1;
    } else if (this->Value() > other_smi.Value()) {
      return 1;
    } else {
      return 0;
    }
  }
  ASSERT(!FitsIntoSmi(other));
  if (other.IsMint() || other.IsBigint()) {
    if (this->IsNegative() == other.IsNegative()) {
      return this->IsNegative() ? 1 : -1;
    }
    return this->IsNegative() ? -1 : 1;
  }
  UNREACHABLE();
  return 0;
}


const char* Smi::ToCString() const {
  const char* kFormat = "%ld";
  // Calculate the size of the string.
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, Value()) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, Value());
  return chars;
}


RawClass* Smi::Class() {
  return Isolate::Current()->object_store()->smi_class();
}


void Mint::set_value(int64_t value) const {
  raw_ptr()->value_ = value;
}


RawMint* Mint::New(int64_t val, Heap::Space space) {
  // Do not allocate a Mint if Smi would do.
  ASSERT(!Smi::IsValid64(val));
  ASSERT(Isolate::Current()->object_store()->mint_class() != Class::null());
  Mint& result = Mint::Handle();
  {
    RawObject* raw = Object::Allocate(Mint::kClassId,
                                      Mint::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_value(val);
  return result.raw();
}


RawMint* Mint::NewCanonical(int64_t value) {
  // Do not allocate a Mint if Smi would do.
  ASSERT(!Smi::IsValid64(value));
  const Class& cls =
      Class::Handle(Isolate::Current()->object_store()->mint_class());
  const Array& constants = Array::Handle(cls.constants());
  const intptr_t constants_len = constants.Length();
  // Linear search to see whether this value is already present in the
  // list of canonicalized constants.
  Mint& canonical_value = Mint::Handle();
  intptr_t index = 0;
  while (index < constants_len) {
    canonical_value ^= constants.At(index);
    if (canonical_value.IsNull()) {
      break;
    }
    if (canonical_value.value() == value) {
      return canonical_value.raw();
    }
    index++;
  }
  // The value needs to be added to the constants list. Grow the list if
  // it is full.
  canonical_value = Mint::New(value, Heap::kOld);
  cls.InsertCanonicalConstant(index, canonical_value);
  canonical_value.SetCanonical();
  return canonical_value.raw();
}


bool Mint::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    // Both handles point to the same raw instance.
    return true;
  }
  if (!other.IsMint() || other.IsNull()) {
    return false;
  }
  return value() == Mint::Cast(other).value();
}


double Mint::AsDoubleValue() const {
  return static_cast<double>(this->value());
}


int64_t Mint::AsInt64Value() const {
  return this->value();
}


int Mint::CompareWith(const Integer& other) const {
  ASSERT(!FitsIntoSmi(*this));
  if (other.IsMint() || other.IsSmi()) {
    int64_t a = AsInt64Value();
    int64_t b = other.AsInt64Value();
    if (a < b) {
      return -1;
    } else if (a > b) {
      return 1;
    } else {
      return 0;
    }
  }
  if (other.IsBigint()) {
    ASSERT(!BigintOperations::FitsIntoMint(Bigint::Cast(other)));
    if (this->IsNegative() == other.IsNegative()) {
      return this->IsNegative() ? 1 : -1;
    }
    return this->IsNegative() ? -1 : 1;
  }
  UNREACHABLE();
  return 0;
}


const char* Mint::ToCString() const {
  const char* kFormat = "%lld";
  // Calculate the size of the string.
  intptr_t len = OS::SNPrint(NULL, 0, kFormat, value()) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, kFormat, value());
  return chars;
}


void Double::set_value(double value) const {
  raw_ptr()->value_ = value;
}


bool Double::EqualsToDouble(double value) const {
  intptr_t value_offset = Double::value_offset();
  void* this_addr = reinterpret_cast<void*>(
      reinterpret_cast<uword>(this->raw_ptr()) + value_offset);
  void* other_addr = reinterpret_cast<void*>(&value);
  return (memcmp(this_addr, other_addr, sizeof(value)) == 0);
}


bool Double::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    return true;  // "===".
  }
  if (other.IsNull() || !other.IsDouble()) {
    return false;
  }
  return EqualsToDouble(Double::Cast(other).value());
}


RawDouble* Double::New(double d, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->double_class() != Class::null());
  Double& result = Double::Handle();
  {
    RawObject* raw = Object::Allocate(Double::kClassId,
                                      Double::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_value(d);
  return result.raw();
}


static bool IsWhiteSpace(char ch) {
  return ch == '\0' || ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t';
}


static bool StringToDouble(const String& str, double* double_value) {
  ASSERT(double_value != NULL);
  // TODO(regis): For now, we use strtod to convert a string to double.
  const char* nptr = str.ToCString();
  char* endptr = NULL;
  *double_value = strtod(nptr, &endptr);
  // We do not treat overflow or underflow as an error and therefore do not
  // check errno for ERANGE.
  if (!IsWhiteSpace(*endptr)) {
    return false;
  }
  return true;
}


RawDouble* Double::New(const String& str, Heap::Space space) {
  double double_value;
  if (!StringToDouble(str, &double_value)) {
    return Double::Handle().raw();
  }
  return New(double_value, space);
}


RawDouble* Double::NewCanonical(double value) {
  const Class& cls =
      Class::Handle(Isolate::Current()->object_store()->double_class());
  const Array& constants = Array::Handle(cls.constants());
  const intptr_t constants_len = constants.Length();
  // Linear search to see whether this value is already present in the
  // list of canonicalized constants.
  Double& canonical_value = Double::Handle();
  intptr_t index = 0;
  while (index < constants_len) {
    canonical_value ^= constants.At(index);
    if (canonical_value.IsNull()) {
      break;
    }
    if (canonical_value.EqualsToDouble(value)) {
      return canonical_value.raw();
    }
    index++;
  }
  // The value needs to be added to the constants list. Grow the list if
  // it is full.
  canonical_value = Double::New(value, Heap::kOld);
  cls.InsertCanonicalConstant(index, canonical_value);
  canonical_value.SetCanonical();
  return canonical_value.raw();
}


RawDouble* Double::NewCanonical(const String& str) {
  double double_value;
  if (!StringToDouble(str, &double_value)) {
    return Double::Handle().raw();
  }
  return NewCanonical(double_value);
}


const char* Double::ToCString() const {
  if (isnan(value())) {
    return "NaN";
  }
  if (isinf(value())) {
    return value() < 0 ? "-Infinity" : "Infinity";
  }
  const int kBufferSize = 128;
  char* buffer = Isolate::Current()->current_zone()->Alloc<char>(kBufferSize);
  buffer[kBufferSize - 1] = '\0';
  DoubleToCString(value(), buffer, kBufferSize);
  return buffer;
}


RawBigint* Integer::AsBigint() const {
  ASSERT(!IsNull());
  if (IsSmi()) {
    Smi& smi = Smi::Handle();
    smi ^= raw();
    return BigintOperations::NewFromSmi(smi);
  } else if (IsMint()) {
    Mint& mint = Mint::Handle();
    mint ^= raw();
    return BigintOperations::NewFromInt64(mint.value());
  } else {
    ASSERT(IsBigint());
    Bigint& big = Bigint::Handle();
    big ^= raw();
    ASSERT(!BigintOperations::FitsIntoSmi(big));
    return big.raw();
  }
}


RawBigint* Bigint::ArithmeticOp(Token::Kind operation,
                                const Bigint& other) const {
  switch (operation) {
    case Token::kADD:
      return BigintOperations::Add(*this, other);
    case Token::kSUB:
      return BigintOperations::Subtract(*this, other);
    case Token::kMUL:
      return BigintOperations::Multiply(*this, other);
    case Token::kTRUNCDIV:
      return BigintOperations::Divide(*this, other);
    case Token::kMOD:
      return BigintOperations::Modulo(*this, other);
    default:
      UNIMPLEMENTED();
      return Bigint::null();
  }
}


bool Bigint::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    // Both handles point to the same raw instance.
    return true;
  }

  if (!other.IsBigint() || other.IsNull()) {
    return false;
  }

  const Bigint& other_bgi = Bigint::Cast(other);

  intptr_t len = this->Length();
  if (len != other_bgi.Length()) {
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->GetChunkAt(i) != other_bgi.GetChunkAt(i)) {
      return false;
    }
  }
  return true;
}


RawBigint* Bigint::New(const String& str, Heap::Space space) {
  return BigintOperations::NewFromCString(str.ToCString(), space);
}


RawBigint* Bigint::New(int64_t value, Heap::Space space) {
  return BigintOperations::NewFromInt64(value, space);
}


double Bigint::AsDoubleValue() const {
  return Double::Handle(BigintOperations::ToDouble(*this)).value();
}


int64_t Bigint::AsInt64Value() const {
  if (!BigintOperations::FitsIntoMint(*this)) {
    UNREACHABLE();
  }
  return BigintOperations::ToMint(*this);
}


// For positive values: Smi < Mint < Bigint.
int Bigint::CompareWith(const Integer& other) const {
  ASSERT(!FitsIntoSmi(*this));
  ASSERT(!BigintOperations::FitsIntoMint(*this));
  if (other.IsBigint()) {
    return BigintOperations::Compare(*this, Bigint::Cast(other));
  }
  if (this->IsNegative() == other.IsNegative()) {
    return this->IsNegative() ? -1 : 1;
  }
  return this->IsNegative() ? -1 : 1;
}


RawBigint* Bigint::Allocate(intptr_t length, Heap::Space space) {
  if (length < 0 || length > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Bigint::Allocate: invalid length %"Pd"\n", length);
  }
  ASSERT(Isolate::Current()->object_store()->bigint_class() != Class::null());
  Bigint& result = Bigint::Handle();
  {
    RawObject* raw = Object::Allocate(Bigint::kClassId,
                                      Bigint::InstanceSize(length),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.raw_ptr()->allocated_length_ = length;  // Chunk length allocated.
    result.raw_ptr()->signed_length_ = length;  // Chunk length in use.
  }
  return result.raw();
}


static uword BigintAllocator(intptr_t size) {
  Zone* zone = Isolate::Current()->current_zone();
  return zone->AllocUnsafe(size);
}


const char* Bigint::ToCString() const {
  return BigintOperations::ToDecimalCString(*this, &BigintAllocator);
}


class StringHasher : ValueObject {
 public:
  StringHasher() : hash_(0) {}
  void Add(int32_t ch) {
    hash_ += ch;
    hash_ += hash_ << 10;
    hash_ ^= hash_ >> 6;
  }
  // Return a non-zero hash of at most 'bits' bits.
  intptr_t Finalize(int bits) {
    ASSERT(1 <= bits && bits <= (kBitsPerWord - 1));
    hash_ += hash_ << 3;
    hash_ ^= hash_ >> 11;
    hash_ += hash_ << 15;
    hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
    ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32));
    return hash_ == 0 ? 1 : hash_;
  }
 private:
  uint32_t hash_;
};


intptr_t String::Hash() const {
  intptr_t result = Smi::Value(raw_ptr()->hash_);
  if (result != 0) {
    return result;
  }
  result = String::Hash(*this, 0, this->Length());
  this->SetHash(result);
  return result;
}


intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
  ASSERT(begin_index >= 0);
  ASSERT(len >= 0);
  ASSERT((begin_index + len) <= str.Length());
  StringHasher hasher;
  for (intptr_t i = 0; i < len; i++) {
    hasher.Add(str.CharAt(begin_index + i));
  }
  return hasher.Finalize(String::kHashBits);
}


template<typename T>
static intptr_t HashImpl(const T* characters, intptr_t len) {
  ASSERT(len >= 0);
  StringHasher hasher;
  for (intptr_t i = 0; i < len; i++) {
    hasher.Add(characters[i]);
  }
  return hasher.Finalize(String::kHashBits);
}


intptr_t String::Hash(const uint8_t* characters, intptr_t len) {
  return HashImpl(characters, len);
}


intptr_t String::Hash(const uint16_t* characters, intptr_t len) {
  return HashImpl(characters, len);
}


intptr_t String::Hash(const int32_t* characters, intptr_t len) {
  return HashImpl(characters, len);
}


int32_t String::CharAt(intptr_t index) const {
  intptr_t class_id = raw()->GetClassId();
  ASSERT(RawObject::IsStringClassId(class_id));
  NoGCScope no_gc;
  if (class_id == kOneByteStringCid) {
      return *OneByteString::CharAddr(*this, index);
  }
  if (class_id == kTwoByteStringCid) {
      return *TwoByteString::CharAddr(*this, index);
  }
  if (class_id == kExternalOneByteStringCid) {
      return *ExternalOneByteString::CharAddr(*this, index);
  }
  ASSERT(class_id == kExternalTwoByteStringCid);
  return *ExternalTwoByteString::CharAddr(*this, index);
}


intptr_t String::CharSize() const {
  intptr_t class_id = raw()->GetClassId();
  if (class_id == kOneByteStringCid || class_id == kExternalOneByteStringCid) {
    return kOneByteChar;
  }
  ASSERT(class_id == kTwoByteStringCid ||
         class_id == kExternalTwoByteStringCid);
  return kTwoByteChar;
}


void* String::GetPeer() const {
  intptr_t class_id = raw()->GetClassId();
  if (class_id == kExternalOneByteStringCid) {
    return ExternalOneByteString::GetPeer(*this);
  }
  ASSERT(class_id == kExternalTwoByteStringCid);
  return ExternalTwoByteString::GetPeer(*this);
}


bool String::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    // Both handles point to the same raw instance.
    return true;
  }

  if (!other.IsString() || other.IsNull()) {
    return false;
  }

  const String& other_string = String::Cast(other);
  if (this->HasHash() && other_string.HasHash() &&
      (this->Hash() != other_string.Hash())) {
    return false;  // Both sides have a hash code and it does not match.
  }
  return Equals(other_string, 0, other_string.Length());
}


bool String::Equals(const char* cstr) const {
  ASSERT(cstr != NULL);
  CodePointIterator it(*this);
  intptr_t len = strlen(cstr);
  while (it.Next()) {
    if (*cstr == '\0') {
      // Lengths don't match.
      return false;
    }
    int32_t ch;
    intptr_t consumed = Utf8::Decode(reinterpret_cast<const uint8_t*>(cstr),
                                     len,
                                     &ch);
    if (consumed == 0 || it.Current() != ch) {
      return false;
    }
    cstr += consumed;
    len -= consumed;
  }
  return *cstr == '\0';
}


bool String::Equals(const uint8_t* latin1_array, intptr_t len) const {
  if (len != this->Length()) {
    // Lengths don't match.
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->CharAt(i) != latin1_array[i]) {
      return false;
    }
  }
  return true;
}


bool String::Equals(const uint16_t* utf16_array, intptr_t len) const {
  if (len != this->Length()) {
    // Lengths don't match.
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->CharAt(i) != utf16_array[i]) {
      return false;
    }
  }
  return true;
}


bool String::Equals(const int32_t* utf32_array, intptr_t len) const {
  CodePointIterator it(*this);
  intptr_t i = 0;
  while (it.Next()) {
    if (it.Current() != static_cast<int32_t>(utf32_array[i])) {
      return false;
    }
    ++i;
  }
  if (i != len) {
    return false;
  }
  return true;
}


intptr_t String::CompareTo(const String& other) const {
  const intptr_t this_len = this->Length();
  const intptr_t other_len = other.IsNull() ? 0 : other.Length();
  const intptr_t len = (this_len < other_len) ? this_len : other_len;
  for (intptr_t i = 0; i < len; i++) {
    int32_t this_code_point = this->CharAt(i);
    int32_t other_code_point = other.CharAt(i);
    if (this_code_point < other_code_point) {
      return -1;
    }
    if (this_code_point > other_code_point) {
      return 1;
    }
  }
  if (this_len < other_len) return -1;
  if (this_len > other_len) return 1;
  return 0;
}


bool String::StartsWith(const String& other) const {
  if (other.IsNull() || (other.Length() > this->Length())) {
    return false;
  }
  intptr_t slen = other.Length();
  for (int i = 0; i < slen; i++) {
    if (this->CharAt(i) != other.CharAt(i)) {
      return false;
    }
  }
  return true;
}


RawInstance* String::Canonicalize() const {
  if (IsCanonical()) {
    return this->raw();
  }
  return Symbols::New(*this);
}


RawString* String::New(const char* str, Heap::Space space) {
  ASSERT(str != NULL);
  intptr_t array_len = strlen(str);
  const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(str);
  return String::New(utf8_array, array_len, space);
}


RawString* String::New(const uint8_t* utf8_array,
                       intptr_t array_len,
                       Heap::Space space) {
  Utf8::Type type;
  intptr_t len = Utf8::CodePointCount(utf8_array, array_len, &type);
  if (type == Utf8::kLatin1) {
    const String& strobj = String::Handle(OneByteString::New(len, space));
    if (len > 0) {
      NoGCScope no_gc;
      Utf8::DecodeToLatin1(utf8_array, array_len,
                           OneByteString::CharAddr(strobj, 0), len);
    }
    return strobj.raw();
  }
  ASSERT((type == Utf8::kBMP) || (type == Utf8::kSupplementary));
  const String& strobj = String::Handle(TwoByteString::New(len, space));
  NoGCScope no_gc;
  Utf8::DecodeToUTF16(utf8_array, array_len,
                      TwoByteString::CharAddr(strobj, 0), len);
  return strobj.raw();
}


RawString* String::New(const uint16_t* utf16_array,
                       intptr_t array_len,
                       Heap::Space space) {
  bool is_one_byte_string = true;
  for (intptr_t i = 0; i < array_len; ++i) {
    if (utf16_array[i] > 0xFF) {
      is_one_byte_string = false;
      break;
    }
  }
  if (is_one_byte_string) {
    return OneByteString::New(utf16_array, array_len, space);
  }
  return TwoByteString::New(utf16_array, array_len, space);
}


RawString* String::New(const int32_t* utf32_array,
                       intptr_t array_len,
                       Heap::Space space) {
  bool is_one_byte_string = true;
  intptr_t utf16_len = array_len;
  for (intptr_t i = 0; i < array_len; ++i) {
    if (utf32_array[i] > 0xFF) {
      is_one_byte_string = false;
    }
    if (utf32_array[i] > 0xFFFF) {
      utf16_len += 1;
    }
  }
  if (is_one_byte_string) {
    return OneByteString::New(utf32_array, array_len, space);
  }
  return TwoByteString::New(utf16_len, utf32_array, array_len, space);
}


RawString* String::New(const String& str, Heap::Space space) {
  // Currently this just creates a copy of the string in the correct space.
  // Once we have external string support, this will also create a heap copy of
  // the string if necessary. Some optimizations are possible, such as not
  // copying internal strings into the same space.
  intptr_t len = str.Length();
  String& result = String::Handle();
  intptr_t char_size = str.CharSize();
  if (char_size == kOneByteChar) {
    result ^= OneByteString::New(len, space);
  } else {
    ASSERT(char_size == kTwoByteChar);
    result ^= TwoByteString::New(len, space);
  }
  String::Copy(result, 0, str, 0, len);
  return result.raw();
}


RawString* String::NewExternal(const uint8_t* characters,
                               intptr_t len,
                               void* peer,
                               Dart_PeerFinalizer callback,
                               Heap::Space space) {
  return ExternalOneByteString::New(characters, len, peer, callback, space);
}


RawString* String::NewExternal(const uint16_t* characters,
                               intptr_t len,
                               void* peer,
                               Dart_PeerFinalizer callback,
                               Heap::Space space) {
  return ExternalTwoByteString::New(characters, len, peer, callback, space);
}


void String::Copy(const String& dst, intptr_t dst_offset,
                  const uint8_t* characters,
                  intptr_t len) {
  ASSERT(dst_offset >= 0);
  ASSERT(len >= 0);
  ASSERT(len <= (dst.Length() - dst_offset));
  if (dst.IsOneByteString()) {
    NoGCScope no_gc;
    if (len > 0) {
      memmove(OneByteString::CharAddr(dst, dst_offset),
              characters,
              len);
    }
  } else if (dst.IsTwoByteString()) {
    for (intptr_t i = 0; i < len; ++i) {
      *TwoByteString::CharAddr(dst, i + dst_offset) = characters[i];
    }
  }
}


void String::Copy(const String& dst, intptr_t dst_offset,
                  const uint16_t* utf16_array,
                  intptr_t array_len) {
  ASSERT(dst_offset >= 0);
  ASSERT(array_len >= 0);
  ASSERT(array_len <= (dst.Length() - dst_offset));
  if (dst.IsOneByteString()) {
    NoGCScope no_gc;
    for (intptr_t i = 0; i < array_len; ++i) {
      ASSERT(utf16_array[i] <= 0xFF);
      *OneByteString::CharAddr(dst, i + dst_offset) = utf16_array[i];
    }
  } else {
    ASSERT(dst.IsTwoByteString());
    NoGCScope no_gc;
    if (array_len > 0) {
      memmove(TwoByteString::CharAddr(dst, dst_offset),
              utf16_array,
              array_len * 2);
    }
  }
}


void String::Copy(const String& dst, intptr_t dst_offset,
                  const String& src, intptr_t src_offset,
                  intptr_t len) {
  ASSERT(dst_offset >= 0);
  ASSERT(src_offset >= 0);
  ASSERT(len >= 0);
  ASSERT(len <= (dst.Length() - dst_offset));
  ASSERT(len <= (src.Length() - src_offset));
  if (len > 0) {
    intptr_t char_size = src.CharSize();
    if (char_size == kOneByteChar) {
      if (src.IsOneByteString()) {
        NoGCScope no_gc;
        String::Copy(dst,
                     dst_offset,
                     OneByteString::CharAddr(src, src_offset),
                     len);
      } else {
        ASSERT(src.IsExternalOneByteString());
        NoGCScope no_gc;
        String::Copy(dst,
                     dst_offset,
                     ExternalOneByteString::CharAddr(src, src_offset),
                     len);
      }
    } else {
      ASSERT(char_size == kTwoByteChar);
      if (src.IsTwoByteString()) {
        NoGCScope no_gc;
        String::Copy(dst,
                     dst_offset,
                     TwoByteString::CharAddr(src, src_offset),
                     len);
      } else {
        ASSERT(src.IsExternalTwoByteString());
        NoGCScope no_gc;
        String::Copy(dst,
                     dst_offset,
                     ExternalTwoByteString::CharAddr(src, src_offset),
                     len);
      }
    }
  }
}


RawString* String::EscapeSpecialCharacters(const String& str, bool raw_str) {
  if (str.IsOneByteString()) {
    return OneByteString::EscapeSpecialCharacters(str, raw_str);
  }
  ASSERT(str.IsTwoByteString());
  return TwoByteString::EscapeSpecialCharacters(str, raw_str);
}


RawString* String::NewFormatted(const char* format, ...) {
  va_list args;
  va_start(args, format);
  RawString* result = NewFormattedV(format, args);
  NoGCScope no_gc;
  va_end(args);
  return result;
}


RawString* String::NewFormattedV(const char* format, va_list args) {
  va_list args_copy;
  va_copy(args_copy, args);
  intptr_t len = OS::VSNPrint(NULL, 0, format, args_copy);
  va_end(args_copy);

  Zone* zone = Isolate::Current()->current_zone();
  char* buffer = zone->Alloc<char>(len + 1);
  OS::VSNPrint(buffer, (len + 1), format, args);

  return String::New(buffer);
}


RawString* String::Concat(const String& str1,
                          const String& str2,
                          Heap::Space space) {
  ASSERT(!str1.IsNull() && !str2.IsNull());
  intptr_t char_size = Utils::Maximum(str1.CharSize(), str2.CharSize());
  if (char_size == kTwoByteChar) {
    return TwoByteString::Concat(str1, str2, space);
  }
  return OneByteString::Concat(str1, str2, space);
}


RawString* String::ConcatAll(const Array& strings,
                             Heap::Space space) {
  ASSERT(!strings.IsNull());
  intptr_t result_len = 0;
  intptr_t strings_len = strings.Length();
  String& str = String::Handle();
  intptr_t char_size = kOneByteChar;
  for (intptr_t i = 0; i < strings_len; i++) {
    str ^= strings.At(i);
    result_len += str.Length();
    char_size = Utils::Maximum(char_size, str.CharSize());
  }
  if (char_size == kOneByteChar) {
    return OneByteString::ConcatAll(strings, result_len, space);
  }
  ASSERT(char_size == kTwoByteChar);
  return TwoByteString::ConcatAll(strings, result_len, space);
}


RawString* String::SubString(const String& str,
                             intptr_t begin_index,
                             Heap::Space space) {
  ASSERT(!str.IsNull());
  if (begin_index >= str.Length()) {
    return String::null();
  }
  return String::SubString(str, begin_index, (str.Length() - begin_index));
}


RawString* String::SubString(const String& str,
                             intptr_t begin_index,
                             intptr_t length,
                             Heap::Space space) {
  ASSERT(!str.IsNull());
  ASSERT(begin_index >= 0);
  ASSERT(length >= 0);
  if (begin_index <= str.Length() && length == 0) {
    return Symbols::Empty();
  }
  if (begin_index > str.Length()) {
    return String::null();
  }
  String& result = String::Handle();
  bool is_one_byte_string = true;
  intptr_t char_size = str.CharSize();
  if (char_size == kTwoByteChar) {
    for (intptr_t i = begin_index; i < begin_index + length; ++i) {
      if (str.CharAt(i) > 0xFF) {
        is_one_byte_string = false;
        break;
      }
    }
  }
  if (is_one_byte_string) {
    result ^= OneByteString::New(length, space);
  } else {
    result ^= TwoByteString::New(length, space);
  }
  String::Copy(result, 0, str, begin_index, length);
  return result.raw();
}


const char* String::ToCString() const {
  intptr_t len = Utf8::Length(*this);
  Zone* zone = Isolate::Current()->current_zone();
  uint8_t* result = zone->Alloc<uint8_t>(len + 1);
  ToUTF8(result, len);
  result[len] = 0;
  return reinterpret_cast<const char*>(result);
}


void String::ToUTF8(uint8_t* utf8_array, intptr_t array_len) const {
  ASSERT(array_len >= Utf8::Length(*this));
  Utf8::Encode(*this, reinterpret_cast<char*>(utf8_array), array_len);
}


static void AddFinalizer(const Object& referent,
                         void* peer,
                         Dart_WeakPersistentHandleFinalizer callback) {
  ASSERT(callback != NULL);
  ApiState* state = Isolate::Current()->api_state();
  ASSERT(state != NULL);
  FinalizablePersistentHandle* weak_ref =
      state->weak_persistent_handles().AllocateHandle();
  weak_ref->set_raw(referent);
  weak_ref->set_peer(peer);
  weak_ref->set_callback(callback);
}


RawString* String::MakeExternal(void* array,
                                intptr_t length,
                                void* peer,
                                Dart_PeerFinalizer cback) const {
  ASSERT(array != NULL);
  intptr_t str_length = this->Length();
  ASSERT(length >= (str_length * this->CharSize()));
  intptr_t class_id = raw()->GetClassId();
  intptr_t used_size = 0;
  intptr_t original_size = 0;
  uword tags = 0;
  NoGCScope no_gc;

  if (class_id == kOneByteStringCid) {
    used_size = ExternalOneByteString::InstanceSize();
    original_size = OneByteString::InstanceSize(str_length);
    ASSERT(original_size >= used_size);

    // Copy the data into the external array.
    if (str_length > 0) {
      memmove(array, OneByteString::CharAddr(*this, 0), str_length);
    }

    // Update the class information of the object.
    const intptr_t class_id = kExternalOneByteStringCid;
    tags = RawObject::SizeTag::update(used_size, tags);
    tags = RawObject::ClassIdTag::update(class_id, tags);
    raw_ptr()->tags_ = tags;
    const String& result = String::Handle(this->raw());
    ExternalStringData<uint8_t>* ext_data = new ExternalStringData<uint8_t>(
        reinterpret_cast<const uint8_t*>(array), peer, cback);
    result.SetLength(str_length);
    result.SetHash(0);
    ExternalOneByteString::SetExternalData(result, ext_data);
    AddFinalizer(result, ext_data, ExternalOneByteString::Finalize);
  } else {
    ASSERT(class_id == kTwoByteStringCid);
    used_size = ExternalTwoByteString::InstanceSize();
    original_size = TwoByteString::InstanceSize(str_length);
    ASSERT(original_size >= used_size);

    // Copy the data into the external array.
    if (str_length > 0) {
      memmove(array,
              TwoByteString::CharAddr(*this, 0),
              (str_length * kTwoByteChar));
    }

    // Update the class information of the object.
    const intptr_t class_id = kExternalTwoByteStringCid;
    tags = RawObject::SizeTag::update(used_size, tags);
    tags = RawObject::ClassIdTag::update(class_id, tags);
    raw_ptr()->tags_ = tags;
    const String& result = String::Handle(this->raw());
    ExternalStringData<uint16_t>* ext_data = new ExternalStringData<uint16_t>(
        reinterpret_cast<const uint16_t*>(array), peer, cback);
    result.SetLength(str_length);
    result.SetHash(0);
    ExternalTwoByteString::SetExternalData(result, ext_data);
    AddFinalizer(result, ext_data, ExternalTwoByteString::Finalize);
  }

  // If there is any left over space fill it with either an Array object or
  // just a plain object (depending on the amount of left over space) so
  // that it can be traversed over successfully during garbage collection.
  Object::MakeUnusedSpaceTraversable(*this, original_size, used_size);

  return this->raw();
}


RawString* String::Transform(int32_t (*mapping)(int32_t ch),
                             const String& str,
                             Heap::Space space) {
  ASSERT(!str.IsNull());
  bool has_mapping = false;
  int32_t dst_max = 0;
  CodePointIterator it(str);
  while (it.Next()) {
    int32_t src = it.Current();
    int32_t dst = mapping(src);
    if (src != dst) {
      has_mapping = true;
    }
    dst_max = Utils::Maximum(dst_max, dst);
  }
  if (!has_mapping) {
    return str.raw();
  }
  if (dst_max <= 0xFF) {
    return OneByteString::Transform(mapping, str, space);
  }
  ASSERT(dst_max > 0xFF);
  return TwoByteString::Transform(mapping, str, space);
}


RawString* String::ToUpperCase(const String& str, Heap::Space space) {
  // TODO(cshapiro): create a fast-path for OneByteString instances.
  return Transform(CaseMapping::ToUpper, str, space);
}


RawString* String::ToLowerCase(const String& str, Heap::Space space) {
  // TODO(cshapiro): create a fast-path for OneByteString instances.
  return Transform(CaseMapping::ToLower, str, space);
}


bool String::CodePointIterator::Next() {
  ASSERT(index_ >= -1);
  ASSERT(index_ < str_.Length());
  int d = Utf16::Length(ch_);
  if (index_ == (str_.Length() - d)) {
    return false;
  }
  index_ += d;
  ch_ = str_.CharAt(index_);
  if (Utf16::IsLeadSurrogate(ch_) && (index_ != (str_.Length() - 1))) {
    int32_t ch2 = str_.CharAt(index_ + 1);
    if (Utf16::IsTrailSurrogate(ch2)) {
      ch_ = Utf16::Decode(ch_, ch2);
    }
  }
  return true;
}


RawOneByteString* OneByteString::EscapeSpecialCharacters(const String& str,
                                                         bool raw_str) {
  intptr_t len = str.Length();
  if (len > 0) {
    intptr_t num_escapes = 0;
    intptr_t index = 0;
    for (intptr_t i = 0; i < len; i++) {
      if (IsSpecialCharacter(*CharAddr(str, i)) ||
          (!raw_str && (*CharAddr(str, i) == '\\'))) {
        num_escapes += 1;
      }
    }
    const String& dststr = String::Handle(
        OneByteString::New(len + num_escapes, Heap::kNew));
    for (intptr_t i = 0; i < len; i++) {
      if (IsSpecialCharacter(*CharAddr(str, i))) {
        *(CharAddr(dststr, index)) = '\\';
        *(CharAddr(dststr, index + 1)) = SpecialCharacter(*CharAddr(str, i));
        index += 2;
      } else if (!raw_str && (*CharAddr(str, i) == '\\')) {
        *(CharAddr(dststr, index)) = '\\';
        *(CharAddr(dststr, index + 1)) = '\\';
        index += 2;
      } else {
        *(CharAddr(dststr, index)) = *CharAddr(str, i);
        index += 1;
      }
    }
    return OneByteString::raw(dststr);
  }
  return OneByteString::null();
}


// Check to see if 'str1' matches 'str2' as is or
// once the private key separator is stripped from str2.
//
// Things are made more complicated by the fact that constructors are
// added *after* the private suffix, so "foo@123.named" should match
// "foo.named".
//
// Also, the private suffix can occur more than once in the name, as in:
//
//    _ReceivePortImpl@6be832b._internal@6be832b
//
bool OneByteString::EqualsIgnoringPrivateKey(const String& str1,
                                             const String& str2) {
  ASSERT(str2.IsOneByteString());
  if (str1.raw() == str2.raw()) {
    return true;  // Both handles point to the same raw instance.
  }
  NoGCScope no_gc;
  intptr_t len = str1.Length();
  intptr_t str2_len = str2.Length();
  if (len == str2_len) {
    for (intptr_t i = 0; i < len; i++) {
      if (*CharAddr(str1, i) != *CharAddr(str2, i)) {
        return false;
      }
    }
    return true;
  }
  if (len < str2_len) {
    return false;  // No way they can match.
  }
  intptr_t pos = 0;
  intptr_t str2_pos = 0;
  while (pos < len) {
    int32_t ch = *CharAddr(str1, pos);
    pos++;

    if (ch == Scanner::kPrivateKeySeparator) {
      // Consume a private key separator.
      while ((pos < len) && (*CharAddr(str1, pos) != '.')) {
        pos++;
      }
      // Resume matching characters.
      continue;
    }
    if ((str2_pos == str2_len) || (ch != *CharAddr(str2, str2_pos))) {
      return false;
    }
    str2_pos++;
  }

  // We have reached the end of mangled_name string.
  ASSERT(pos == len);
  return (str2_pos == str2_len);
}


RawOneByteString* OneByteString::New(intptr_t len,
                                     Heap::Space space) {
  ASSERT(Isolate::Current() == Dart::vm_isolate() ||
         Isolate::Current()->object_store()->one_byte_string_class() !=
         Class::null());
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in OneByteString::New: invalid len %"Pd"\n", len);
  }
  String& result = String::Handle();
  {
    RawObject* raw = Object::Allocate(OneByteString::kClassId,
                                      OneByteString::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    result.SetHash(0);
  }
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::New(const uint8_t* characters,
                                     intptr_t len,
                                     Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(len, space));
  if (len > 0) {
    NoGCScope no_gc;
    memmove(CharAddr(result, 0), characters, len);
  }
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::New(const uint16_t* characters,
                                     intptr_t len,
                                     Heap::Space space) {
  const String& result =String::Handle(OneByteString::New(len, space));
  for (intptr_t i = 0; i < len; ++i) {
    ASSERT(characters[i] <= 0xFF);
    *CharAddr(result, i) = characters[i];
  }
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::New(const int32_t* characters,
                                     intptr_t len,
                                     Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(len, space));
  for (intptr_t i = 0; i < len; ++i) {
    ASSERT(characters[i] <= 0xFF);
    *CharAddr(result, i) = characters[i];
  }
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::New(const String& str,
                                     Heap::Space space) {
  intptr_t len = str.Length();
  const String& result = String::Handle(OneByteString::New(len, space));
  String::Copy(result, 0, str, 0, len);
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::Concat(const String& str1,
                                        const String& str2,
                                        Heap::Space space) {
  intptr_t len1 = str1.Length();
  intptr_t len2 = str2.Length();
  intptr_t len = len1 + len2;
  const String& result = String::Handle(OneByteString::New(len, space));
  String::Copy(result, 0, str1, 0, len1);
  String::Copy(result, len1, str2, 0, len2);
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::ConcatAll(const Array& strings,
                                           intptr_t len,
                                           Heap::Space space) {
  const String& result = String::Handle(OneByteString::New(len, space));
  String& str = String::Handle();
  intptr_t strings_len = strings.Length();
  intptr_t pos = 0;
  for (intptr_t i = 0; i < strings_len; i++) {
    str ^= strings.At(i);
    intptr_t str_len = str.Length();
    String::Copy(result, pos, str, 0, str_len);
    pos += str_len;
  }
  return OneByteString::raw(result);
}


RawOneByteString* OneByteString::Transform(int32_t (*mapping)(int32_t ch),
                                           const String& str,
                                           Heap::Space space) {
  ASSERT(!str.IsNull());
  intptr_t len = str.Length();
  const String& result = String::Handle(OneByteString::New(len, space));
  for (intptr_t i = 0; i < len; ++i) {
    int32_t ch = mapping(str.CharAt(i));
    ASSERT(ch >= 0 && ch <= 0xFF);
    *CharAddr(result, i) = ch;
  }
  return OneByteString::raw(result);
}


RawTwoByteString* TwoByteString::EscapeSpecialCharacters(const String& str,
                                                         bool raw_str) {
  intptr_t len = str.Length();
  if (len > 0) {
    intptr_t num_escapes = 0;
    intptr_t index = 0;
    for (intptr_t i = 0; i < len; i++) {
      if (IsSpecialCharacter(*CharAddr(str, i)) ||
          (!raw_str && (*CharAddr(str, i) == '\\'))) {
        num_escapes += 1;
      }
    }
    const String& dststr = String::Handle(
        TwoByteString::New(len + num_escapes, Heap::kNew));
    for (intptr_t i = 0; i < len; i++) {
      if (IsSpecialCharacter(*CharAddr(str, i))) {
        *(CharAddr(dststr, index)) = '\\';
        *(CharAddr(dststr, index + 1)) = SpecialCharacter(*CharAddr(str, i));
        index += 2;
      } else if (!raw_str && (*CharAddr(str, i) == '\\')) {
        *(CharAddr(dststr, index)) = '\\';
        *(CharAddr(dststr, index + 1)) = '\\';
        index += 2;
      } else {
        *(CharAddr(dststr, index)) = *CharAddr(str, i);
        index += 1;
      }
    }
    return TwoByteString::raw(dststr);
  }
  return TwoByteString::null();
}


RawTwoByteString* TwoByteString::New(intptr_t len,
                                     Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->two_byte_string_class());
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in TwoByteString::New: invalid len %"Pd"\n", len);
  }
  String& result = String::Handle();
  {
    RawObject* raw = Object::Allocate(TwoByteString::kClassId,
                                      TwoByteString::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    result.SetHash(0);
  }
  return TwoByteString::raw(result);
}


RawTwoByteString* TwoByteString::New(const uint16_t* utf16_array,
                                     intptr_t array_len,
                                     Heap::Space space) {
  ASSERT(array_len > 0);
  const String& result = String::Handle(TwoByteString::New(array_len, space));
  {
    NoGCScope no_gc;
    memmove(CharAddr(result, 0), utf16_array, (array_len * 2));
  }
  return TwoByteString::raw(result);
}


RawTwoByteString* TwoByteString::New(intptr_t utf16_len,
                                     const int32_t* utf32_array,
                                     intptr_t array_len,
                                     Heap::Space space) {
  ASSERT((array_len > 0) && (utf16_len >= array_len));
  const String& result = String::Handle(TwoByteString::New(utf16_len, space));
  {
    NoGCScope no_gc;
    intptr_t j = 0;
    for (intptr_t i = 0; i < array_len; ++i) {
      if (utf32_array[i] > 0xffff) {
        ASSERT(j < (utf16_len - 1));
        Utf16::Encode(utf32_array[i], CharAddr(result, j));
        j += 2;
      } else {
        ASSERT(j < utf16_len);
        *CharAddr(result, j) = utf32_array[i];
        j += 1;
      }
    }
  }
  return TwoByteString::raw(result);
}


RawTwoByteString* TwoByteString::New(const String& str,
                                     Heap::Space space) {
  intptr_t len = str.Length();
  const String& result = String::Handle(TwoByteString::New(len, space));
  String::Copy(result, 0, str, 0, len);
  return TwoByteString::raw(result);
}


RawTwoByteString* TwoByteString::Concat(const String& str1,
                                        const String& str2,
                                        Heap::Space space) {
  intptr_t len1 = str1.Length();
  intptr_t len2 = str2.Length();
  intptr_t len = len1 + len2;
  const String& result = String::Handle(TwoByteString::New(len, space));
  String::Copy(result, 0, str1, 0, len1);
  String::Copy(result, len1, str2, 0, len2);
  return TwoByteString::raw(result);
}


RawTwoByteString* TwoByteString::ConcatAll(const Array& strings,
                                           intptr_t len,
                                           Heap::Space space) {
  const String& result = String::Handle(TwoByteString::New(len, space));
  String& str = String::Handle();
  intptr_t strings_len = strings.Length();
  intptr_t pos = 0;
  for (intptr_t i = 0; i < strings_len; i++) {
    str ^= strings.At(i);
    intptr_t str_len = str.Length();
    String::Copy(result, pos, str, 0, str_len);
    pos += str_len;
  }
  return TwoByteString::raw(result);
}


RawTwoByteString* TwoByteString::Transform(int32_t (*mapping)(int32_t ch),
                                           const String& str,
                                           Heap::Space space) {
  ASSERT(!str.IsNull());
  intptr_t len = str.Length();
  const String& result = String::Handle(TwoByteString::New(len, space));
  String::CodePointIterator it(str);
  intptr_t i = 0;
  while (it.Next()) {
    int32_t src = it.Current();
    int32_t dst = mapping(src);
    ASSERT(dst >= 0 && dst <= 0x10FFFF);
    intptr_t len = Utf16::Length(dst);
    if (len == 1) {
      *CharAddr(result, i) = dst;
    } else {
      ASSERT(len == 2);
      Utf16::Encode(dst, CharAddr(result, i));
    }
    i += len;
  }
  return TwoByteString::raw(result);
}


RawExternalOneByteString* ExternalOneByteString::New(
    const uint8_t* data,
    intptr_t len,
    void* peer,
    Dart_PeerFinalizer callback,
    Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->
         external_one_byte_string_class() != Class::null());
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ExternalOneByteString::New: invalid len %"Pd"\n",
           len);
  }
  String& result = String::Handle();
  ExternalStringData<uint8_t>* external_data =
      new ExternalStringData<uint8_t>(data, peer, callback);
  {
    RawObject* raw = Object::Allocate(ExternalOneByteString::kClassId,
                                      ExternalOneByteString::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    result.SetHash(0);
    SetExternalData(result, external_data);
  }
  AddFinalizer(result, external_data, ExternalOneByteString::Finalize);
  return ExternalOneByteString::raw(result);
}


static void DeleteWeakPersistentHandle(Dart_Handle handle) {
  ApiState* state = Isolate::Current()->api_state();
  ASSERT(state != NULL);
  FinalizablePersistentHandle* weak_ref =
      reinterpret_cast<FinalizablePersistentHandle*>(handle);
  ASSERT(state->IsValidWeakPersistentHandle(handle));
  state->weak_persistent_handles().FreeHandle(weak_ref);
}


void ExternalOneByteString::Finalize(Dart_Handle handle, void* peer) {
  delete reinterpret_cast<ExternalStringData<uint8_t>*>(peer);
  DeleteWeakPersistentHandle(handle);
}


RawExternalTwoByteString* ExternalTwoByteString::New(
    const uint16_t* data,
    intptr_t len,
    void* peer,
    Dart_PeerFinalizer callback,
    Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_two_byte_string_class() !=
         Class::null());
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ExternalTwoByteString::New: invalid len %"Pd"\n",
           len);
  }
  String& result = String::Handle();
  ExternalStringData<uint16_t>* external_data =
      new ExternalStringData<uint16_t>(data, peer, callback);
  {
    RawObject* raw = Object::Allocate(ExternalTwoByteString::kClassId,
                                      ExternalTwoByteString::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    result.SetHash(0);
    SetExternalData(result, external_data);
  }
  AddFinalizer(result, external_data, ExternalTwoByteString::Finalize);
  return ExternalTwoByteString::raw(result);
}


void ExternalTwoByteString::Finalize(Dart_Handle handle, void* peer) {
  delete reinterpret_cast<ExternalStringData<uint16_t>*>(peer);
  DeleteWeakPersistentHandle(handle);
}


RawBool* Bool::True() {
  return Isolate::Current()->object_store()->true_value();
}


RawBool* Bool::False() {
  return Isolate::Current()->object_store()->false_value();
}


RawBool* Bool::New(bool value) {
  ASSERT(Isolate::Current()->object_store()->bool_class() != Class::null());
  Bool& result = Bool::Handle();
  {
    // Since the two boolean instances are singletons we allocate them straight
    // in the old generation.
    RawObject* raw = Object::Allocate(Bool::kClassId,
                                      Bool::InstanceSize(),
                                      Heap::kOld);
    NoGCScope no_gc;
    result ^= raw;
  }
  result.set_value(value);
  return result.raw();
}


const char* Bool::ToCString() const {
  return value() ? "true" : "false";
}


bool Array::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    // Both handles point to the same raw instance.
    return true;
  }

  if (!other.IsArray() || other.IsNull()) {
    return false;
  }

  // Must have the same type arguments.
  if (!AbstractTypeArguments::AreEqual(
      AbstractTypeArguments::Handle(GetTypeArguments()),
      AbstractTypeArguments::Handle(other.GetTypeArguments()))) {
    return false;
  }

  const Array& other_arr = Array::Cast(other);

  intptr_t len = this->Length();
  if (len != other_arr.Length()) {
    return false;
  }

  for (intptr_t i = 0; i < len; i++) {
    if (this->At(i) != other_arr.At(i)) {
      return false;
    }
  }
  return true;
}


RawArray* Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
  return New(kClassId, len, space);
}


RawArray* Array::New(intptr_t class_id, intptr_t len, Heap::Space space) {
  if (len < 0 || len > Array::kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in Array::New: invalid len %"Pd"\n", len);
  }
  Array& result = Array::Handle();
  {
    RawObject* raw = Object::Allocate(class_id,
                                      Array::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
  }
  return result.raw();
}


void Array::MakeImmutable() const {
  NoGCScope no_gc;
  uword tags = raw_ptr()->tags_;
  tags = RawObject::ClassIdTag::update(kImmutableArrayCid, tags);
  raw_ptr()->tags_ = tags;
}


const char* Array::ToCString() const {
  return "Array";
}


RawArray* Array::Grow(const Array& source, int new_length, Heap::Space space) {
  const Array& result = Array::Handle(Array::New(new_length, space));
  intptr_t len = 0;
  if (!source.IsNull()) {
    len = source.Length();
    result.SetTypeArguments(
        AbstractTypeArguments::Handle(source.GetTypeArguments()));
  }
  ASSERT(new_length >= len);  // Cannot copy 'source' into new array.
  ASSERT(new_length != len);  // Unnecessary copying of array.
  Object& obj = Object::Handle();
  for (int i = 0; i < len; i++) {
    obj = source.At(i);
    result.SetAt(i, obj);
  }
  return result.raw();
}


RawArray* Array::MakeArray(const GrowableObjectArray& growable_array) {
  intptr_t used_len = growable_array.Length();
  intptr_t capacity_len = growable_array.Capacity();
  Isolate* isolate = Isolate::Current();
  const Array& array = Array::Handle(isolate, growable_array.data());
  const Array& new_array = Array::Handle(isolate, Object::empty_array());
  intptr_t capacity_size = Array::InstanceSize(capacity_len);
  intptr_t used_size = Array::InstanceSize(used_len);
  NoGCScope no_gc;

  // Update the size in the header field and length of the array object.
  uword tags = array.raw_ptr()->tags_;
  ASSERT(kArrayCid == RawObject::ClassIdTag::decode(tags));
  tags = RawObject::SizeTag::update(used_size, tags);
  array.raw_ptr()->tags_ = tags;
  array.SetLength(used_len);

  // Null the GrowableObjectArray, we are removing it's backing array.
  growable_array.SetLength(0);
  growable_array.SetData(new_array);

  // If there is any left over space fill it with either an Array object or
  // just a plain object (depending on the amount of left over space) so
  // that it can be traversed over successfully during garbage collection.
  Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size);

  return array.raw();
}


RawImmutableArray* ImmutableArray::New(intptr_t len,
                                       Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->immutable_array_class() !=
         Class::null());
  return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space));
}


const char* ImmutableArray::ToCString() const {
  return "ImmutableArray";
}


void GrowableObjectArray::Add(const Object& value, Heap::Space space) const {
  ASSERT(!IsNull());
  Array& contents = Array::Handle(data());
  if (Length() == Capacity()) {
    // TODO(Issue 2500): Need a better growth strategy.
    intptr_t new_capacity = (Capacity() == 0) ? 4 : Capacity() * 2;
    if (new_capacity <= Capacity()) {
      // Use the preallocated out of memory exception to avoid calling
      // into dart code or allocating any code.
      const Instance& exception =
          Instance::Handle(Isolate::Current()->object_store()->out_of_memory());
      Exceptions::Throw(exception);
      UNREACHABLE();
    }
    Grow(new_capacity, space);
    contents = data();
  }
  ASSERT(Length() < Capacity());
  intptr_t index = Length();
  SetLength(index + 1);
  contents.SetAt(index, value);
}


void GrowableObjectArray::Grow(intptr_t new_capacity, Heap::Space space) const {
  ASSERT(new_capacity > Capacity());
  const Array& contents = Array::Handle(data());
  const Array& new_contents =
      Array::Handle(Array::Grow(contents, new_capacity, space));
  StorePointer(&(raw_ptr()->data_), new_contents.raw());
  ASSERT(AbstractTypeArguments::AreEqual(
      AbstractTypeArguments::Handle(new_contents.GetTypeArguments()),
      AbstractTypeArguments::Handle(raw_ptr()->type_arguments_)));
}


RawObject* GrowableObjectArray::RemoveLast() const {
  ASSERT(!IsNull());
  ASSERT(Length() > 0);
  intptr_t index = Length() - 1;
  const Array& contents = Array::Handle(data());
  const Object& obj = Object::Handle(contents.At(index));
  contents.SetAt(index, Object::Handle());
  SetLength(index);
  return obj.raw();
}


bool GrowableObjectArray::Equals(const Instance& other) const {
  // If both handles point to the same raw instance they are equal.
  if (this->raw() == other.raw()) {
    return true;
  }

  // Other instance must be non null and a GrowableObjectArray.
  if (!other.IsGrowableObjectArray() || other.IsNull()) {
    return false;
  }

  const GrowableObjectArray& other_arr = GrowableObjectArray::Cast(other);

  // The capacity and length of both objects must be equal.
  if (Capacity() != other_arr.Capacity() || Length() != other_arr.Length()) {
    return false;
  }

  // Both must have the same type arguments.
  if (!AbstractTypeArguments::AreEqual(
      AbstractTypeArguments::Handle(GetTypeArguments()),
      AbstractTypeArguments::Handle(other.GetTypeArguments()))) {
    return false;
  }

  // The data part in both arrays must be identical.
  const Array& contents = Array::Handle(data());
  const Array& other_contents = Array::Handle(other_arr.data());
  for (intptr_t i = 0; i < Length(); i++) {
    if (contents.At(i) != other_contents.At(i)) {
      return false;
    }
  }
  return true;
}


RawGrowableObjectArray* GrowableObjectArray::New(intptr_t capacity,
                                                 Heap::Space space) {
  const Array& data = Array::Handle(Array::New(capacity, space));
  return New(data, space);
}


RawGrowableObjectArray* GrowableObjectArray::New(const Array& array,
                                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->growable_object_array_class()
         != Class::null());
  GrowableObjectArray& result = GrowableObjectArray::Handle();
  {
    RawObject* raw = Object::Allocate(GrowableObjectArray::kClassId,
                                      GrowableObjectArray::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(0);
    result.SetData(array);
  }
  return result.raw();
}


const char* GrowableObjectArray::ToCString() const {
  return "GrowableObjectArray";
}


void ByteArray::Copy(void* dst,
                     const ByteArray& src,
                     intptr_t src_offset,
                     intptr_t length) {
  ASSERT(Utils::RangeCheck(src_offset, length, src.ByteLength()));
  {
    NoGCScope no_gc;
    if (length > 0) {
      memmove(dst, src.ByteAddr(src_offset), length);
    }
  }
}


void ByteArray::Copy(const ByteArray& dst,
                     intptr_t dst_offset,
                     const void* src,
                     intptr_t length) {
  ASSERT(Utils::RangeCheck(dst_offset, length, dst.ByteLength()));
  {
    NoGCScope no_gc;
    if (length > 0) {
      memmove(dst.ByteAddr(dst_offset), src, length);
    }
  }
}


void ByteArray::Copy(const ByteArray& dst,
                     intptr_t dst_offset,
                     const ByteArray& src,
                     intptr_t src_offset,
                     intptr_t length) {
  ASSERT(Utils::RangeCheck(src_offset, length, src.ByteLength()));
  ASSERT(Utils::RangeCheck(dst_offset, length, dst.ByteLength()));
  {
    NoGCScope no_gc;
    if (length > 0) {
      memmove(dst.ByteAddr(dst_offset), src.ByteAddr(src_offset), length);
    }
  }
}


template<typename T>
static void ExternalByteArrayFinalize(Dart_Handle handle, void* peer) {
  delete reinterpret_cast<ExternalByteArrayData<T>*>(peer);
  DeleteWeakPersistentHandle(handle);
}


template<typename HandleT, typename RawT, typename ElementT>
RawT* ByteArray::NewExternalImpl(intptr_t class_id,
                                 ElementT* data,
                                 intptr_t len,
                                 void* peer,
                                 Dart_PeerFinalizer callback,
                                 Heap::Space space) {
  if (len < 0 || len > HandleT::kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ByteArray::NewExternalImpl: invalid len %"Pd"\n",
           len);
  }
  HandleT& result = HandleT::Handle();
  ExternalByteArrayData<ElementT>* external_data =
      new ExternalByteArrayData<ElementT>(data, peer, callback);
  {
    RawObject* raw = Object::Allocate(class_id, HandleT::InstanceSize(), space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    result.SetExternalData(external_data);
  }
  AddFinalizer(result, external_data, ExternalByteArrayFinalize<ElementT>);
  return result.raw();
}


intptr_t ByteArray::ByteLength() const {
  // ByteArray is an abstract class.
  UNREACHABLE();
  return 0;
}


uint8_t* ByteArray::ByteAddr(intptr_t byte_offset) const {
  // ByteArray is an abstract class.
  UNREACHABLE();
  return NULL;
}


const char* ByteArray::ToCString() const {
  // ByteArray is an abstract class.
  UNREACHABLE();
  return "ByteArray";
}


template<typename HandleT, typename RawT>
RawT* ByteArray::NewImpl(intptr_t class_id, intptr_t len, Heap::Space space) {
  if (len < 0 || len > HandleT::kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ByteArray::NewImpl: invalid len %"Pd"\n", len);
  }
  HandleT& result = HandleT::Handle();
  {
    RawObject* raw = Object::Allocate(class_id,
                                      HandleT::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    if (len > 0) {
      memset(result.ByteAddr(0), 0, result.ByteLength());
    }
  }
  return result.raw();
}


template<typename HandleT, typename RawT, typename ElementT>
RawT* ByteArray::NewImpl(intptr_t class_id,
                         const ElementT* data,
                         intptr_t len,
                         Heap::Space space) {
  if (len < 0 || len > HandleT::kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in ByteArray::NewImpl: invalid len %"Pd"\n", len);
  }
  HandleT& result = HandleT::Handle();
  {
    RawObject* raw = Object::Allocate(class_id,
                                      HandleT::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.SetLength(len);
    if (len > 0) {
      memmove(result.ByteAddr(0), data, result.ByteLength());
    }
  }
  return result.raw();
}


RawInt8Array* Int8Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int8_array_class() !=
         Class::null());
  return NewImpl<Int8Array, RawInt8Array>(kClassId, len, space);
}


RawInt8Array* Int8Array::New(const int8_t* data,
                             intptr_t len,
                             Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int8_array_class() !=
         Class::null());
  return NewImpl<Int8Array, RawInt8Array>(kClassId, data, len, space);
}


const char* Int8Array::ToCString() const {
  return "_Int8Array";
}


RawUint8Array* Uint8Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint8_array_class() !=
         Class::null());
  return NewImpl<Uint8Array, RawUint8Array>(kClassId, len, space);
}


RawUint8Array* Uint8Array::New(const uint8_t* data,
                               intptr_t len,
                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint8_array_class() !=
         Class::null());
  return NewImpl<Uint8Array, RawUint8Array>(kClassId, data, len, space);
}


const char* Uint8Array::ToCString() const {
  return "_Uint8Array";
}


RawInt16Array* Int16Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int16_array_class() !=
         Class::null());
  return NewImpl<Int16Array, RawInt16Array>(kClassId, len, space);
}


RawInt16Array* Int16Array::New(const int16_t* data,
                               intptr_t len,
                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int16_array_class() !=
         Class::null());
  return NewImpl<Int16Array, RawInt16Array>(kClassId, data, len, space);
}


const char* Int16Array::ToCString() const {
  return "_Int16Array";
}


RawUint16Array* Uint16Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint16_array_class() !=
         Class::null());
  return NewImpl<Uint16Array, RawUint16Array>(kClassId, len, space);
}


RawUint16Array* Uint16Array::New(const uint16_t* data,
                                 intptr_t len,
                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint16_array_class() !=
         Class::null());
  return NewImpl<Uint16Array, RawUint16Array>(kClassId, data, len, space);
}


const char* Uint16Array::ToCString() const {
  return "_Uint16Array";
}


RawInt32Array* Int32Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int32_array_class() !=
         Class::null());
  return NewImpl<Int32Array, RawInt32Array>(kClassId, len, space);
}


RawInt32Array* Int32Array::New(const int32_t* data,
                               intptr_t len,
                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int32_array_class() !=
         Class::null());
  return NewImpl<Int32Array, RawInt32Array>(kClassId, data, len, space);
}


const char* Int32Array::ToCString() const {
  return "_Int32Array";
}


RawUint32Array* Uint32Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint32_array_class() !=
         Class::null());
  return NewImpl<Uint32Array, RawUint32Array>(kClassId, len, space);
}


RawUint32Array* Uint32Array::New(const uint32_t* data,
                                 intptr_t len,
                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint32_array_class() !=
         Class::null());
  return NewImpl<Uint32Array, RawUint32Array>(kClassId, data, len, space);
}


const char* Uint32Array::ToCString() const {
  return "_Uint32Array";
}


RawInt64Array* Int64Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int64_array_class() !=
         Class::null());
  return NewImpl<Int64Array, RawInt64Array>(kClassId, len, space);
}


RawInt64Array* Int64Array::New(const int64_t* data,
                               intptr_t len,
                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->int64_array_class() !=
         Class::null());
  return NewImpl<Int64Array, RawInt64Array>(kClassId, data, len, space);
}


const char* Int64Array::ToCString() const {
  return "_Int64Array";
}


RawUint64Array* Uint64Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint64_array_class() !=
         Class::null());
  return NewImpl<Uint64Array, RawUint64Array>(kClassId, len, space);
}


RawUint64Array* Uint64Array::New(const uint64_t* data,
                                 intptr_t len,
                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->uint64_array_class() !=
         Class::null());
  return NewImpl<Uint64Array, RawUint64Array>(kClassId, data, len, space);
}


const char* Uint64Array::ToCString() const {
  return "_Uint64Array";
}


RawFloat32Array* Float32Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
         Class::null());
  return NewImpl<Float32Array, RawFloat32Array>(kClassId, len, space);
}


RawFloat32Array* Float32Array::New(const float* data,
                                   intptr_t len,
                                   Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->float32_array_class() !=
         Class::null());
  return NewImpl<Float32Array, RawFloat32Array>(kClassId, data, len, space);
}


const char* Float32Array::ToCString() const {
  return "_Float32Array";
}


RawFloat64Array* Float64Array::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->float64_array_class() !=
         Class::null());
  return NewImpl<Float64Array, RawFloat64Array>(kClassId, len, space);
}


RawFloat64Array* Float64Array::New(const double* data,
                                   intptr_t len,
                                   Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->float64_array_class() !=
         Class::null());
  return NewImpl<Float64Array, RawFloat64Array>(kClassId, data, len, space);
}


const char* Float64Array::ToCString() const {
  return "_Float64Array";
}


RawExternalInt8Array* ExternalInt8Array::New(int8_t* data,
                                             intptr_t len,
                                             void* peer,
                                             Dart_PeerFinalizer callback,
                                             Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_int8_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalInt8Array, RawExternalInt8Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalInt8Array::ToCString() const {
  return "_ExternalInt8Array";
}


RawExternalUint8Array* ExternalUint8Array::New(uint8_t* data,
                                               intptr_t len,
                                               void* peer,
                                               Dart_PeerFinalizer callback,
                                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_uint8_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalUint8Array, RawExternalUint8Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalUint8Array::ToCString() const {
  return "_ExternalUint8Array";
}


RawExternalInt16Array* ExternalInt16Array::New(int16_t* data,
                                               intptr_t len,
                                               void* peer,
                                               Dart_PeerFinalizer callback,
                                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_int16_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalInt16Array, RawExternalInt16Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalInt16Array::ToCString() const {
  return "_ExternalInt16Array";
}


RawExternalUint16Array* ExternalUint16Array::New(uint16_t* data,
                                                 intptr_t len,
                                                 void* peer,
                                                 Dart_PeerFinalizer callback,
                                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_uint16_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalUint16Array, RawExternalUint16Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalUint16Array::ToCString() const {
  return "_ExternalUint16Array";
}


RawExternalInt32Array* ExternalInt32Array::New(int32_t* data,
                                               intptr_t len,
                                               void* peer,
                                               Dart_PeerFinalizer callback,
                                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_int32_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalInt32Array, RawExternalInt32Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalInt32Array::ToCString() const {
  return "_ExternalInt32Array";
}


RawExternalUint32Array* ExternalUint32Array::New(uint32_t* data,
                                                 intptr_t len,
                                                 void* peer,
                                                 Dart_PeerFinalizer callback,
                                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_uint32_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalUint32Array, RawExternalUint32Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalUint32Array::ToCString() const {
  return "_ExternalUint32Array";
}


RawExternalInt64Array* ExternalInt64Array::New(int64_t* data,
                                               intptr_t len,
                                               void* peer,
                                               Dart_PeerFinalizer callback,
                                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_int64_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalInt64Array, RawExternalInt64Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalInt64Array::ToCString() const {
  return "_ExternalInt64Array";
}


RawExternalUint64Array* ExternalUint64Array::New(uint64_t* data,
                                                 intptr_t len,
                                                 void* peer,
                                                 Dart_PeerFinalizer callback,
                                                 Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_uint64_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalUint64Array, RawExternalUint64Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalUint64Array::ToCString() const {
  return "_ExternalUint64Array";
}


RawExternalFloat32Array* ExternalFloat32Array::New(float* data,
                                                   intptr_t len,
                                                   void* peer,
                                                   Dart_PeerFinalizer callback,
                                                   Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_float32_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalFloat32Array, RawExternalFloat32Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalFloat32Array::ToCString() const {
  return "_ExternalFloat32Array";
}


RawExternalFloat64Array* ExternalFloat64Array::New(double* data,
                                                   intptr_t len,
                                                   void* peer,
                                                   Dart_PeerFinalizer callback,
                                                   Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->external_float64_array_class() !=
         Class::null());
  return NewExternalImpl<ExternalFloat64Array, RawExternalFloat64Array>(
      kClassId, data, len, peer, callback, space);
}


const char* ExternalFloat64Array::ToCString() const {
  return "_ExternalFloat64Array";
}


const char* Closure::ToCString(const Instance& closure) {
  const Function& fun = Function::Handle(Closure::function(closure));
  const bool is_implicit_closure = fun.IsImplicitClosureFunction();
  const char* fun_sig = String::Handle(fun.Signature()).ToCString();
  const char* from = is_implicit_closure ? " from " : "";
  const char* fun_desc = is_implicit_closure ? fun.ToCString() : "";
  const char* format = "Closure: %s%s%s";
  intptr_t len = OS::SNPrint(NULL, 0, format, fun_sig, from, fun_desc) + 1;
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
  OS::SNPrint(chars, len, format, fun_sig, from, fun_desc);
  return chars;
}


RawInstance* Closure::New(const Function& function,
                          const Context& context,
                          Heap::Space space) {
  Isolate* isolate = Isolate::Current();
  ASSERT(context.isolate() == isolate);

  const Class& cls = Class::Handle(function.signature_class());
  ASSERT(cls.instance_size() == Closure::InstanceSize());
  Instance& result = Instance::Handle();
  {
    RawObject* raw = Object::Allocate(cls.id(), Closure::InstanceSize(), space);
    NoGCScope no_gc;
    result ^= raw;
  }
  Closure::set_function(result, function);
  Closure::set_context(result, context);
  return result.raw();
}


const char* DartFunction::ToCString() const {
  return "Function type class";
}


intptr_t Stacktrace::Length() const {
  const Array& code_array = Array::Handle(raw_ptr()->code_array_);
  return code_array.Length();
}


RawFunction* Stacktrace::FunctionAtFrame(intptr_t frame_index) const {
  const Array& function_array = Array::Handle(raw_ptr()->function_array_);
  return reinterpret_cast<RawFunction*>(function_array.At(frame_index));
}


RawCode* Stacktrace::CodeAtFrame(intptr_t frame_index) const {
  const Array& code_array = Array::Handle(raw_ptr()->code_array_);
  return reinterpret_cast<RawCode*>(code_array.At(frame_index));
}


RawSmi* Stacktrace::PcOffsetAtFrame(intptr_t frame_index) const {
  const Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array_);
  return reinterpret_cast<RawSmi*>(pc_offset_array.At(frame_index));
}


void Stacktrace::set_function_array(const Array& function_array) const {
  StorePointer(&raw_ptr()->function_array_, function_array.raw());
}


void Stacktrace::set_code_array(const Array& code_array) const {
  StorePointer(&raw_ptr()->code_array_, code_array.raw());
}


void Stacktrace::set_pc_offset_array(const Array& pc_offset_array) const {
  StorePointer(&raw_ptr()->pc_offset_array_, pc_offset_array.raw());
}


RawStacktrace* Stacktrace::New(const GrowableObjectArray& func_list,
                               const GrowableObjectArray& code_list,
                               const GrowableObjectArray& pc_offset_list,
                               Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->stacktrace_class() !=
         Class::null());
  Stacktrace& result = Stacktrace::Handle();
  {
    RawObject* raw = Object::Allocate(Stacktrace::kClassId,
                                      Stacktrace::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  // Create arrays for the function, code and pc_offset triplet for each frame.
  const Array& function_array = Array::Handle(Array::MakeArray(func_list));
  const Array& code_array = Array::Handle(Array::MakeArray(code_list));
  const Array& pc_offset_array =
      Array::Handle(Array::MakeArray(pc_offset_list));
  result.set_function_array(function_array);
  result.set_code_array(code_array);
  result.set_pc_offset_array(pc_offset_array);
  return result.raw();
}


void Stacktrace::Append(const GrowableObjectArray& func_list,
                        const GrowableObjectArray& code_list,
                        const GrowableObjectArray& pc_offset_list) const {
  intptr_t old_length = Length();
  intptr_t new_length = old_length + pc_offset_list.Length();
  ASSERT(pc_offset_list.Length() == func_list.Length());
  ASSERT(pc_offset_list.Length() == code_list.Length());

  // Grow the arrays for function, code and pc_offset triplet to accommodate
  // the new stack frames.
  Array& function_array = Array::Handle(raw_ptr()->function_array_);
  Array& code_array = Array::Handle(raw_ptr()->code_array_);
  Array& pc_offset_array = Array::Handle(raw_ptr()->pc_offset_array_);
  function_array = Array::Grow(function_array, new_length);
  code_array = Array::Grow(code_array, new_length);
  pc_offset_array = Array::Grow(pc_offset_array, new_length);
  set_function_array(function_array);
  set_code_array(code_array);
  set_pc_offset_array(pc_offset_array);
  // Now append the new function and code list to the existing arrays.
  intptr_t j = 0;
  Object& obj = Object::Handle();
  for (intptr_t i = old_length; i < new_length; i++, j++) {
    obj = func_list.At(j);
    function_array.SetAt(i, obj);
    obj = code_list.At(j);
    code_array.SetAt(i, obj);
    obj = pc_offset_list.At(j);
    pc_offset_array.SetAt(i, obj);
  }
}


const char* Stacktrace::ToCString() const {
  Function& function = Function::Handle();
  Code& code = Code::Handle();
  Script& script = Script::Handle();
  String& function_name = String::Handle();
  String& url = String::Handle();

  // Iterate through the stack frames and create C string description
  // for each frame.
  intptr_t total_len = 0;
  const char* kFormat = "#%-6d %s (%s:%d:%d)\n";
  GrowableArray<char*> frame_strings;
  for (intptr_t i = 0; i < Length(); i++) {
    function = FunctionAtFrame(i);
    code = CodeAtFrame(i);
    uword pc = code.EntryPoint() + Smi::Value(PcOffsetAtFrame(i));
    intptr_t token_pos = code.GetTokenIndexOfPC(pc);
    script = function.script();
    function_name = function.QualifiedUserVisibleName();
    url = script.url();
    intptr_t line = -1;
    intptr_t column = -1;
    if (token_pos >= 0) {
      script.GetTokenLocation(token_pos, &line, &column);
    }
    intptr_t len = OS::SNPrint(NULL, 0, kFormat,
                               i,
                               function_name.ToCString(),
                               url.ToCString(),
                               line, column);
    total_len += len;
    char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
    OS::SNPrint(chars, (len + 1), kFormat,
                i,
                function_name.ToCString(),
                url.ToCString(),
                line, column);
    frame_strings.Add(chars);
  }

  // Now concatentate the frame descriptions into a single C string.
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(total_len + 1);
  intptr_t index = 0;
  for (intptr_t i = 0; i < frame_strings.length(); i++) {
    index += OS::SNPrint((chars + index),
                         (total_len + 1 - index),
                         "%s",
                         frame_strings[i]);
  }
  return chars;
}


void JSRegExp::set_pattern(const String& pattern) const {
  StorePointer(&raw_ptr()->pattern_, pattern.raw());
}


void JSRegExp::set_num_bracket_expressions(intptr_t value) const {
  raw_ptr()->num_bracket_expressions_ = Smi::New(value);
}


RawJSRegExp* JSRegExp::New(intptr_t len, Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->jsregexp_class() !=
         Class::null());
  if (len < 0 || len > kMaxElements) {
    // This should be caught before we reach here.
    FATAL1("Fatal error in JSRegexp::New: invalid len %"Pd"\n", len);
  }
  JSRegExp& result = JSRegExp::Handle();
  {
    RawObject* raw = Object::Allocate(JSRegExp::kClassId,
                                      JSRegExp::InstanceSize(len),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
    result.set_type(kUnitialized);
    result.set_flags(0);
    result.SetLength(len);
  }
  return result.raw();
}


void* JSRegExp::GetDataStartAddress() const {
  intptr_t addr = reinterpret_cast<intptr_t>(raw_ptr());
  return reinterpret_cast<void*>(addr + sizeof(RawJSRegExp));
}


RawJSRegExp* JSRegExp::FromDataStartAddress(void* data) {
  JSRegExp& regexp = JSRegExp::Handle();
  intptr_t addr = reinterpret_cast<intptr_t>(data) - sizeof(RawJSRegExp);
  regexp ^= RawObject::FromAddr(addr);
  return regexp.raw();
}


const char* JSRegExp::Flags() const {
  switch (raw_ptr()->flags_) {
    case kGlobal | kIgnoreCase | kMultiLine :
    case kIgnoreCase | kMultiLine :
      return "im";
    case kGlobal | kIgnoreCase :
    case kIgnoreCase:
      return "i";
    case kGlobal | kMultiLine :
    case kMultiLine:
      return "m";
    default:
      break;
  }
  return "";
}


bool JSRegExp::Equals(const Instance& other) const {
  if (this->raw() == other.raw()) {
    return true;  // "===".
  }
  if (other.IsNull() || !other.IsJSRegExp()) {
    return false;
  }
  const JSRegExp& other_js = JSRegExp::Cast(other);
  // Match the pattern.
  const String& str1 = String::Handle(pattern());
  const String& str2 = String::Handle(other_js.pattern());
  if (!str1.Equals(str2)) {
    return false;
  }
  // Match the flags.
  if ((is_global() != other_js.is_global()) ||
      (is_ignore_case() != other_js.is_ignore_case()) ||
      (is_multi_line() != other_js.is_multi_line())) {
    return false;
  }
  return true;
}


const char* JSRegExp::ToCString() const {
  const String& str = String::Handle(pattern());
  const char* format = "JSRegExp: pattern=%s flags=%s";
  intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
  char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1);
  OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
  return chars;
}


RawWeakProperty* WeakProperty::New(Heap::Space space) {
  ASSERT(Isolate::Current()->object_store()->weak_property_class()
         != Class::null());
  WeakProperty& result = WeakProperty::Handle();
  {
    RawObject* raw = Object::Allocate(WeakProperty::kClassId,
                                      WeakProperty::InstanceSize(),
                                      space);
    NoGCScope no_gc;
    result ^= raw;
  }
  return result.raw();
}


const char* WeakProperty::ToCString() const {
  return "_WeakProperty";
}

}  // namespace dart
