Update V8 to version 4.1.0.21

This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.

Original commit message:

Version 4.1.0.21 (cherry-pick)

Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412

Unlink pages from the space page list after evacuation.

BUG=430201
LOG=N
R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/953813002

Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}

---

FPIIM-449

Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/runtime/runtime-compiler.cc b/src/runtime/runtime-compiler.cc
new file mode 100644
index 0000000..ebd0c13
--- /dev/null
+++ b/src/runtime/runtime-compiler.cc
@@ -0,0 +1,451 @@
+// Copyright 2014 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/v8.h"
+
+#include "src/arguments.h"
+#include "src/compiler.h"
+#include "src/deoptimizer.h"
+#include "src/frames.h"
+#include "src/full-codegen.h"
+#include "src/isolate-inl.h"
+#include "src/runtime/runtime-utils.h"
+#include "src/v8threads.h"
+#include "src/vm-state-inl.h"
+
+namespace v8 {
+namespace internal {
+
+RUNTIME_FUNCTION(Runtime_CompileLazy) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+#ifdef DEBUG
+  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
+    PrintF("[unoptimized: ");
+    function->PrintName();
+    PrintF("]\n");
+  }
+#endif
+
+  // Compile the target function.
+  DCHECK(function->shared()->allows_lazy_compilation());
+
+  Handle<Code> code;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, code,
+                                     Compiler::GetLazyCode(function));
+  DCHECK(code->kind() == Code::FUNCTION ||
+         code->kind() == Code::OPTIMIZED_FUNCTION);
+  function->ReplaceCode(*code);
+  return *code;
+}
+
+
+RUNTIME_FUNCTION(Runtime_CompileOptimized) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 2);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+  CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
+  DCHECK(isolate->use_crankshaft());
+
+  Handle<Code> unoptimized(function->shared()->code());
+  if (function->shared()->optimization_disabled() ||
+      isolate->DebuggerHasBreakPoints()) {
+    // If the function is not optimizable or debugger is active continue
+    // using the code from the full compiler.
+    if (FLAG_trace_opt) {
+      PrintF("[failed to optimize ");
+      function->PrintName();
+      PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
+             function->shared()->optimization_disabled() ? "F" : "T",
+             isolate->DebuggerHasBreakPoints() ? "T" : "F");
+    }
+    function->ReplaceCode(*unoptimized);
+    return function->code();
+  }
+
+  Compiler::ConcurrencyMode mode =
+      concurrent ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT;
+  Handle<Code> code;
+  if (Compiler::GetOptimizedCode(function, unoptimized, mode).ToHandle(&code)) {
+    function->ReplaceCode(*code);
+  } else {
+    function->ReplaceCode(function->shared()->code());
+  }
+
+  DCHECK(function->code()->kind() == Code::FUNCTION ||
+         function->code()->kind() == Code::OPTIMIZED_FUNCTION ||
+         function->IsInOptimizationQueue());
+  return function->code();
+}
+
+
+RUNTIME_FUNCTION(Runtime_NotifyStubFailure) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 0);
+  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
+  DCHECK(AllowHeapAllocation::IsAllowed());
+  delete deoptimizer;
+  return isolate->heap()->undefined_value();
+}
+
+
+class ActivationsFinder : public ThreadVisitor {
+ public:
+  Code* code_;
+  bool has_code_activations_;
+
+  explicit ActivationsFinder(Code* code)
+      : code_(code), has_code_activations_(false) {}
+
+  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
+    JavaScriptFrameIterator it(isolate, top);
+    VisitFrames(&it);
+  }
+
+  void VisitFrames(JavaScriptFrameIterator* it) {
+    for (; !it->done(); it->Advance()) {
+      JavaScriptFrame* frame = it->frame();
+      if (code_->contains(frame->pc())) has_code_activations_ = true;
+    }
+  }
+};
+
+
+RUNTIME_FUNCTION(Runtime_NotifyDeoptimized) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_SMI_ARG_CHECKED(type_arg, 0);
+  Deoptimizer::BailoutType type =
+      static_cast<Deoptimizer::BailoutType>(type_arg);
+  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
+  DCHECK(AllowHeapAllocation::IsAllowed());
+
+  Handle<JSFunction> function = deoptimizer->function();
+  Handle<Code> optimized_code = deoptimizer->compiled_code();
+
+  DCHECK(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
+  DCHECK(type == deoptimizer->bailout_type());
+
+  // Make sure to materialize objects before causing any allocation.
+  JavaScriptFrameIterator it(isolate);
+  deoptimizer->MaterializeHeapObjects(&it);
+  delete deoptimizer;
+
+  JavaScriptFrame* frame = it.frame();
+  RUNTIME_ASSERT(frame->function()->IsJSFunction());
+  DCHECK(frame->function() == *function);
+
+  // Avoid doing too much work when running with --always-opt and keep
+  // the optimized code around.
+  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
+    return isolate->heap()->undefined_value();
+  }
+
+  // Search for other activations of the same function and code.
+  ActivationsFinder activations_finder(*optimized_code);
+  activations_finder.VisitFrames(&it);
+  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
+
+  if (!activations_finder.has_code_activations_) {
+    if (function->code() == *optimized_code) {
+      if (FLAG_trace_deopt) {
+        PrintF("[removing optimized code for: ");
+        function->PrintName();
+        PrintF("]\n");
+      }
+      function->ReplaceCode(function->shared()->code());
+      // Evict optimized code for this function from the cache so that it
+      // doesn't get used for new closures.
+      function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
+                                                    "notify deoptimized");
+    }
+  } else {
+    // TODO(titzer): we should probably do DeoptimizeCodeList(code)
+    // unconditionally if the code is not already marked for deoptimization.
+    // If there is an index by shared function info, all the better.
+    Deoptimizer::DeoptimizeFunction(*function);
+  }
+
+  return isolate->heap()->undefined_value();
+}
+
+
+static bool IsSuitableForOnStackReplacement(Isolate* isolate,
+                                            Handle<JSFunction> function,
+                                            Handle<Code> current_code) {
+  // Keep track of whether we've succeeded in optimizing.
+  if (!current_code->optimizable()) return false;
+  // If we are trying to do OSR when there are already optimized
+  // activations of the function, it means (a) the function is directly or
+  // indirectly recursive and (b) an optimized invocation has been
+  // deoptimized so that we are currently in an unoptimized activation.
+  // Check for optimized activations of this function.
+  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
+    JavaScriptFrame* frame = it.frame();
+    if (frame->is_optimized() && frame->function() == *function) return false;
+  }
+
+  return true;
+}
+
+
+RUNTIME_FUNCTION(Runtime_CompileForOnStackReplacement) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+  Handle<Code> caller_code(function->shared()->code());
+
+  // We're not prepared to handle a function with arguments object.
+  DCHECK(!function->shared()->uses_arguments());
+
+  RUNTIME_ASSERT(FLAG_use_osr);
+
+  // Passing the PC in the javascript frame from the caller directly is
+  // not GC safe, so we walk the stack to get it.
+  JavaScriptFrameIterator it(isolate);
+  JavaScriptFrame* frame = it.frame();
+  if (!caller_code->contains(frame->pc())) {
+    // Code on the stack may not be the code object referenced by the shared
+    // function info.  It may have been replaced to include deoptimization data.
+    caller_code = Handle<Code>(frame->LookupCode());
+  }
+
+  uint32_t pc_offset =
+      static_cast<uint32_t>(frame->pc() - caller_code->instruction_start());
+
+#ifdef DEBUG
+  DCHECK_EQ(frame->function(), *function);
+  DCHECK_EQ(frame->LookupCode(), *caller_code);
+  DCHECK(caller_code->contains(frame->pc()));
+#endif  // DEBUG
+
+
+  BailoutId ast_id = caller_code->TranslatePcOffsetToAstId(pc_offset);
+  DCHECK(!ast_id.IsNone());
+
+  Compiler::ConcurrencyMode mode =
+      isolate->concurrent_osr_enabled() &&
+              (function->shared()->ast_node_count() > 512)
+          ? Compiler::CONCURRENT
+          : Compiler::NOT_CONCURRENT;
+  Handle<Code> result = Handle<Code>::null();
+
+  OptimizedCompileJob* job = NULL;
+  if (mode == Compiler::CONCURRENT) {
+    // Gate the OSR entry with a stack check.
+    BackEdgeTable::AddStackCheck(caller_code, pc_offset);
+    // Poll already queued compilation jobs.
+    OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
+    if (thread->IsQueuedForOSR(function, ast_id)) {
+      if (FLAG_trace_osr) {
+        PrintF("[OSR - Still waiting for queued: ");
+        function->PrintName();
+        PrintF(" at AST id %d]\n", ast_id.ToInt());
+      }
+      return NULL;
+    }
+
+    job = thread->FindReadyOSRCandidate(function, ast_id);
+  }
+
+  if (job != NULL) {
+    if (FLAG_trace_osr) {
+      PrintF("[OSR - Found ready: ");
+      function->PrintName();
+      PrintF(" at AST id %d]\n", ast_id.ToInt());
+    }
+    result = Compiler::GetConcurrentlyOptimizedCode(job);
+  } else if (IsSuitableForOnStackReplacement(isolate, function, caller_code)) {
+    if (FLAG_trace_osr) {
+      PrintF("[OSR - Compiling: ");
+      function->PrintName();
+      PrintF(" at AST id %d]\n", ast_id.ToInt());
+    }
+    MaybeHandle<Code> maybe_result =
+        Compiler::GetOptimizedCode(function, caller_code, mode, ast_id);
+    if (maybe_result.ToHandle(&result) &&
+        result.is_identical_to(isolate->builtins()->InOptimizationQueue())) {
+      // Optimization is queued.  Return to check later.
+      return NULL;
+    }
+  }
+
+  // Revert the patched back edge table, regardless of whether OSR succeeds.
+  BackEdgeTable::Revert(isolate, *caller_code);
+
+  // Check whether we ended up with usable optimized code.
+  if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
+    DeoptimizationInputData* data =
+        DeoptimizationInputData::cast(result->deoptimization_data());
+
+    if (data->OsrPcOffset()->value() >= 0) {
+      DCHECK(BailoutId(data->OsrAstId()->value()) == ast_id);
+      if (FLAG_trace_osr) {
+        PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
+               ast_id.ToInt(), data->OsrPcOffset()->value());
+      }
+      // TODO(titzer): this is a massive hack to make the deopt counts
+      // match. Fix heuristics for reenabling optimizations!
+      function->shared()->increment_deopt_count();
+
+      // TODO(titzer): Do not install code into the function.
+      function->ReplaceCode(*result);
+      return *result;
+    }
+  }
+
+  // Failed.
+  if (FLAG_trace_osr) {
+    PrintF("[OSR - Failed: ");
+    function->PrintName();
+    PrintF(" at AST id %d]\n", ast_id.ToInt());
+  }
+
+  if (!function->IsOptimized()) {
+    function->ReplaceCode(function->shared()->code());
+  }
+  return NULL;
+}
+
+
+RUNTIME_FUNCTION(Runtime_TryInstallOptimizedCode) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+
+  // First check if this is a real stack overflow.
+  StackLimitCheck check(isolate);
+  if (check.JsHasOverflowed()) {
+    SealHandleScope shs(isolate);
+    return isolate->StackOverflow();
+  }
+
+  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
+  return (function->IsOptimized()) ? function->code()
+                                   : function->shared()->code();
+}
+
+
+bool CodeGenerationFromStringsAllowed(Isolate* isolate,
+                                      Handle<Context> context) {
+  DCHECK(context->allow_code_gen_from_strings()->IsFalse());
+  // Check with callback if set.
+  AllowCodeGenerationFromStringsCallback callback =
+      isolate->allow_code_gen_callback();
+  if (callback == NULL) {
+    // No callback set and code generation disallowed.
+    return false;
+  } else {
+    // Callback set. Let it decide if code generation is allowed.
+    VMState<EXTERNAL> state(isolate);
+    return callback(v8::Utils::ToLocal(context));
+  }
+}
+
+
+RUNTIME_FUNCTION(Runtime_CompileString) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 3);
+  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
+  CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
+  CONVERT_SMI_ARG_CHECKED(source_offset, 2);
+
+  // Extract native context.
+  Handle<Context> context(isolate->native_context());
+
+  // Check if native context allows code generation from
+  // strings. Throw an exception if it doesn't.
+  if (context->allow_code_gen_from_strings()->IsFalse() &&
+      !CodeGenerationFromStringsAllowed(isolate, context)) {
+    Handle<Object> error_message =
+        context->ErrorMessageForCodeGenerationFromStrings();
+    THROW_NEW_ERROR_RETURN_FAILURE(
+        isolate, NewEvalError("code_gen_from_strings",
+                              HandleVector<Object>(&error_message, 1)));
+  }
+
+  // Compile source string in the native context.
+  ParseRestriction restriction = function_literal_only
+                                     ? ONLY_SINGLE_FUNCTION_LITERAL
+                                     : NO_PARSE_RESTRICTION;
+  Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
+  Handle<JSFunction> fun;
+  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+      isolate, fun,
+      Compiler::GetFunctionFromEval(source, outer_info, context, SLOPPY,
+                                    restriction, RelocInfo::kNoPosition));
+  if (function_literal_only) {
+    // The actual body is wrapped, which shifts line numbers.
+    Handle<Script> script(Script::cast(fun->shared()->script()), isolate);
+    if (script->line_offset() == 0) {
+      int line_num = Script::GetLineNumber(script, source_offset);
+      script->set_line_offset(Smi::FromInt(-line_num));
+    }
+  }
+  return *fun;
+}
+
+
+static ObjectPair CompileGlobalEval(Isolate* isolate, Handle<String> source,
+                                    Handle<SharedFunctionInfo> outer_info,
+                                    Handle<Object> receiver,
+                                    StrictMode strict_mode,
+                                    int scope_position) {
+  Handle<Context> context = Handle<Context>(isolate->context());
+  Handle<Context> native_context = Handle<Context>(context->native_context());
+
+  // Check if native context allows code generation from
+  // strings. Throw an exception if it doesn't.
+  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
+      !CodeGenerationFromStringsAllowed(isolate, native_context)) {
+    Handle<Object> error_message =
+        native_context->ErrorMessageForCodeGenerationFromStrings();
+    Handle<Object> error;
+    MaybeHandle<Object> maybe_error = isolate->factory()->NewEvalError(
+        "code_gen_from_strings", HandleVector<Object>(&error_message, 1));
+    if (maybe_error.ToHandle(&error)) isolate->Throw(*error);
+    return MakePair(isolate->heap()->exception(), NULL);
+  }
+
+  // Deal with a normal eval call with a string argument. Compile it
+  // and return the compiled function bound in the local context.
+  static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
+  Handle<JSFunction> compiled;
+  ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+      isolate, compiled,
+      Compiler::GetFunctionFromEval(source, outer_info, context, strict_mode,
+                                    restriction, scope_position),
+      MakePair(isolate->heap()->exception(), NULL));
+  return MakePair(*compiled, *receiver);
+}
+
+
+RUNTIME_FUNCTION_RETURN_PAIR(Runtime_ResolvePossiblyDirectEval) {
+  HandleScope scope(isolate);
+  DCHECK(args.length() == 6);
+
+  Handle<Object> callee = args.at<Object>(0);
+
+  // If "eval" didn't refer to the original GlobalEval, it's not a
+  // direct call to eval.
+  // (And even if it is, but the first argument isn't a string, just let
+  // execution default to an indirect call to eval, which will also return
+  // the first argument without doing anything).
+  if (*callee != isolate->native_context()->global_eval_fun() ||
+      !args[1]->IsString()) {
+    return MakePair(*callee, isolate->heap()->undefined_value());
+  }
+
+  DCHECK(args[4]->IsSmi());
+  DCHECK(args.smi_at(4) == SLOPPY || args.smi_at(4) == STRICT);
+  StrictMode strict_mode = static_cast<StrictMode>(args.smi_at(4));
+  DCHECK(args[5]->IsSmi());
+  Handle<SharedFunctionInfo> outer_info(args.at<JSFunction>(2)->shared(),
+                                        isolate);
+  return CompileGlobalEval(isolate, args.at<String>(1), outer_info,
+                           args.at<Object>(3), strict_mode, args.smi_at(5));
+}
+}
+}  // namespace v8::internal