Upgrade V8 to version 4.9.385.28

https://chromium.googlesource.com/v8/v8/+/4.9.385.28

FPIIM-449

Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/api-natives.cc b/src/api-natives.cc
new file mode 100644
index 0000000..bc71e3e
--- /dev/null
+++ b/src/api-natives.cc
@@ -0,0 +1,625 @@
+// Copyright 2015 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/api-natives.h"
+
+#include "src/api.h"
+#include "src/isolate-inl.h"
+#include "src/lookup.h"
+#include "src/messages.h"
+
+namespace v8 {
+namespace internal {
+
+
+namespace {
+
+MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
+                                        Handle<ObjectTemplateInfo> data);
+
+
+MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
+                                            Handle<FunctionTemplateInfo> data,
+                                            Handle<Name> name = Handle<Name>());
+
+
+MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data,
+                                Handle<Name> name = Handle<Name>()) {
+  if (data->IsFunctionTemplateInfo()) {
+    return InstantiateFunction(isolate,
+                               Handle<FunctionTemplateInfo>::cast(data), name);
+  } else if (data->IsObjectTemplateInfo()) {
+    return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data));
+  } else {
+    return data;
+  }
+}
+
+
+MaybeHandle<Object> DefineAccessorProperty(Isolate* isolate,
+                                           Handle<JSObject> object,
+                                           Handle<Name> name,
+                                           Handle<Object> getter,
+                                           Handle<Object> setter,
+                                           PropertyAttributes attributes) {
+  if (!getter->IsUndefined()) {
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, getter,
+        InstantiateFunction(isolate,
+                            Handle<FunctionTemplateInfo>::cast(getter)),
+        Object);
+  }
+  if (!setter->IsUndefined()) {
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, setter,
+        InstantiateFunction(isolate,
+                            Handle<FunctionTemplateInfo>::cast(setter)),
+        Object);
+  }
+  RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
+                                                        setter, attributes),
+                      Object);
+  return object;
+}
+
+
+MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
+                                       Handle<JSObject> object,
+                                       Handle<Name> name,
+                                       Handle<Object> prop_data,
+                                       PropertyAttributes attributes) {
+  Handle<Object> value;
+  ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
+                             Instantiate(isolate, prop_data, name), Object);
+
+  LookupIterator it = LookupIterator::PropertyOrElement(
+      isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
+
+#ifdef DEBUG
+  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
+  DCHECK(maybe.IsJust());
+  if (it.IsFound()) {
+    THROW_NEW_ERROR(
+        isolate,
+        NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
+        Object);
+  }
+#endif
+
+  MAYBE_RETURN_NULL(
+      Object::AddDataProperty(&it, value, attributes, Object::THROW_ON_ERROR,
+                              Object::CERTAINLY_NOT_STORE_FROM_KEYED));
+  return value;
+}
+
+
+void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
+  Handle<Map> old_map(object->map());
+  // Copy map so it won't interfere constructor's initial map.
+  Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
+  new_map->set_is_access_check_needed(false);
+  JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
+}
+
+
+void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
+  Handle<Map> old_map(object->map());
+  // Copy map so it won't interfere constructor's initial map.
+  Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
+  new_map->set_is_access_check_needed(true);
+  JSObject::MigrateToMap(object, new_map);
+}
+
+
+class AccessCheckDisableScope {
+ public:
+  AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
+      : isolate_(isolate),
+        disabled_(obj->map()->is_access_check_needed()),
+        obj_(obj) {
+    if (disabled_) {
+      DisableAccessChecks(isolate_, obj_);
+    }
+  }
+  ~AccessCheckDisableScope() {
+    if (disabled_) {
+      EnableAccessChecks(isolate_, obj_);
+    }
+  }
+
+ private:
+  Isolate* isolate_;
+  const bool disabled_;
+  Handle<JSObject> obj_;
+};
+
+
+Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
+  Handle<Context> native_context = isolate->native_context();
+  DCHECK(!native_context.is_null());
+  switch (intrinsic) {
+#define GET_INTRINSIC_VALUE(name, iname) \
+  case v8::k##name:                      \
+    return native_context->iname();
+    V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
+#undef GET_INTRINSIC_VALUE
+  }
+  return nullptr;
+}
+
+
+MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
+                                        Handle<TemplateInfo> data) {
+  auto property_list = handle(data->property_list(), isolate);
+  if (property_list->IsUndefined()) return obj;
+  // TODO(dcarney): just use a FixedArray here.
+  NeanderArray properties(property_list);
+  if (properties.length() == 0) return obj;
+  HandleScope scope(isolate);
+  // Disable access checks while instantiating the object.
+  AccessCheckDisableScope access_check_scope(isolate, obj);
+
+  int i = 0;
+  for (int c = 0; c < data->number_of_properties(); c++) {
+    auto name = handle(Name::cast(properties.get(i++)), isolate);
+    auto bit = handle(properties.get(i++), isolate);
+    if (bit->IsSmi()) {
+      PropertyDetails details(Smi::cast(*bit));
+      PropertyAttributes attributes = details.attributes();
+      PropertyKind kind = details.kind();
+
+      if (kind == kData) {
+        auto prop_data = handle(properties.get(i++), isolate);
+
+        RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
+                                                        prop_data, attributes),
+                            JSObject);
+      } else {
+        auto getter = handle(properties.get(i++), isolate);
+        auto setter = handle(properties.get(i++), isolate);
+        RETURN_ON_EXCEPTION(isolate,
+                            DefineAccessorProperty(isolate, obj, name, getter,
+                                                   setter, attributes),
+                            JSObject);
+      }
+    } else {
+      // Intrinsic data property --- Get appropriate value from the current
+      // context.
+      PropertyDetails details(Smi::cast(properties.get(i++)));
+      PropertyAttributes attributes = details.attributes();
+      DCHECK_EQ(kData, details.kind());
+
+      v8::Intrinsic intrinsic =
+          static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value());
+      auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
+
+      RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
+                                                      prop_data, attributes),
+                          JSObject);
+    }
+  }
+  return obj;
+}
+
+
+MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
+                                        Handle<ObjectTemplateInfo> data) {
+  // Enter a new scope.  Recursion could otherwise create a lot of handles.
+  HandleScope scope(isolate);
+  // Fast path.
+  Handle<JSObject> result;
+  auto info = Handle<ObjectTemplateInfo>::cast(data);
+  auto constructor = handle(info->constructor(), isolate);
+  Handle<JSFunction> cons;
+  if (constructor->IsUndefined()) {
+    cons = isolate->object_function();
+  } else {
+    auto cons_templ = Handle<FunctionTemplateInfo>::cast(constructor);
+    ASSIGN_RETURN_ON_EXCEPTION(
+        isolate, cons, InstantiateFunction(isolate, cons_templ), JSFunction);
+  }
+  auto object = isolate->factory()->NewJSObject(cons);
+  ASSIGN_RETURN_ON_EXCEPTION(
+      isolate, result, ConfigureInstance(isolate, object, info), JSFunction);
+  // TODO(dcarney): is this necessary?
+  JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
+  return scope.CloseAndEscape(result);
+}
+
+
+void CacheFunction(Isolate* isolate, Handle<Smi> serial_number,
+                   Handle<JSFunction> function) {
+  auto cache = isolate->function_cache();
+  auto new_cache = ObjectHashTable::Put(cache, serial_number, function);
+  isolate->native_context()->set_function_cache(*new_cache);
+}
+
+
+void UncacheFunction(Isolate* isolate, Handle<Smi> serial_number) {
+  auto cache = isolate->function_cache();
+  bool was_present = false;
+  auto new_cache = ObjectHashTable::Remove(cache, serial_number, &was_present);
+  DCHECK(was_present);
+  isolate->native_context()->set_function_cache(*new_cache);
+}
+
+
+MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
+                                            Handle<FunctionTemplateInfo> data,
+                                            Handle<Name> name) {
+  auto serial_number = handle(Smi::cast(data->serial_number()), isolate);
+  // Probe cache.
+  if (!data->do_not_cache()) {
+    auto cache = isolate->function_cache();
+    Object* element = cache->Lookup(serial_number);
+    if (element->IsJSFunction()) {
+      return handle(JSFunction::cast(element), isolate);
+    }
+  }
+  // Enter a new scope.  Recursion could otherwise create a lot of handles.
+  HandleScope scope(isolate);
+  Handle<JSObject> prototype;
+  if (!data->remove_prototype()) {
+    auto prototype_templ = handle(data->prototype_template(), isolate);
+    if (prototype_templ->IsUndefined()) {
+      prototype = isolate->factory()->NewJSObject(isolate->object_function());
+    } else {
+      ASSIGN_RETURN_ON_EXCEPTION(
+          isolate, prototype,
+          InstantiateObject(isolate,
+                            Handle<ObjectTemplateInfo>::cast(prototype_templ)),
+          JSFunction);
+    }
+    auto parent = handle(data->parent_template(), isolate);
+    if (!parent->IsUndefined()) {
+      Handle<JSFunction> parent_instance;
+      ASSIGN_RETURN_ON_EXCEPTION(
+          isolate, parent_instance,
+          InstantiateFunction(isolate,
+                              Handle<FunctionTemplateInfo>::cast(parent)),
+          JSFunction);
+      // TODO(dcarney): decide what to do here.
+      Handle<Object> parent_prototype;
+      ASSIGN_RETURN_ON_EXCEPTION(
+          isolate, parent_prototype,
+          JSObject::GetProperty(parent_instance,
+                                isolate->factory()->prototype_string()),
+          JSFunction);
+      MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false,
+                                          Object::THROW_ON_ERROR),
+                   MaybeHandle<JSFunction>());
+    }
+  }
+  auto function = ApiNatives::CreateApiFunction(
+      isolate, data, prototype, ApiNatives::JavaScriptObjectType);
+  if (!name.is_null() && name->IsString()) {
+    function->shared()->set_name(*name);
+  }
+  if (!data->do_not_cache()) {
+    // Cache the function.
+    CacheFunction(isolate, serial_number, function);
+  }
+  auto result = ConfigureInstance(isolate, function, data);
+  if (result.is_null()) {
+    // Uncache on error.
+    if (!data->do_not_cache()) {
+      UncacheFunction(isolate, serial_number);
+    }
+    return MaybeHandle<JSFunction>();
+  }
+  return scope.CloseAndEscape(function);
+}
+
+
+class InvokeScope {
+ public:
+  explicit InvokeScope(Isolate* isolate)
+      : isolate_(isolate), save_context_(isolate) {}
+  ~InvokeScope() {
+    bool has_exception = isolate_->has_pending_exception();
+    if (has_exception) {
+      isolate_->ReportPendingMessages();
+    } else {
+      isolate_->clear_pending_message();
+    }
+  }
+
+ private:
+  Isolate* isolate_;
+  SaveContext save_context_;
+};
+
+
+void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
+                               int length, Handle<Object>* data) {
+  auto list = handle(templ->property_list(), isolate);
+  if (list->IsUndefined()) {
+    list = NeanderArray(isolate).value();
+    templ->set_property_list(*list);
+  }
+  templ->set_number_of_properties(templ->number_of_properties() + 1);
+  NeanderArray array(list);
+  for (int i = 0; i < length; i++) {
+    Handle<Object> value =
+        data[i].is_null()
+            ? Handle<Object>::cast(isolate->factory()->undefined_value())
+            : data[i];
+    array.add(isolate, value);
+  }
+}
+
+}  // namespace
+
+
+MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
+    Handle<FunctionTemplateInfo> data) {
+  Isolate* isolate = data->GetIsolate();
+  InvokeScope invoke_scope(isolate);
+  return ::v8::internal::InstantiateFunction(isolate, data);
+}
+
+
+MaybeHandle<JSObject> ApiNatives::InstantiateObject(
+    Handle<ObjectTemplateInfo> data) {
+  Isolate* isolate = data->GetIsolate();
+  InvokeScope invoke_scope(isolate);
+  return ::v8::internal::InstantiateObject(isolate, data);
+}
+
+
+MaybeHandle<FunctionTemplateInfo> ApiNatives::ConfigureInstance(
+    Isolate* isolate, Handle<FunctionTemplateInfo> desc,
+    Handle<JSObject> instance) {
+  // Configure the instance by adding the properties specified by the
+  // instance template.
+  if (desc->instance_template()->IsUndefined()) return desc;
+  InvokeScope invoke_scope(isolate);
+  Handle<ObjectTemplateInfo> instance_template(
+      ObjectTemplateInfo::cast(desc->instance_template()), isolate);
+  RETURN_ON_EXCEPTION(isolate, ::v8::internal::ConfigureInstance(
+                                   isolate, instance, instance_template),
+                      FunctionTemplateInfo);
+  return desc;
+}
+
+
+void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
+                                 Handle<Name> name, Handle<Object> value,
+                                 PropertyAttributes attributes) {
+  const int kSize = 3;
+  PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
+  auto details_handle = handle(details.AsSmi(), isolate);
+  Handle<Object> data[kSize] = {name, details_handle, value};
+  AddPropertyToPropertyList(isolate, info, kSize, data);
+}
+
+
+void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
+                                 Handle<Name> name, v8::Intrinsic intrinsic,
+                                 PropertyAttributes attributes) {
+  const int kSize = 4;
+  auto value = handle(Smi::FromInt(intrinsic), isolate);
+  auto intrinsic_marker = isolate->factory()->true_value();
+  PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
+  auto details_handle = handle(details.AsSmi(), isolate);
+  Handle<Object> data[kSize] = {name, intrinsic_marker, details_handle, value};
+  AddPropertyToPropertyList(isolate, info, kSize, data);
+}
+
+
+void ApiNatives::AddAccessorProperty(Isolate* isolate,
+                                     Handle<TemplateInfo> info,
+                                     Handle<Name> name,
+                                     Handle<FunctionTemplateInfo> getter,
+                                     Handle<FunctionTemplateInfo> setter,
+                                     PropertyAttributes attributes) {
+  const int kSize = 4;
+  PropertyDetails details(attributes, ACCESSOR, 0, PropertyCellType::kNoCell);
+  auto details_handle = handle(details.AsSmi(), isolate);
+  Handle<Object> data[kSize] = {name, details_handle, getter, setter};
+  AddPropertyToPropertyList(isolate, info, kSize, data);
+}
+
+
+void ApiNatives::AddNativeDataProperty(Isolate* isolate,
+                                       Handle<TemplateInfo> info,
+                                       Handle<AccessorInfo> property) {
+  auto list = handle(info->property_accessors(), isolate);
+  if (list->IsUndefined()) {
+    list = NeanderArray(isolate).value();
+    info->set_property_accessors(*list);
+  }
+  NeanderArray array(list);
+  array.add(isolate, property);
+}
+
+
+Handle<JSFunction> ApiNatives::CreateApiFunction(
+    Isolate* isolate, Handle<FunctionTemplateInfo> obj,
+    Handle<Object> prototype, ApiInstanceType instance_type) {
+  Handle<Code> code;
+  if (obj->call_code()->IsCallHandlerInfo() &&
+      CallHandlerInfo::cast(obj->call_code())->fast_handler()->IsCode()) {
+    code = isolate->builtins()->HandleFastApiCall();
+  } else {
+    code = isolate->builtins()->HandleApiCall();
+  }
+  Handle<Code> construct_stub =
+      prototype.is_null() ? isolate->builtins()->ConstructedNonConstructable()
+                          : isolate->builtins()->JSConstructStubApi();
+
+  obj->set_instantiated(true);
+  Handle<JSFunction> result;
+  if (obj->remove_prototype()) {
+    result = isolate->factory()->NewFunctionWithoutPrototype(
+        isolate->factory()->empty_string(), code);
+  } else {
+    int internal_field_count = 0;
+    if (!obj->instance_template()->IsUndefined()) {
+      Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
+          ObjectTemplateInfo::cast(obj->instance_template()));
+      internal_field_count =
+          Smi::cast(instance_template->internal_field_count())->value();
+    }
+
+    // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
+    // JSObject::GetHeaderSize.
+    int instance_size = kPointerSize * internal_field_count;
+    InstanceType type;
+    switch (instance_type) {
+      case JavaScriptObjectType:
+        type = JS_OBJECT_TYPE;
+        instance_size += JSObject::kHeaderSize;
+        break;
+      case GlobalObjectType:
+        type = JS_GLOBAL_OBJECT_TYPE;
+        instance_size += JSGlobalObject::kSize;
+        break;
+      case GlobalProxyType:
+        type = JS_GLOBAL_PROXY_TYPE;
+        instance_size += JSGlobalProxy::kSize;
+        break;
+      default:
+        UNREACHABLE();
+        type = JS_OBJECT_TYPE;  // Keep the compiler happy.
+        break;
+    }
+
+    result = isolate->factory()->NewFunction(
+        isolate->factory()->empty_string(), code, prototype, type,
+        instance_size, obj->read_only_prototype(), true);
+  }
+
+  result->shared()->set_length(obj->length());
+  Handle<Object> class_name(obj->class_name(), isolate);
+  if (class_name->IsString()) {
+    result->shared()->set_instance_class_name(*class_name);
+    result->shared()->set_name(*class_name);
+  }
+  result->shared()->set_function_data(*obj);
+  result->shared()->set_construct_stub(*construct_stub);
+  result->shared()->DontAdaptArguments();
+
+  if (obj->remove_prototype()) {
+    DCHECK(result->shared()->IsApiFunction());
+    DCHECK(!result->has_initial_map());
+    DCHECK(!result->has_prototype());
+    return result;
+  }
+
+#ifdef DEBUG
+  LookupIterator it(handle(JSObject::cast(result->prototype())),
+                    isolate->factory()->constructor_string(),
+                    LookupIterator::OWN_SKIP_INTERCEPTOR);
+  MaybeHandle<Object> maybe_prop = Object::GetProperty(&it);
+  DCHECK(it.IsFound());
+  DCHECK(maybe_prop.ToHandleChecked().is_identical_to(result));
+#endif
+
+  // Down from here is only valid for API functions that can be used as a
+  // constructor (don't set the "remove prototype" flag).
+
+  Handle<Map> map(result->initial_map());
+
+  // Mark as undetectable if needed.
+  if (obj->undetectable()) {
+    map->set_is_undetectable();
+  }
+
+  // Mark as hidden for the __proto__ accessor if needed.
+  if (obj->hidden_prototype()) {
+    map->set_is_hidden_prototype();
+  }
+
+  // Mark as needs_access_check if needed.
+  if (obj->needs_access_check()) {
+    map->set_is_access_check_needed(true);
+  }
+
+  // Set interceptor information in the map.
+  if (!obj->named_property_handler()->IsUndefined()) {
+    map->set_has_named_interceptor();
+  }
+  if (!obj->indexed_property_handler()->IsUndefined()) {
+    map->set_has_indexed_interceptor();
+  }
+
+  // Mark instance as callable in the map.
+  if (!obj->instance_call_handler()->IsUndefined()) {
+    map->set_is_callable();
+    map->set_is_constructor();
+  }
+
+  // Recursively copy parent instance templates' accessors,
+  // 'data' may be modified.
+  int max_number_of_additional_properties = 0;
+  int max_number_of_static_properties = 0;
+  FunctionTemplateInfo* info = *obj;
+  while (true) {
+    if (!info->instance_template()->IsUndefined()) {
+      Object* props = ObjectTemplateInfo::cast(info->instance_template())
+                          ->property_accessors();
+      if (!props->IsUndefined()) {
+        Handle<Object> props_handle(props, isolate);
+        NeanderArray props_array(props_handle);
+        max_number_of_additional_properties += props_array.length();
+      }
+    }
+    if (!info->property_accessors()->IsUndefined()) {
+      Object* props = info->property_accessors();
+      if (!props->IsUndefined()) {
+        Handle<Object> props_handle(props, isolate);
+        NeanderArray props_array(props_handle);
+        max_number_of_static_properties += props_array.length();
+      }
+    }
+    Object* parent = info->parent_template();
+    if (parent->IsUndefined()) break;
+    info = FunctionTemplateInfo::cast(parent);
+  }
+
+  Map::EnsureDescriptorSlack(map, max_number_of_additional_properties);
+
+  // Use a temporary FixedArray to acculumate static accessors
+  int valid_descriptors = 0;
+  Handle<FixedArray> array;
+  if (max_number_of_static_properties > 0) {
+    array = isolate->factory()->NewFixedArray(max_number_of_static_properties);
+  }
+
+  while (true) {
+    // Install instance descriptors
+    if (!obj->instance_template()->IsUndefined()) {
+      Handle<ObjectTemplateInfo> instance = Handle<ObjectTemplateInfo>(
+          ObjectTemplateInfo::cast(obj->instance_template()), isolate);
+      Handle<Object> props =
+          Handle<Object>(instance->property_accessors(), isolate);
+      if (!props->IsUndefined()) {
+        Map::AppendCallbackDescriptors(map, props);
+      }
+    }
+    // Accumulate static accessors
+    if (!obj->property_accessors()->IsUndefined()) {
+      Handle<Object> props = Handle<Object>(obj->property_accessors(), isolate);
+      valid_descriptors =
+          AccessorInfo::AppendUnique(props, array, valid_descriptors);
+    }
+    // Climb parent chain
+    Handle<Object> parent = Handle<Object>(obj->parent_template(), isolate);
+    if (parent->IsUndefined()) break;
+    obj = Handle<FunctionTemplateInfo>::cast(parent);
+  }
+
+  // Install accumulated static accessors
+  for (int i = 0; i < valid_descriptors; i++) {
+    Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
+    JSObject::SetAccessor(result, accessor).Assert();
+  }
+
+  DCHECK(result->shared()->IsApiFunction());
+  return result;
+}
+
+}  // namespace internal
+}  // namespace v8