1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2012 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h"
6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assembler.h"
8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/base/hashmap.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/contexts.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles-inl.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/heap/heap.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h"
1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime-utils.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Header of runtime functions.
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define F(name, number_of_args, result_size)                    \
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Object* Runtime_##name(int args_length, Object** args_object, \
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                         Isolate* isolate);
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFOR_EACH_INTRINSIC_RETURN_OBJECT(F)
24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef F
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define P(name, number_of_args, result_size)                       \
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ObjectPair Runtime_##name(int args_length, Object** args_object, \
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                            Isolate* isolate);
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFOR_EACH_INTRINSIC_RETURN_PAIR(P)
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef P
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
32109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define T(name, number_of_args, result_size)                         \
33109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ObjectTriple Runtime_##name(int args_length, Object** args_object, \
34109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                              Isolate* isolate);
35109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochFOR_EACH_INTRINSIC_RETURN_TRIPLE(T)
36109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef T
37109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define F(name, number_of_args, result_size)                                  \
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {                                                                           \
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        number_of_args, result_size                                           \
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }                                                                           \
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ,
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define I(name, number_of_args, result_size)                       \
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  {                                                                \
49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Runtime::kInline##name, Runtime::INLINE, "_" #name,            \
50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }                                                                \
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ,
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const Runtime::Function kIntrinsicFunctions[] = {
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FOR_EACH_INTRINSIC(F)
56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FOR_EACH_INTRINSIC(I)
57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef I
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef F
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace {
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochV8_DECLARE_ONCE(initialize_function_name_map_once);
65f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
66f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
67f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstruct IntrinsicFunctionIdentifier {
68f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
69f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      : data_(data), length_(length) {}
70f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
71f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static bool Match(void* key1, void* key2) {
72f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const IntrinsicFunctionIdentifier* lhs =
73f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        static_cast<IntrinsicFunctionIdentifier*>(key1);
74f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const IntrinsicFunctionIdentifier* rhs =
75f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        static_cast<IntrinsicFunctionIdentifier*>(key2);
76f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    if (lhs->length_ != rhs->length_) return false;
77f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                reinterpret_cast<const uint8_t*>(rhs->data_),
79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                rhs->length_) == 0;
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  uint32_t Hash() {
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return StringHasher::HashSequentialString<uint8_t>(
84f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        data_, length_, v8::internal::kZeroHashSeed);
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
87f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const unsigned char* data_;
88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  const int length_;
89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch};
90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid InitializeIntrinsicFunctionNames() {
92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::CustomMatcherHashMap* function_name_map =
93f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
94f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
95f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const Runtime::Function* function = &kIntrinsicFunctions[i];
96f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
97f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        reinterpret_cast<const unsigned char*>(function->name),
98f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        static_cast<int>(strlen(function->name)));
99f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    base::HashMap::Entry* entry =
100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch        function_name_map->InsertNew(identifier, identifier->Hash());
101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    entry->value = const_cast<Runtime::Function*>(function);
102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  kRuntimeFunctionNameMap = function_name_map;
104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}  // namespace
107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochconst Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                                  int length) {
110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::CallOnce(&initialize_function_name_map_once,
111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                 &InitializeIntrinsicFunctionNames);
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  IntrinsicFunctionIdentifier identifier(name, length);
113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::HashMap::Entry* entry =
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  if (entry) {
116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return reinterpret_cast<Function*>(entry->value);
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NULL;
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst Runtime::Function* Runtime::FunctionForEntry(Address entry) {
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (entry == kIntrinsicFunctions[i].entry) {
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return &(kIntrinsicFunctions[i]);
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return NULL;
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return &(kIntrinsicFunctions[static_cast<int>(id)]);
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (isolate->external_reference_redirector()) {
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // When running with the simulator we need to provide a table which has
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // redirected runtime entry addresses.
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      size_t function_count = arraysize(kIntrinsicFunctions);
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Function* redirected_functions = new Function[function_count];
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      memcpy(redirected_functions, kIntrinsicFunctions,
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             sizeof(kIntrinsicFunctions));
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (size_t i = 0; i < function_count; i++) {
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        ExternalReference redirected_entry(static_cast<Runtime::FunctionId>(i),
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                           isolate);
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        redirected_functions[i].entry = redirected_entry.address();
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      isolate->runtime_state()->set_redirected_intrinsic_functions(
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          redirected_functions);
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return isolate->runtime_state()->redirected_intrinsic_functions();
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return kIntrinsicFunctions;
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstd::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return os << Runtime::FunctionForId(id)->name;
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace internal
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
169