1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/builtins/builtins-utils.h"
662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/builtins/builtins.h"
762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-factory.h"
862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-stub-assembler.h"
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/compiler.h"
1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/conversions.h"
1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/counters.h"
1262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/lookup.h"
1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/string-builder.h"
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
16f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace v8 {
17f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace internal {
18f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
19f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace {
20f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.1.1.1 CreateDynamicFunction
22f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochMaybeHandle<Object> CreateDynamicFunction(Isolate* isolate,
23f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                          BuiltinArguments args,
24f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                          const char* token) {
25f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Compute number of arguments, ignoring the receiver.
26f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_LE(1, args.length());
27f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int const argc = args.length() - 1;
28f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
29c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<JSFunction> target = args.target();
30f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
31f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
32f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!Builtins::AllowDynamicFunction(isolate, target, target_global_proxy)) {
33f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    isolate->CountUsage(v8::Isolate::kFunctionConstructorReturnedUndefined);
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return isolate->factory()->undefined_value();
35f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
36f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
37f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Build the source string.
38f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<String> source;
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int parameters_end_pos = kNoSourcePosition;
40f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
41f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    IncrementalStringBuilder builder(isolate);
42f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    builder.AppendCharacter('(');
43f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    builder.AppendCString(token);
4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (FLAG_harmony_function_tostring) {
4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      builder.AppendCString(" anonymous(");
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } else {
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      builder.AppendCharacter('(');
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
49f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    bool parenthesis_in_arg_string = false;
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (argc > 1) {
51f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      for (int i = 1; i < argc; ++i) {
52f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        if (i > 1) builder.AppendCharacter(',');
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Handle<String> param;
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        ASSIGN_RETURN_ON_EXCEPTION(
5562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            isolate, param, Object::ToString(isolate, args.at(i)), Object);
56f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        param = String::Flatten(param);
57f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        builder.AppendString(param);
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        if (!FLAG_harmony_function_tostring) {
5962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          // If the formal parameters string include ) - an illegal
6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          // character - it may make the combined function expression
6162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          // compile. We avoid this problem by checking for this early on.
6262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          DisallowHeapAllocation no_gc;  // Ensure vectors stay valid.
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          String::FlatContent param_content = param->GetFlatContent();
6462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          for (int i = 0, length = param->length(); i < length; ++i) {
6562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if (param_content.Get(i) == ')') {
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              parenthesis_in_arg_string = true;
6762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              break;
6862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            }
69f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          }
70f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        }
71f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
7262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (!FLAG_harmony_function_tostring) {
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // If the formal parameters include an unbalanced block comment, the
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // function must be rejected. Since JavaScript does not allow nested
7562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        // comments we can include a trailing block comment to catch this.
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        builder.AppendCString("\n/*``*/");
7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
7862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
7962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (FLAG_harmony_function_tostring) {
8062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      builder.AppendCharacter('\n');
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      parameters_end_pos = builder.Length();
82f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
83f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    builder.AppendCString(") {\n");
84f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (argc > 0) {
85f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<String> body;
86f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ASSIGN_RETURN_ON_EXCEPTION(
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          isolate, body, Object::ToString(isolate, args.at(argc)), Object);
88f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      builder.AppendString(body);
89f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
90f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    builder.AppendCString("\n})");
91f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), Object);
92f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
93f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // The SyntaxError must be thrown after all the (observable) ToString
94f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // conversions are done.
95f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (parenthesis_in_arg_string) {
96f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      THROW_NEW_ERROR(isolate,
97f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                      NewSyntaxError(MessageTemplate::kParenthesisInArgString),
98f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                      Object);
99f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
100f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
101f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
102f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Compile the string in the constructor and not a helper so that errors to
103f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // come from here.
104f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<JSFunction> function;
105f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_ON_EXCEPTION(
10762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, function,
10862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Compiler::GetFunctionFromString(
10962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            handle(target->native_context(), isolate), source,
11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            ONLY_SINGLE_FUNCTION_LITERAL, parameters_end_pos),
11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Object);
112f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<Object> result;
113f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ASSIGN_RETURN_ON_EXCEPTION(
114f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, result,
115f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
116f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Object);
117f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    function = Handle<JSFunction>::cast(result);
118f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    function->shared()->set_name_should_print_as_anonymous(true);
119f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
120f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
121f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If new.target is equal to target then the function created
122f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // is already correctly setup and nothing else should be done
123f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // here. But if new.target is not equal to target then we are
124f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // have a Function builtin subclassing case and therefore the
125f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // function has wrong initial map. To fix that we create a new
126f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // function object with correct initial map.
127f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> unchecked_new_target = args.new_target();
128f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!unchecked_new_target->IsUndefined(isolate) &&
129f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      !unchecked_new_target.is_identical_to(target)) {
130f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<JSReceiver> new_target =
131f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        Handle<JSReceiver>::cast(unchecked_new_target);
132f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<Map> initial_map;
133f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ASSIGN_RETURN_ON_EXCEPTION(
134f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, initial_map,
135f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        JSFunction::GetDerivedMap(isolate, target, new_target), Object);
136f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
137f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
138f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<Map> map = Map::AsLanguageMode(
139f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        initial_map, shared_info->language_mode(), shared_info->kind());
140f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
141f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<Context> context(function->context(), isolate);
142f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
143f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        map, shared_info, context, NOT_TENURED);
144f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
145f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return function;
146f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
147f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
148f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace
149f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
150f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
151f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(FunctionConstructor) {
152f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
153f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> result;
154f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
155f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, result, CreateDynamicFunction(isolate, args, "function"));
156f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *result;
157f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
158f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
159f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
160f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(GeneratorFunctionConstructor) {
161f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
162f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  RETURN_RESULT_OR_FAILURE(isolate,
163f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                           CreateDynamicFunction(isolate, args, "function*"));
164f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
165f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
166f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(AsyncFunctionConstructor) {
167f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
168f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> maybe_func;
169f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
170f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, maybe_func,
171f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      CreateDynamicFunction(isolate, args, "async function"));
172f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!maybe_func->IsJSFunction()) return *maybe_func;
173f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
174f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Do not lazily compute eval position for AsyncFunction, as they may not be
175f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // determined after the function is resumed.
176f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<JSFunction> func = Handle<JSFunction>::cast(maybe_func);
177f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Script> script = handle(Script::cast(func->shared()->script()));
178f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int position = script->GetEvalPosition();
179f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  USE(position);
180f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
181f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *func;
182f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
183f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
184f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace {
185f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
186f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochObject* DoFunctionBind(Isolate* isolate, BuiltinArguments args) {
187f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
188f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_LE(1, args.length());
189f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!args.receiver()->IsCallable()) {
190f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
191f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewTypeError(MessageTemplate::kFunctionBind));
192f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
193f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
194f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Allocate the bound function with the given {this_arg} and {args}.
195f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<JSReceiver> target = args.at<JSReceiver>(0);
196f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> this_arg = isolate->factory()->undefined_value();
197f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
198f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (args.length() > 1) {
19962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    this_arg = args.at(1);
200f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    for (int i = 2; i < args.length(); ++i) {
20162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      argv[i - 2] = args.at(i);
202f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
203f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
204f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<JSBoundFunction> function;
205f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
206f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, function,
207f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
208f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
209f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  LookupIterator length_lookup(target, isolate->factory()->length_string(),
210f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               target, LookupIterator::OWN);
211f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Setup the "length" property based on the "length" of the {target}.
212f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If the targets length is the default JSFunction accessor, we can keep the
213f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // accessor that's installed by default on the JSBoundFunction. It lazily
214f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // computes the value from the underlying internal length.
215f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!target->IsJSFunction() ||
216f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      length_lookup.state() != LookupIterator::ACCESSOR ||
217f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      !length_lookup.GetAccessors()->IsAccessorInfo()) {
218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> length(Smi::kZero, isolate);
219f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Maybe<PropertyAttributes> attributes =
220f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        JSReceiver::GetPropertyAttributes(&length_lookup);
221f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (!attributes.IsJust()) return isolate->heap()->exception();
222f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (attributes.FromJust() != ABSENT) {
223f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      Handle<Object> target_length;
224f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_length,
225f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                         Object::GetProperty(&length_lookup));
226f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      if (target_length->IsNumber()) {
227f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        length = isolate->factory()->NewNumber(std::max(
228f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch            0.0, DoubleToInteger(target_length->Number()) - argv.length()));
229f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      }
230f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
231f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    LookupIterator it(function, isolate->factory()->length_string(), function);
232f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
233f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    RETURN_FAILURE_ON_EXCEPTION(isolate,
234f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                JSObject::DefineOwnPropertyIgnoreAttributes(
235f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    &it, length, it.property_attributes()));
236f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
237f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
238f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Setup the "name" property based on the "name" of the {target}.
239f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If the targets name is the default JSFunction accessor, we can keep the
240f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // accessor that's installed by default on the JSBoundFunction. It lazily
241f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // computes the value from the underlying internal name.
242f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  LookupIterator name_lookup(target, isolate->factory()->name_string(), target,
243f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             LookupIterator::OWN);
244f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!target->IsJSFunction() ||
245f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      name_lookup.state() != LookupIterator::ACCESSOR ||
246f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      !name_lookup.GetAccessors()->IsAccessorInfo()) {
247f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<Object> target_name;
248f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target_name,
249f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                       Object::GetProperty(&name_lookup));
250f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    Handle<String> name;
251f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (target_name->IsString()) {
252f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
253f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate, name,
254f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          Name::ToFunctionName(Handle<String>::cast(target_name)));
255f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
256f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch          isolate, name, isolate->factory()->NewConsString(
257f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                             isolate->factory()->bound__string(), name));
258f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    } else {
259f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      name = isolate->factory()->bound__string();
260f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
261f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    LookupIterator it(function, isolate->factory()->name_string());
262f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_EQ(LookupIterator::ACCESSOR, it.state());
263f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    RETURN_FAILURE_ON_EXCEPTION(isolate,
264f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                JSObject::DefineOwnPropertyIgnoreAttributes(
265f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                    &it, name, it.property_attributes()));
266f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
267f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *function;
268f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
269f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
270f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace
271f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(FunctionPrototypeBind) { return DoFunctionBind(isolate, args); }
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid Builtins::Generate_FastFunctionPrototypeBind(
27662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    compiler::CodeAssemblerState* state) {
27762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  using compiler::Node;
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  typedef CodeStubAssembler::Label Label;
27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  typedef CodeStubAssembler::Variable Variable;
28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CodeStubAssembler assembler(state);
28262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label slow(&assembler);
28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* argc = assembler.Parameter(BuiltinDescriptor::kArgumentsCount);
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = assembler.Parameter(BuiltinDescriptor::kContext);
28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* new_target = assembler.Parameter(BuiltinDescriptor::kNewTarget);
28762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CodeStubArguments args(&assembler, assembler.ChangeInt32ToIntPtr(argc));
28962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check that receiver has instance type of JS_FUNCTION_TYPE
29162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver = args.GetReceiver();
29262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.TaggedIsSmi(receiver), &slow);
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
29462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver_map = assembler.LoadMap(receiver);
29562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* instance_type = assembler.LoadMapInstanceType(receiver_map);
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler.Word32NotEqual(instance_type,
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               assembler.Int32Constant(JS_FUNCTION_TYPE)),
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      &slow);
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Disallow binding of slow-mode functions. We need to figure out whether the
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // length and name property are in the original state.
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Disallow binding of slow-mode functions");
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.IsDictionaryMap(receiver_map), &slow);
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check whether the length and name properties are still present as
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // AccessorInfo objects. In that case, their value can be recomputed even if
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // the actual value on the object changes.
30962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Check descriptor array length");
31062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* descriptors = assembler.LoadMapDescriptors(receiver_map);
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* descriptors_length = assembler.LoadFixedArrayBaseLength(descriptors);
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.SmiLessThanOrEqual(descriptors_length,
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                assembler.SmiConstant(1)),
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   &slow);
31562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Check whether the length and name properties are still present as
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // AccessorInfo objects. In that case, their value can be recomputed even if
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // the actual value on the object changes.
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Check name and length properties");
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const int length_index = JSFunction::kLengthDescriptorIndex;
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* maybe_length = assembler.LoadFixedArrayElement(
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      descriptors, DescriptorArray::ToKeyIndex(length_index));
32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler.WordNotEqual(maybe_length,
32562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             assembler.LoadRoot(Heap::klength_stringRootIndex)),
32662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      &slow);
32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* maybe_length_accessor = assembler.LoadFixedArrayElement(
32962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      descriptors, DescriptorArray::ToValueIndex(length_index));
33062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.TaggedIsSmi(maybe_length_accessor), &slow);
33162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* length_value_map = assembler.LoadMap(maybe_length_accessor);
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIfNot(assembler.IsAccessorInfoMap(length_value_map), &slow);
33362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const int name_index = JSFunction::kNameDescriptorIndex;
33562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* maybe_name = assembler.LoadFixedArrayElement(
33662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      descriptors, DescriptorArray::ToKeyIndex(name_index));
33762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(
33862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler.WordNotEqual(maybe_name,
33962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             assembler.LoadRoot(Heap::kname_stringRootIndex)),
34062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      &slow);
34162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* maybe_name_accessor = assembler.LoadFixedArrayElement(
34362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      descriptors, DescriptorArray::ToValueIndex(name_index));
34462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.TaggedIsSmi(maybe_name_accessor), &slow);
34562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* name_value_map = assembler.LoadMap(maybe_name_accessor);
34662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIfNot(assembler.IsAccessorInfoMap(name_value_map), &slow);
34762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
34862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Choose the right bound function map based on whether the target is
34962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // constructable.
35062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Choose the right bound function map");
35162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable bound_function_map(&assembler, MachineRepresentation::kTagged);
35262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label with_constructor(&assembler);
35362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CodeStubAssembler::VariableList vars({&bound_function_map}, assembler.zone());
35462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* native_context = assembler.LoadNativeContext(context);
35562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
35662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label map_done(&assembler, vars);
35762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* bit_field = assembler.LoadMapBitField(receiver_map);
35862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int mask = static_cast<int>(1 << Map::kIsConstructor);
35962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.IsSetWord32(bit_field, mask), &with_constructor);
36062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
36162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bound_function_map.Bind(assembler.LoadContextElement(
36262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      native_context, Context::BOUND_FUNCTION_WITHOUT_CONSTRUCTOR_MAP_INDEX));
36362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Goto(&map_done);
36462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
36562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&with_constructor);
36662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bound_function_map.Bind(assembler.LoadContextElement(
36762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      native_context, Context::BOUND_FUNCTION_WITH_CONSTRUCTOR_MAP_INDEX));
36862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Goto(&map_done);
36962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
37062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&map_done);
37162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
37262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Verify that __proto__ matches that of a the target bound function.
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Verify that __proto__ matches target bound function");
37462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* prototype = assembler.LoadMapPrototype(receiver_map);
37562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* expected_prototype =
37662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler.LoadMapPrototype(bound_function_map.value());
37762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.WordNotEqual(prototype, expected_prototype),
37862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   &slow);
37962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
38062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Allocate the arguments array.
38162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Allocate the arguments array");
38262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable argument_array(&assembler, MachineRepresentation::kTagged);
38362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label empty_arguments(&assembler);
38462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label arguments_done(&assembler, &argument_array);
38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(
38662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler.Uint32LessThanOrEqual(argc, assembler.Int32Constant(1)),
38762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      &empty_arguments);
38862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* elements_length = assembler.ChangeUint32ToWord(
38962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler.Int32Sub(argc, assembler.Int32Constant(1)));
39062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* elements = assembler.AllocateFixedArray(FAST_ELEMENTS, elements_length);
39162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable index(&assembler, MachineType::PointerRepresentation());
39262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  index.Bind(assembler.IntPtrConstant(0));
39362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CodeStubAssembler::VariableList foreach_vars({&index}, assembler.zone());
39462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args.ForEach(foreach_vars,
39562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               [&assembler, elements, &index](compiler::Node* arg) {
39662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 assembler.StoreFixedArrayElement(elements, index.value(), arg);
39762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 assembler.Increment(index);
39862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               },
39962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               assembler.IntPtrConstant(1));
40062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  argument_array.Bind(elements);
40162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Goto(&arguments_done);
40262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&empty_arguments);
40462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  argument_array.Bind(assembler.EmptyFixedArrayConstant());
40562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Goto(&arguments_done);
40662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&arguments_done);
40862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
40962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Determine bound receiver.
41062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Determine bound receiver");
41162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable bound_receiver(&assembler, MachineRepresentation::kTagged);
41262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label has_receiver(&assembler);
41362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label receiver_done(&assembler, &bound_receiver);
41462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.GotoIf(assembler.Word32NotEqual(argc, assembler.Int32Constant(0)),
41562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   &has_receiver);
41662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bound_receiver.Bind(assembler.UndefinedConstant());
41762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Goto(&receiver_done);
41862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
41962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&has_receiver);
42062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  bound_receiver.Bind(args.AtIndex(0));
42162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Goto(&receiver_done);
42262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&receiver_done);
42462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
42562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Allocate the resulting bound function.
42662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Comment("Allocate the resulting bound function");
42762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* bound_function = assembler.Allocate(JSBoundFunction::kSize);
42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.StoreMapNoWriteBarrier(bound_function, bound_function_map.value());
42962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.StoreObjectFieldNoWriteBarrier(
43062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bound_function, JSBoundFunction::kBoundTargetFunctionOffset, receiver);
43162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.StoreObjectFieldNoWriteBarrier(bound_function,
43262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                           JSBoundFunction::kBoundThisOffset,
43362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                           bound_receiver.value());
43462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.StoreObjectFieldNoWriteBarrier(
43562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bound_function, JSBoundFunction::kBoundArgumentsOffset,
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      argument_array.value());
43762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* empty_fixed_array = assembler.EmptyFixedArrayConstant();
43862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.StoreObjectFieldNoWriteBarrier(
43962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bound_function, JSObject::kPropertiesOffset, empty_fixed_array);
44062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.StoreObjectFieldNoWriteBarrier(
44162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      bound_function, JSObject::kElementsOffset, empty_fixed_array);
44262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
44362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args.PopAndReturn(bound_function);
44462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Bind(&slow);
44562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
44662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* target = assembler.LoadFromFrame(
44762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      StandardFrameConstants::kFunctionOffset, MachineType::TaggedPointer());
44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.TailCallStub(
44962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      CodeFactory::FunctionPrototypeBind(assembler.isolate()), context, target,
45062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      new_target, argc);
45162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
45262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// TODO(verwaest): This is a temporary helper until the FastFunctionBind stub
454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// can tailcall to the builtin directly.
455f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochRUNTIME_FUNCTION(Runtime_FunctionBind) {
456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DCHECK_EQ(2, args.length());
457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Arguments* incoming = reinterpret_cast<Arguments*>(args[0]);
458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Rewrap the arguments as builtins arguments.
459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int argc = incoming->length() + BuiltinArguments::kNumExtraArgsWithReceiver;
460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  BuiltinArguments caller_args(argc, incoming->arguments() + 1);
461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return DoFunctionBind(isolate, caller_args);
462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.3.5 Function.prototype.toString ( )
465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(FunctionPrototypeToString) {
466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> receiver = args.receiver();
468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (receiver->IsJSBoundFunction()) {
469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  } else if (receiver->IsJSFunction()) {
471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  THROW_NEW_ERROR_RETURN_FAILURE(
474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, NewTypeError(MessageTemplate::kNotGeneric,
475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                            isolate->factory()->NewStringFromAsciiChecked(
476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                "Function.prototype.toString")));
477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 19.2.3.6 Function.prototype [ @@hasInstance ] ( V )
480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochvoid Builtins::Generate_FunctionPrototypeHasInstance(
48162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    compiler::CodeAssemblerState* state) {
482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  using compiler::Node;
48362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CodeStubAssembler assembler(state);
484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
48562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* f = assembler.Parameter(0);
48662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* v = assembler.Parameter(1);
48762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = assembler.Parameter(4);
48862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* result = assembler.OrdinaryHasInstance(context, f, v);
48962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  assembler.Return(result);
490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
492f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace internal
493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace v8
494