11b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// Copyright 2015 the V8 project authors. All rights reserved.
21b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
31b268ca467c924004286c97bac133db489cf43d0Ben Murdoch// found in the LICENSE file.
41b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
51b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#include "src/interpreter/interpreter-intrinsics.h"
61b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch#include "src/code-factory.h"
821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
91b268ca467c924004286c97bac133db489cf43d0Ben Murdochnamespace v8 {
101b268ca467c924004286c97bac133db489cf43d0Ben Murdochnamespace internal {
111b268ca467c924004286c97bac133db489cf43d0Ben Murdochnamespace interpreter {
121b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
131b268ca467c924004286c97bac133db489cf43d0Ben Murdochusing compiler::Node;
141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
151b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define __ assembler_->
161b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
171b268ca467c924004286c97bac133db489cf43d0Ben MurdochIntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
1821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    : isolate_(assembler->isolate()),
1921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      zone_(assembler->zone()),
2021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      assembler_(assembler) {}
211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
2221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch// static
231b268ca467c924004286c97bac133db489cf43d0Ben Murdochbool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
241b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  switch (function_id) {
251b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define SUPPORTED(name, lower_case, count) case Runtime::kInline##name:
261b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    INTRINSICS_LIST(SUPPORTED)
271b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    return true;
281b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#undef SUPPORTED
291b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    default:
301b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      return false;
311b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  }
321b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}
331b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
3421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch// static
3521efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochIntrinsicsHelper::IntrinsicId IntrinsicsHelper::FromRuntimeId(
3621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    Runtime::FunctionId function_id) {
3721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  switch (function_id) {
3821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch#define TO_RUNTIME_ID(name, lower_case, count) \
3921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  case Runtime::kInline##name:                 \
4021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return IntrinsicId::k##name;
4121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    INTRINSICS_LIST(TO_RUNTIME_ID)
4221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch#undef TO_RUNTIME_ID
4321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    default:
4421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      UNREACHABLE();
4521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return static_cast<IntrinsicsHelper::IntrinsicId>(-1);
4621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
4721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
4821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
4921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch// static
5021efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochRuntime::FunctionId IntrinsicsHelper::ToRuntimeId(
5121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    IntrinsicsHelper::IntrinsicId intrinsic_id) {
5221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  switch (intrinsic_id) {
5321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch#define TO_INTRINSIC_ID(name, lower_case, count) \
5421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  case IntrinsicId::k##name:                     \
5521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return Runtime::kInline##name;
5621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    INTRINSICS_LIST(TO_INTRINSIC_ID)
5721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch#undef TO_INTRINSIC_ID
5821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    default:
5921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      UNREACHABLE();
6021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return static_cast<Runtime::FunctionId>(-1);
6121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
6221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
6321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
641b268ca467c924004286c97bac133db489cf43d0Ben MurdochNode* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
651b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                        Node* first_arg_reg, Node* arg_count) {
661b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Label abort(assembler_), end(assembler_);
671b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Variable result(assembler_,
681b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                        MachineRepresentation::kTagged);
691b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
701b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define MAKE_LABEL(name, lower_case, count) \
711b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Label lower_case(assembler_);
721b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  INTRINSICS_LIST(MAKE_LABEL)
731b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#undef MAKE_LABEL
741b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
751b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define LABEL_POINTER(name, lower_case, count) &lower_case,
761b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Label* labels[] = {INTRINSICS_LIST(LABEL_POINTER)};
771b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#undef LABEL_POINTER
781b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
791b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define CASE(name, lower_case, count) \
8021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  static_cast<int32_t>(IntrinsicId::k##name),
811b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  int32_t cases[] = {INTRINSICS_LIST(CASE)};
821b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#undef CASE
831b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
841b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Switch(function_id, &abort, cases, labels, arraysize(cases));
851b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#define HANDLE_CASE(name, lower_case, expected_arg_count)   \
861b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&lower_case);                                     \
8721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (FLAG_debug_code && expected_arg_count >= 0) {         \
881b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    AbortIfArgCountMismatch(expected_arg_count, arg_count); \
891b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  }                                                         \
9021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  result.Bind(name(first_arg_reg, arg_count, context));     \
911b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Goto(&end);
921b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  INTRINSICS_LIST(HANDLE_CASE)
931b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#undef HANDLE_CASE
941b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
951b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&abort);
9621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
9721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Abort(BailoutReason::kUnexpectedFunctionIDForInvokeIntrinsic);
9821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    result.Bind(__ UndefinedConstant());
9921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
10021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
1011b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
1021b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&end);
1031b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  return result.value();
1041b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}
1051b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
1061b268ca467c924004286c97bac133db489cf43d0Ben MurdochNode* IntrinsicsHelper::CompareInstanceType(Node* map, int type,
1071b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                            InstanceTypeCompareMode mode) {
1081b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Variable return_value(assembler_,
1091b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                              MachineRepresentation::kTagged);
1101b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  Node* instance_type = __ LoadInstanceType(map);
1111b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
1121b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Label if_true(assembler_), if_false(assembler_),
1131b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      end(assembler_);
1141b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  if (mode == kInstanceTypeEqual) {
11521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return __ Word32Equal(instance_type, __ Int32Constant(type));
1161b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  } else {
1171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    DCHECK(mode == kInstanceTypeGreaterThanOrEqual);
11821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return __ Int32GreaterThanOrEqual(instance_type, __ Int32Constant(type));
1191b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  }
12021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
1211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
12221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsInstanceType(Node* input, int type) {
12321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  InterpreterAssembler::Variable return_value(assembler_,
12421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                              MachineRepresentation::kTagged);
12521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  InterpreterAssembler::Label if_not_smi(assembler_), return_true(assembler_),
12621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      return_false(assembler_), end(assembler_);
12721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* arg = __ LoadRegister(input);
12821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ GotoIf(__ WordIsSmi(arg), &return_false);
1291b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
13021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* condition = CompareInstanceType(arg, type, kInstanceTypeEqual);
13121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Branch(condition, &return_true, &return_false);
13221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
13321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Bind(&return_true);
13421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
13521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return_value.Bind(__ BooleanConstant(true));
13621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
13721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
13821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
13921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Bind(&return_false);
14021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
14121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return_value.Bind(__ BooleanConstant(false));
14221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
14321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
1441b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
1451b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&end);
1461b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  return return_value.value();
1471b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}
1481b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
14921efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsJSReceiver(Node* input, Node* arg_count,
15021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                     Node* context) {
1511b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Variable return_value(assembler_,
1521b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                              MachineRepresentation::kTagged);
15321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  InterpreterAssembler::Label return_true(assembler_), return_false(assembler_),
1541b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      end(assembler_);
1551b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
15621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* arg = __ LoadRegister(input);
15721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ GotoIf(__ WordIsSmi(arg), &return_false);
1581b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
1591b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
16021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* condition = CompareInstanceType(arg, FIRST_JS_RECEIVER_TYPE,
16121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                        kInstanceTypeGreaterThanOrEqual);
16221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Branch(condition, &return_true, &return_false);
16321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
16421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Bind(&return_true);
16521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
16621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return_value.Bind(__ BooleanConstant(true));
16721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
16821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
16921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
17021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Bind(&return_false);
17121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
17221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return_value.Bind(__ BooleanConstant(false));
17321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
17421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
1751b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
1761b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&end);
1771b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  return return_value.value();
1781b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}
1791b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
18021efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsArray(Node* input, Node* arg_count, Node* context) {
18121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IsInstanceType(input, JS_ARRAY_TYPE);
18221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
18321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
18421efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsJSProxy(Node* input, Node* arg_count, Node* context) {
18521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IsInstanceType(input, JS_PROXY_TYPE);
18621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
18721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
18821efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsRegExp(Node* input, Node* arg_count, Node* context) {
18921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IsInstanceType(input, JS_REGEXP_TYPE);
19021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
19121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
19221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsTypedArray(Node* input, Node* arg_count,
19321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                     Node* context) {
19421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IsInstanceType(input, JS_TYPED_ARRAY_TYPE);
19521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
19621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
19721efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IsSmi(Node* input, Node* arg_count, Node* context) {
1981b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Variable return_value(assembler_,
1991b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                              MachineRepresentation::kTagged);
2001b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  InterpreterAssembler::Label if_smi(assembler_), if_not_smi(assembler_),
2011b268ca467c924004286c97bac133db489cf43d0Ben Murdoch      end(assembler_);
20221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
2031b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  Node* arg = __ LoadRegister(input);
2041b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
2051b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Branch(__ WordIsSmi(arg), &if_smi, &if_not_smi);
2061b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&if_smi);
20721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
20821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return_value.Bind(__ BooleanConstant(true));
20921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
21021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
2111b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
2121b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&if_not_smi);
21321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  {
21421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    return_value.Bind(__ BooleanConstant(false));
21521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&end);
21621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
2171b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
2181b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&end);
2191b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  return return_value.value();
2201b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}
2211b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
22221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::IntrinsicAsStubCall(Node* args_reg, Node* context,
22321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                            Callable const& callable) {
22421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  int param_count = callable.descriptor().GetParameterCount();
22521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node** args = zone()->NewArray<Node*>(param_count + 1);  // 1 for context
22621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  for (int i = 0; i < param_count; i++) {
22721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    args[i] = __ LoadRegister(args_reg);
22821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    args_reg = __ NextRegister(args_reg);
22921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
23021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  args[param_count] = context;
23121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
23221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return __ CallStubN(callable, args);
23321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
23421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
23521efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::HasProperty(Node* input, Node* arg_count,
23621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                    Node* context) {
23721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context,
23821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                             CodeFactory::HasProperty(isolate()));
23921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
24021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
24121efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::MathPow(Node* input, Node* arg_count, Node* context) {
24221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::MathPow(isolate()));
24321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
24421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
24521efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::NewObject(Node* input, Node* arg_count, Node* context) {
24621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context,
24721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                             CodeFactory::FastNewObject(isolate()));
24821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
24921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
25021efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::NumberToString(Node* input, Node* arg_count,
25121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                       Node* context) {
25221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context,
25321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                             CodeFactory::NumberToString(isolate()));
25421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
25521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
25621efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::RegExpConstructResult(Node* input, Node* arg_count,
25721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                              Node* context) {
25821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context,
25921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                             CodeFactory::RegExpConstructResult(isolate()));
26021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
26121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
26221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::RegExpExec(Node* input, Node* arg_count,
26321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                   Node* context) {
26421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context,
26521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                             CodeFactory::RegExpExec(isolate()));
26621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
26721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
26821efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::SubString(Node* input, Node* arg_count, Node* context) {
26921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::SubString(isolate()));
27021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
27121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
27221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ToString(Node* input, Node* arg_count, Node* context) {
27321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToString(isolate()));
27421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
27521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
27621efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ToName(Node* input, Node* arg_count, Node* context) {
27721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToName(isolate()));
27821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
27921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
28021efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ToLength(Node* input, Node* arg_count, Node* context) {
28121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToLength(isolate()));
28221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
28321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
28421efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ToInteger(Node* input, Node* arg_count, Node* context) {
28521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToInteger(isolate()));
28621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
28721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
28821efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ToNumber(Node* input, Node* arg_count, Node* context) {
28921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToNumber(isolate()));
29021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
29121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
29221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ToObject(Node* input, Node* arg_count, Node* context) {
29321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return IntrinsicAsStubCall(input, context, CodeFactory::ToObject(isolate()));
29421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
29521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
29621efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::Call(Node* args_reg, Node* arg_count, Node* context) {
29721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // First argument register contains the function target.
29821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* function = __ LoadRegister(args_reg);
29921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
30021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // Receiver is the second runtime call argument.
30121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* receiver_reg = __ NextRegister(args_reg);
30221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* receiver_arg = __ RegisterLocation(receiver_reg);
30321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
30421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // Subtract function and receiver from arg count.
30521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* function_and_receiver_count = __ Int32Constant(2);
30621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* target_args_count = __ Int32Sub(arg_count, function_and_receiver_count);
30721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
30821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (FLAG_debug_code) {
30921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    InterpreterAssembler::Label arg_count_positive(assembler_);
31021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    Node* comparison = __ Int32LessThan(target_args_count, __ Int32Constant(0));
31121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ GotoUnless(comparison, &arg_count_positive);
31221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Abort(kWrongArgumentCountForInvokeIntrinsic);
31321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Goto(&arg_count_positive);
31421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch    __ Bind(&arg_count_positive);
31521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  }
31621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
31721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* result = __ CallJS(function, context, receiver_arg, target_args_count,
31821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                           TailCallMode::kDisallow);
31921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return result;
32021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
32121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
32221efce637eb329c94f1323b6a2334a1c977e1a9dBen MurdochNode* IntrinsicsHelper::ValueOf(Node* args_reg, Node* arg_count,
32321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                Node* context) {
32421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  InterpreterAssembler::Variable return_value(assembler_,
32521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch                                              MachineRepresentation::kTagged);
32621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  InterpreterAssembler::Label done(assembler_);
32721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
32821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* object = __ LoadRegister(args_reg);
32921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return_value.Bind(object);
33021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
33121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // If the object is a smi return the object.
33221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ GotoIf(__ WordIsSmi(object), &done);
33321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
33421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // If the object is not a value type, return the object.
33521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  Node* condition =
33621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch      CompareInstanceType(object, JS_VALUE_TYPE, kInstanceTypeEqual);
33721efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ GotoUnless(condition, &done);
33821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
33921efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  // If the object is a value type, return the value field.
34021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return_value.Bind(__ LoadObjectField(object, JSValue::kValueOffset));
34121efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Goto(&done);
34221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
34321efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Bind(&done);
34421efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  return return_value.value();
34521efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch}
34621efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch
3471b268ca467c924004286c97bac133db489cf43d0Ben Murdochvoid IntrinsicsHelper::AbortIfArgCountMismatch(int expected, Node* actual) {
34821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  InterpreterAssembler::Label match(assembler_);
3491b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  Node* comparison = __ Word32Equal(actual, __ Int32Constant(expected));
35021efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ GotoIf(comparison, &match);
3511b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Abort(kWrongArgumentCountForInvokeIntrinsic);
35221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  __ Goto(&match);
3531b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  __ Bind(&match);
3541b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}
3551b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
3561b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}  // namespace interpreter
3571b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}  // namespace internal
3581b268ca467c924004286c97bac133db489cf43d0Ben Murdoch}  // namespace v8
359