13b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
23b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
33b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// found in the LICENSE file.
43b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
53b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#include "src/interpreter/interpreter-intrinsics.h"
63b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/code-factory.h"
862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochnamespace v8 {
113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochnamespace internal {
123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochnamespace interpreter {
133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochusing compiler::Node;
153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define __ assembler_->
173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochIntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
1913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    : isolate_(assembler->isolate()),
2013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      zone_(assembler->zone()),
2113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      assembler_(assembler) {}
223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static
243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochbool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  switch (function_id) {
263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define SUPPORTED(name, lower_case, count) case Runtime::kInline##name:
273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    INTRINSICS_LIST(SUPPORTED)
283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return true;
293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#undef SUPPORTED
303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    default:
313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return false;
323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static
3613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochIntrinsicsHelper::IntrinsicId IntrinsicsHelper::FromRuntimeId(
3713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Runtime::FunctionId function_id) {
3813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  switch (function_id) {
3913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define TO_RUNTIME_ID(name, lower_case, count) \
4013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  case Runtime::kInline##name:                 \
4113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return IntrinsicId::k##name;
4213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INTRINSICS_LIST(TO_RUNTIME_ID)
4313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#undef TO_RUNTIME_ID
4413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    default:
4513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      UNREACHABLE();
4613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return static_cast<IntrinsicsHelper::IntrinsicId>(-1);
4713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
4813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
4913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
5013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch// static
5113e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochRuntime::FunctionId IntrinsicsHelper::ToRuntimeId(
5213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    IntrinsicsHelper::IntrinsicId intrinsic_id) {
5313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  switch (intrinsic_id) {
5413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#define TO_INTRINSIC_ID(name, lower_case, count) \
5513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  case IntrinsicId::k##name:                     \
5613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return Runtime::kInline##name;
5713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    INTRINSICS_LIST(TO_INTRINSIC_ID)
5813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#undef TO_INTRINSIC_ID
5913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    default:
6013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      UNREACHABLE();
6113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return static_cast<Runtime::FunctionId>(-1);
6213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
6313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
6413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben MurdochNode* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        Node* first_arg_reg, Node* arg_count) {
673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Label abort(assembler_), end(assembler_);
683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Variable result(assembler_,
693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                        MachineRepresentation::kTagged);
703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define MAKE_LABEL(name, lower_case, count) \
723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Label lower_case(assembler_);
733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  INTRINSICS_LIST(MAKE_LABEL)
743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#undef MAKE_LABEL
753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define LABEL_POINTER(name, lower_case, count) &lower_case,
773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)};
783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#undef LABEL_POINTER
793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define CASE(name, lower_case, count) \
8113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static_cast<int32_t>(IntrinsicId::k##name),
823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int32_t cases[] = {INTRINSICS_LIST(CASE)};
833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#undef CASE
843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Switch(function_id, &abort, cases, labels, arraysize(cases));
863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#define HANDLE_CASE(name, lower_case, expected_arg_count)   \
873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&lower_case);                                     \
8813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (FLAG_debug_code && expected_arg_count >= 0) {         \
893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    AbortIfArgCountMismatch(expected_arg_count, arg_count); \
903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }                                                         \
9113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  result.Bind(name(first_arg_reg, arg_count, context));     \
923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Goto(&end);
933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  INTRINSICS_LIST(HANDLE_CASE)
943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#undef HANDLE_CASE
953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&abort);
9713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
9813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
9913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    result.Bind(__ UndefinedConstant());
10013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
10113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
1023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&end);
1043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return result.value();
1053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
107f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochNode* IntrinsicsHelper::CompareInstanceType(Node* object, int type,
1083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                            InstanceTypeCompareMode mode) {
109f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Node* instance_type = __ LoadInstanceType(object);
1103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  if (mode == kInstanceTypeEqual) {
11213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return __ Word32Equal(instance_type, __ Int32Constant(type));
1133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  } else {
1143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(mode == kInstanceTypeGreaterThanOrEqual);
11513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
1163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
11713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
1183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
11913e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IsInstanceType(Node* input, int type) {
12013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InterpreterAssembler::Variable return_value(assembler_,
12113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                              MachineRepresentation::kTagged);
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(ishell): Use Select here.
12313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_),
12413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return_false(assembler_), end(assembler_);
12513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* arg = __ LoadRegister(input);
126c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ GotoIf(__ TaggedIsSmi(arg), &return_false);
1273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
12813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual);
12913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Branch(condition, &return_true, &return_false);
13013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
13113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Bind(&return_true);
13213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
13313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return_value.Bind(__ BooleanConstant(true));
13413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
13513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
13613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
13713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Bind(&return_false);
13813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
13913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return_value.Bind(__ BooleanConstant(false));
14013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
14113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
1423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&end);
1443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return return_value.value();
1453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
14713e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count,
14813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                     Node* context) {
14962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(ishell): Use Select here.
15062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(ishell): Use CSA::IsJSReceiverInstanceType here.
1513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Variable return_value(assembler_,
1523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                              MachineRepresentation::kTagged);
15313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InterpreterAssembler::Label return_true(assembler_), return_false(assembler_),
1543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      end(assembler_);
1553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
15613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* arg = __ LoadRegister(input);
157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ GotoIf(__ TaggedIsSmi(arg), &return_false);
1583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
16013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* condition = CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
16113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                        kInstanceTypeGreaterThanOrEqual);
16213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Branch(condition, &return_true, &return_false);
16313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
16413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Bind(&return_true);
16513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
16613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return_value.Bind(__ BooleanConstant(true));
16713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
16813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
16913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
17013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Bind(&return_false);
17113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
17213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return_value.Bind(__ BooleanConstant(false));
17313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
17413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
1753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&end);
1773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return return_value.value();
1783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
1793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IsArray(Node* input, Node* arg_count, Node* context) {
18113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IsInstanceType(input, JS_ARRAY_TYPE);
18213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
18313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
18413e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IsJSProxy(Node* input, Node* arg_count, Node* context) {
18513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IsInstanceType(input, JS_PROXY_TYPE);
18613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
18713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
18813e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count,
18913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                     Node* context) {
19013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
19113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
19213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
19313e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) {
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(ishell): Use SelectBooleanConstant here.
1953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Variable return_value(assembler_,
1963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                              MachineRepresentation::kTagged);
1973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
1983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      end(assembler_);
19913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* arg = __ LoadRegister(input);
2013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  __ Branch(__ TaggedIsSmi(arg), &if_smi, &if_not_smi);
2033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&if_smi);
20413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
20513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return_value.Bind(__ BooleanConstant(true));
20613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
20713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
2083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&if_not_smi);
21013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  {
21113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return_value.Bind(__ BooleanConstant(false));
21213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&end);
21313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
2143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&end);
2163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  return return_value.value();
2173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
2183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
21913e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::IntrinsicAsStubCall(Node* args_reg, Node* context,
22013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                            Callable const& callable) {
22113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int param_count = callable.descriptor().GetParameterCount();
22262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int input_count = param_count + 2;  // +2 for target and context
22362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node** args = zone()->NewArray<Node*>(input_count);
22462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int index = 0;
22562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args[index++] = __ HeapConstant(callable.code());
22613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  for (int i = 0; i < param_count; i++) {
22762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    args[index++] = __ LoadRegister(args_reg);
22813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    args_reg = __ NextRegister(args_reg);
22913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  args[index++] = context;
23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ CallStubN(callable.descriptor(), 1, input_count, args);
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
23313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* IntrinsicsHelper::CreateIterResultObject(Node* input, Node* arg_count,
23562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                               Node* context) {
23662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return IntrinsicAsStubCall(input, context,
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             CodeFactory::CreateIterResultObject(isolate()));
23813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
23913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
24013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::HasProperty(Node* input, Node* arg_count,
24113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                    Node* context) {
24213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context,
24313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                             CodeFactory::HasProperty(isolate()));
24413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
24513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
24613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::SubString(Node* input, Node* arg_count, Node* context) {
24713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::SubString(isolate()));
24813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
24913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
25013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::ToString(Node* input, Node* arg_count, Node* context) {
25113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToString(isolate()));
25213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
25313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
25413e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::ToLength(Node* input, Node* arg_count, Node* context) {
25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToLength(isolate()));
25613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
25713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
25813e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::ToInteger(Node* input, Node* arg_count, Node* context) {
25913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToInteger(isolate()));
26013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
26113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
26213e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::ToNumber(Node* input, Node* arg_count, Node* context) {
26313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToNumber(isolate()));
26413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
26513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
26613e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::ToObject(Node* input, Node* arg_count, Node* context) {
26713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToObject(isolate()));
26813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
26913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
27013e2dadd00298019ed862f2b2fc5068bba730bcfBen MurdochNode* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) {
27113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // First argument register contains the function target.
27213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* function = __ LoadRegister(args_reg);
27313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
27413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Receiver is the second runtime call argument.
27513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* receiver_reg = __ NextRegister(args_reg);
27613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* receiver_arg = __ RegisterLocation(receiver_reg);
27713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
27813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Subtract function and receiver from arg count.
27913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* function_and_receiver_count = __ Int32Constant(2);
28013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* target_args_count = __ Int32Sub(arg_count, function_and_receiver_count);
28113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  if (FLAG_debug_code) {
28313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    InterpreterAssembler::Label arg_count_positive(assembler_);
28413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    Node* comparison = __ Int32LessThan(target_args_count, __ Int32Constant(0));
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    __ GotoIfNot(comparison, &arg_count_positive);
28613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Abort(kWrongArgumentCountForInvokeIntrinsic);
28713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Goto(&arg_count_positive);
28813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    __ Bind(&arg_count_positive);
28913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
29013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Node* result = __ CallJS(function, context, receiver_arg, target_args_count,
29213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                           TailCallMode::kDisallow);
29313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  return result;
29413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch}
29513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* IntrinsicsHelper::ClassOf(Node* args_reg, Node* arg_count,
29713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                Node* context) {
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* value = __ LoadRegister(args_reg);
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return __ ClassOf(value);
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
30162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
30262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochNode* IntrinsicsHelper::CreateAsyncFromSyncIterator(Node* args_reg,
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* arg_count,
30462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                    Node* context) {
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InterpreterAssembler::Label not_receiver(
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      assembler_, InterpreterAssembler::Label::kDeferred);
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  InterpreterAssembler::Label done(assembler_);
30813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InterpreterAssembler::Variable return_value(assembler_,
30913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                              MachineRepresentation::kTagged);
31013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* sync_iterator = __ LoadRegister(args_reg);
31213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIf(__ TaggedIsSmi(sync_iterator), &not_receiver);
31462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ GotoIfNot(__ IsJSReceiver(sync_iterator), &not_receiver);
31513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const native_context = __ LoadNativeContext(context);
31762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const map = __ LoadContextElement(
31862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      native_context, Context::ASYNC_FROM_SYNC_ITERATOR_MAP_INDEX);
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* const iterator = __ AllocateJSObjectFromMap(map);
32013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ StoreObjectFieldNoWriteBarrier(
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      iterator, JSAsyncFromSyncIterator::kSyncIteratorOffset, sync_iterator);
32313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return_value.Bind(iterator);
325f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Goto(&done);
326f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  __ Bind(&not_receiver);
328f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  {
32962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return_value.Bind(
33062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        __ CallRuntime(Runtime::kThrowSymbolIteratorInvalid, context));
331f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    // Unreachable due to the Throw in runtime call.
333f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    __ Goto(&done);
334f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
335f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
336f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  __ Bind(&done);
337f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return return_value.value();
338f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
3403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochvoid IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) {
34113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  InterpreterAssembler::Label match(assembler_);
3423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
34313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ GotoIf(comparison, &match);
3443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Abort(kWrongArgumentCountForInvokeIntrinsic);
34513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  __ Goto(&match);
3463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  __ Bind(&match);
3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}
3483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}  // namespace interpreter
3503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}  // namespace internal
3513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch}  // namespace v8
352