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/messages.cc b/src/messages.cc
index 290f756..23deb1a 100644
--- a/src/messages.cc
+++ b/src/messages.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "src/v8.h"
+#include "src/messages.h"
 
 #include "src/api.h"
 #include "src/execution.h"
-#include "src/heap/spaces-inl.h"
-#include "src/messages.h"
+#include "src/isolate-inl.h"
+#include "src/string-builder.h"
 
 namespace v8 {
 namespace internal {
@@ -18,13 +18,13 @@
 void MessageHandler::DefaultMessageReport(Isolate* isolate,
                                           const MessageLocation* loc,
                                           Handle<Object> message_obj) {
-  SmartArrayPointer<char> str = GetLocalizedMessage(isolate, message_obj);
+  base::SmartArrayPointer<char> str = GetLocalizedMessage(isolate, message_obj);
   if (loc == NULL) {
     PrintF("%s\n", str.get());
   } else {
     HandleScope scope(isolate);
     Handle<Object> data(loc->script()->name(), isolate);
-    SmartArrayPointer<char> data_str;
+    base::SmartArrayPointer<char> data_str;
     if (data->IsString())
       data_str = Handle<String>::cast(data)->ToCString(DISALLOW_NULLS);
     PrintF("%s:%i: %s\n", data_str.get() ? data_str.get() : "<unknown>",
@@ -34,49 +34,35 @@
 
 
 Handle<JSMessageObject> MessageHandler::MakeMessageObject(
-    Isolate* isolate,
-    const char* type,
-    MessageLocation* loc,
-    Vector< Handle<Object> > args,
+    Isolate* isolate, MessageTemplate::Template message,
+    MessageLocation* location, Handle<Object> argument,
     Handle<JSArray> stack_frames) {
   Factory* factory = isolate->factory();
-  Handle<String> type_handle = factory->InternalizeUtf8String(type);
-  Handle<FixedArray> arguments_elements =
-      factory->NewFixedArray(args.length());
-  for (int i = 0; i < args.length(); i++) {
-    arguments_elements->set(i, *args[i]);
-  }
-  Handle<JSArray> arguments_handle =
-      factory->NewJSArrayWithElements(arguments_elements);
 
-  int start = 0;
-  int end = 0;
+  int start = -1;
+  int end = -1;
   Handle<Object> script_handle = factory->undefined_value();
-  if (loc) {
-    start = loc->start_pos();
-    end = loc->end_pos();
-    script_handle = Script::GetWrapper(loc->script());
+  if (location != NULL) {
+    start = location->start_pos();
+    end = location->end_pos();
+    script_handle = Script::GetWrapper(location->script());
+  } else {
+    script_handle = Script::GetWrapper(isolate->factory()->empty_script());
   }
 
   Handle<Object> stack_frames_handle = stack_frames.is_null()
       ? Handle<Object>::cast(factory->undefined_value())
       : Handle<Object>::cast(stack_frames);
 
-  Handle<JSMessageObject> message =
-      factory->NewJSMessageObject(type_handle,
-                                  arguments_handle,
-                                  start,
-                                  end,
-                                  script_handle,
-                                  stack_frames_handle);
+  Handle<JSMessageObject> message_obj = factory->NewJSMessageObject(
+      message, argument, start, end, script_handle, stack_frames_handle);
 
-  return message;
+  return message_obj;
 }
 
 
-void MessageHandler::ReportMessage(Isolate* isolate,
-                                   MessageLocation* loc,
-                                   Handle<Object> message) {
+void MessageHandler::ReportMessage(Isolate* isolate, MessageLocation* loc,
+                                   Handle<JSMessageObject> message) {
   // We are calling into embedder's code which can throw exceptions.
   // Thus we need to save current exception state, reset it to the clean one
   // and ignore scheduled exceptions callbacks can throw.
@@ -86,14 +72,41 @@
   if (isolate->has_pending_exception()) {
     exception_object = isolate->pending_exception();
   }
-  Handle<Object> exception_handle(exception_object, isolate);
+  Handle<Object> exception(exception_object, isolate);
 
   Isolate::ExceptionScope exception_scope(isolate);
   isolate->clear_pending_exception();
   isolate->set_external_caught_exception(false);
 
+  // Turn the exception on the message into a string if it is an object.
+  if (message->argument()->IsJSObject()) {
+    HandleScope scope(isolate);
+    Handle<Object> argument(message->argument(), isolate);
+
+    MaybeHandle<Object> maybe_stringified;
+    Handle<Object> stringified;
+    // Make sure we don't leak uncaught internally generated Error objects.
+    if (Object::IsErrorObject(isolate, argument)) {
+      Handle<Object> args[] = {argument};
+      maybe_stringified = Execution::TryCall(
+          isolate, isolate->no_side_effects_to_string_fun(),
+          isolate->factory()->undefined_value(), arraysize(args), args);
+    } else {
+      v8::TryCatch catcher(reinterpret_cast<v8::Isolate*>(isolate));
+      catcher.SetVerbose(false);
+      catcher.SetCaptureMessage(false);
+
+      maybe_stringified = Object::ToString(isolate, argument);
+    }
+
+    if (!maybe_stringified.ToHandle(&stringified)) {
+      stringified = isolate->factory()->NewStringFromAsciiChecked("exception");
+    }
+    message->set_argument(*stringified);
+  }
+
   v8::Local<v8::Message> api_message_obj = v8::Utils::MessageToLocal(message);
-  v8::Local<v8::Value> api_exception_obj = v8::Utils::ToLocal(exception_handle);
+  v8::Local<v8::Value> api_exception_obj = v8::Utils::ToLocal(exception);
 
   v8::NeanderArray global_listeners(isolate->factory()->message_listeners());
   int global_length = global_listeners.length();
@@ -113,7 +126,7 @@
       Handle<Object> callback_data(listener.get(1), isolate);
       {
         // Do not allow exceptions to propagate.
-        v8::TryCatch try_catch;
+        v8::TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
         callback(api_message_obj, callback_data->IsUndefined()
                                       ? api_exception_obj
                                       : v8::Utils::ToLocal(callback_data));
@@ -128,38 +141,266 @@
 
 Handle<String> MessageHandler::GetMessage(Isolate* isolate,
                                           Handle<Object> data) {
-  Factory* factory = isolate->factory();
-  Handle<String> fmt_str =
-      factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("FormatMessage"));
-  Handle<JSFunction> fun = Handle<JSFunction>::cast(Object::GetProperty(
-          isolate->js_builtins_object(), fmt_str).ToHandleChecked());
   Handle<JSMessageObject> message = Handle<JSMessageObject>::cast(data);
-  Handle<Object> argv[] = { Handle<Object>(message->type(), isolate),
-                            Handle<Object>(message->arguments(), isolate) };
-
-  MaybeHandle<Object> maybe_result = Execution::TryCall(
-      fun, isolate->js_builtins_object(), arraysize(argv), argv);
-  Handle<Object> result;
-  if (!maybe_result.ToHandle(&result) || !result->IsString()) {
-    return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>"));
-  }
-  Handle<String> result_string = Handle<String>::cast(result);
-  // A string that has been obtained from JS code in this way is
-  // likely to be a complicated ConsString of some sort.  We flatten it
-  // here to improve the efficiency of converting it to a C string and
-  // other operations that are likely to take place (see GetLocalizedMessage
-  // for example).
-  result_string = String::Flatten(result_string);
-  return result_string;
+  Handle<Object> arg = Handle<Object>(message->argument(), isolate);
+  return MessageTemplate::FormatMessage(isolate, message->type(), arg);
 }
 
 
-SmartArrayPointer<char> MessageHandler::GetLocalizedMessage(
-    Isolate* isolate,
-    Handle<Object> data) {
+base::SmartArrayPointer<char> MessageHandler::GetLocalizedMessage(
+    Isolate* isolate, Handle<Object> data) {
   HandleScope scope(isolate);
   return GetMessage(isolate, data)->ToCString(DISALLOW_NULLS);
 }
 
 
-} }  // namespace v8::internal
+CallSite::CallSite(Isolate* isolate, Handle<JSObject> call_site_obj)
+    : isolate_(isolate) {
+  Handle<Object> maybe_function = JSObject::GetDataProperty(
+      call_site_obj, isolate->factory()->call_site_function_symbol());
+  if (!maybe_function->IsJSFunction()) return;
+
+  fun_ = Handle<JSFunction>::cast(maybe_function);
+  receiver_ = JSObject::GetDataProperty(
+      call_site_obj, isolate->factory()->call_site_receiver_symbol());
+  CHECK(JSObject::GetDataProperty(
+            call_site_obj, isolate->factory()->call_site_position_symbol())
+            ->ToInt32(&pos_));
+}
+
+
+Handle<Object> CallSite::GetFileName() {
+  Handle<Object> script(fun_->shared()->script(), isolate_);
+  if (script->IsScript()) {
+    return Handle<Object>(Handle<Script>::cast(script)->name(), isolate_);
+  }
+  return isolate_->factory()->null_value();
+}
+
+
+Handle<Object> CallSite::GetFunctionName() {
+  Handle<String> result = JSFunction::GetName(fun_);
+  if (result->length() != 0) return result;
+
+  Handle<Object> script(fun_->shared()->script(), isolate_);
+  if (script->IsScript() &&
+      Handle<Script>::cast(script)->compilation_type() ==
+          Script::COMPILATION_TYPE_EVAL) {
+    return isolate_->factory()->eval_string();
+  }
+  return isolate_->factory()->null_value();
+}
+
+
+Handle<Object> CallSite::GetScriptNameOrSourceUrl() {
+  Handle<Object> script_obj(fun_->shared()->script(), isolate_);
+  if (script_obj->IsScript()) {
+    Handle<Script> script = Handle<Script>::cast(script_obj);
+    Object* source_url = script->source_url();
+    if (source_url->IsString()) return Handle<Object>(source_url, isolate_);
+    return Handle<Object>(script->name(), isolate_);
+  }
+  return isolate_->factory()->null_value();
+}
+
+
+bool CheckMethodName(Isolate* isolate, Handle<JSObject> obj, Handle<Name> name,
+                     Handle<JSFunction> fun,
+                     LookupIterator::Configuration config) {
+  LookupIterator iter =
+      LookupIterator::PropertyOrElement(isolate, obj, name, config);
+  if (iter.state() == LookupIterator::DATA) {
+    return iter.GetDataValue().is_identical_to(fun);
+  } else if (iter.state() == LookupIterator::ACCESSOR) {
+    Handle<Object> accessors = iter.GetAccessors();
+    if (accessors->IsAccessorPair()) {
+      Handle<AccessorPair> pair = Handle<AccessorPair>::cast(accessors);
+      return pair->getter() == *fun || pair->setter() == *fun;
+    }
+  }
+  return false;
+}
+
+
+Handle<Object> CallSite::GetMethodName() {
+  MaybeHandle<JSReceiver> maybe = Object::ToObject(isolate_, receiver_);
+  Handle<JSReceiver> receiver;
+  if (!maybe.ToHandle(&receiver) || !receiver->IsJSObject()) {
+    return isolate_->factory()->null_value();
+  }
+
+  Handle<JSObject> obj = Handle<JSObject>::cast(receiver);
+  Handle<Object> function_name(fun_->shared()->name(), isolate_);
+  if (function_name->IsName()) {
+    Handle<Name> name = Handle<Name>::cast(function_name);
+    if (CheckMethodName(isolate_, obj, name, fun_,
+                        LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR))
+      return name;
+  }
+
+  HandleScope outer_scope(isolate_);
+  Handle<Object> result;
+  for (PrototypeIterator iter(isolate_, obj,
+                              PrototypeIterator::START_AT_RECEIVER);
+       !iter.IsAtEnd(); iter.Advance()) {
+    Handle<Object> current = PrototypeIterator::GetCurrent(iter);
+    if (!current->IsJSObject()) break;
+    Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
+    if (current_obj->IsAccessCheckNeeded()) break;
+    Handle<FixedArray> keys = JSObject::GetEnumPropertyKeys(current_obj, false);
+    for (int i = 0; i < keys->length(); i++) {
+      HandleScope inner_scope(isolate_);
+      if (!keys->get(i)->IsName()) continue;
+      Handle<Name> name_key(Name::cast(keys->get(i)), isolate_);
+      if (!CheckMethodName(isolate_, current_obj, name_key, fun_,
+                           LookupIterator::OWN_SKIP_INTERCEPTOR))
+        continue;
+      // Return null in case of duplicates to avoid confusion.
+      if (!result.is_null()) return isolate_->factory()->null_value();
+      result = inner_scope.CloseAndEscape(name_key);
+    }
+  }
+
+  if (!result.is_null()) return outer_scope.CloseAndEscape(result);
+  return isolate_->factory()->null_value();
+}
+
+
+int CallSite::GetLineNumber() {
+  if (pos_ >= 0) {
+    Handle<Object> script_obj(fun_->shared()->script(), isolate_);
+    if (script_obj->IsScript()) {
+      Handle<Script> script = Handle<Script>::cast(script_obj);
+      return Script::GetLineNumber(script, pos_) + 1;
+    }
+  }
+  return -1;
+}
+
+
+int CallSite::GetColumnNumber() {
+  if (pos_ >= 0) {
+    Handle<Object> script_obj(fun_->shared()->script(), isolate_);
+    if (script_obj->IsScript()) {
+      Handle<Script> script = Handle<Script>::cast(script_obj);
+      return Script::GetColumnNumber(script, pos_) + 1;
+    }
+  }
+  return -1;
+}
+
+
+bool CallSite::IsNative() {
+  Handle<Object> script(fun_->shared()->script(), isolate_);
+  return script->IsScript() &&
+         Handle<Script>::cast(script)->type() == Script::TYPE_NATIVE;
+}
+
+
+bool CallSite::IsToplevel() {
+  return receiver_->IsJSGlobalProxy() || receiver_->IsNull() ||
+         receiver_->IsUndefined();
+}
+
+
+bool CallSite::IsEval() {
+  Handle<Object> script(fun_->shared()->script(), isolate_);
+  return script->IsScript() &&
+         Handle<Script>::cast(script)->compilation_type() ==
+             Script::COMPILATION_TYPE_EVAL;
+}
+
+
+bool CallSite::IsConstructor() {
+  if (!receiver_->IsJSObject()) return false;
+  Handle<Object> constructor =
+      JSReceiver::GetDataProperty(Handle<JSObject>::cast(receiver_),
+                                  isolate_->factory()->constructor_string());
+  return constructor.is_identical_to(fun_);
+}
+
+
+Handle<String> MessageTemplate::FormatMessage(Isolate* isolate,
+                                              int template_index,
+                                              Handle<Object> arg) {
+  Factory* factory = isolate->factory();
+  Handle<String> result_string;
+  if (arg->IsString()) {
+    result_string = Handle<String>::cast(arg);
+  } else {
+    Handle<JSFunction> fun = isolate->no_side_effects_to_string_fun();
+
+    MaybeHandle<Object> maybe_result =
+        Execution::TryCall(isolate, fun, factory->undefined_value(), 1, &arg);
+    Handle<Object> result;
+    if (!maybe_result.ToHandle(&result) || !result->IsString()) {
+      return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>"));
+    }
+    result_string = Handle<String>::cast(result);
+  }
+  MaybeHandle<String> maybe_result_string = MessageTemplate::FormatMessage(
+      template_index, result_string, factory->empty_string(),
+      factory->empty_string());
+  if (!maybe_result_string.ToHandle(&result_string)) {
+    return factory->InternalizeOneByteString(STATIC_CHAR_VECTOR("<error>"));
+  }
+  // A string that has been obtained from JS code in this way is
+  // likely to be a complicated ConsString of some sort.  We flatten it
+  // here to improve the efficiency of converting it to a C string and
+  // other operations that are likely to take place (see GetLocalizedMessage
+  // for example).
+  return String::Flatten(result_string);
+}
+
+
+const char* MessageTemplate::TemplateString(int template_index) {
+  switch (template_index) {
+#define CASE(NAME, STRING) \
+  case k##NAME:            \
+    return STRING;
+    MESSAGE_TEMPLATES(CASE)
+#undef CASE
+    case kLastMessage:
+    default:
+      return NULL;
+  }
+}
+
+
+MaybeHandle<String> MessageTemplate::FormatMessage(int template_index,
+                                                   Handle<String> arg0,
+                                                   Handle<String> arg1,
+                                                   Handle<String> arg2) {
+  Isolate* isolate = arg0->GetIsolate();
+  const char* template_string = TemplateString(template_index);
+  if (template_string == NULL) {
+    isolate->ThrowIllegalOperation();
+    return MaybeHandle<String>();
+  }
+
+  IncrementalStringBuilder builder(isolate);
+
+  unsigned int i = 0;
+  Handle<String> args[] = {arg0, arg1, arg2};
+  for (const char* c = template_string; *c != '\0'; c++) {
+    if (*c == '%') {
+      // %% results in verbatim %.
+      if (*(c + 1) == '%') {
+        c++;
+        builder.AppendCharacter('%');
+      } else {
+        DCHECK(i < arraysize(args));
+        Handle<String> arg = args[i++];
+        builder.AppendString(arg);
+      }
+    } else {
+      builder.AppendCharacter(*c);
+    }
+  }
+
+  return builder.Finish();
+}
+
+
+}  // namespace internal
+}  // namespace v8