blob: c673b5a1557d45d1cf9ee65b1728f113d0179b34 [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// Copyright 2014 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_RUNTIME_RUNTIME_UTILS_H_
6#define V8_RUNTIME_RUNTIME_UTILS_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "src/runtime/runtime.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04009
10namespace v8 {
11namespace internal {
12
13#define RUNTIME_ASSERT(value) \
14 if (!(value)) return isolate->ThrowIllegalOperation();
15
16#define RUNTIME_ASSERT_HANDLIFIED(value, T) \
17 if (!(value)) { \
18 isolate->ThrowIllegalOperation(); \
19 return MaybeHandle<T>(); \
20 }
21
22// Cast the given object to a value of the specified type and store
23// it in a variable with the given name. If the object is not of the
24// expected type call IllegalOperation and return.
25#define CONVERT_ARG_CHECKED(Type, name, index) \
26 RUNTIME_ASSERT(args[index]->Is##Type()); \
27 Type* name = Type::cast(args[index]);
28
29#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
30 RUNTIME_ASSERT(args[index]->Is##Type()); \
31 Handle<Type> name = args.at<Type>(index);
32
33#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \
34 RUNTIME_ASSERT(args[index]->IsNumber()); \
35 Handle<Object> name = args.at<Object>(index);
36
37// Cast the given object to a boolean and store it in a variable with
38// the given name. If the object is not a boolean call IllegalOperation
39// and return.
40#define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
41 RUNTIME_ASSERT(args[index]->IsBoolean()); \
42 bool name = args[index]->IsTrue();
43
44// Cast the given argument to a Smi and store its value in an int variable
45// with the given name. If the argument is not a Smi call IllegalOperation
46// and return.
47#define CONVERT_SMI_ARG_CHECKED(name, index) \
48 RUNTIME_ASSERT(args[index]->IsSmi()); \
49 int name = args.smi_at(index);
50
51// Cast the given argument to a double and store it in a variable with
52// the given name. If the argument is not a number (as opposed to
53// the number not-a-number) call IllegalOperation and return.
54#define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
55 RUNTIME_ASSERT(args[index]->IsNumber()); \
56 double name = args.number_at(index);
57
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058
59// Cast the given argument to a size_t and store its value in a variable with
60// the given name. If the argument is not a size_t call IllegalOperation and
61// return.
62#define CONVERT_SIZE_ARG_CHECKED(name, index) \
63 RUNTIME_ASSERT(args[index]->IsNumber()); \
64 Handle<Object> name##_object = args.at<Object>(index); \
65 size_t name = 0; \
66 RUNTIME_ASSERT(TryNumberToSize(isolate, *name##_object, &name));
67
68
Emily Bernierd0a1eb72015-03-24 16:35:39 -040069// Call the specified converter on the object *comand store the result in
70// a variable of the specified type with the given name. If the
71// object is not a Number call IllegalOperation and return.
72#define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
73 RUNTIME_ASSERT(obj->IsNumber()); \
74 type name = NumberTo##Type(obj);
75
76
77// Cast the given argument to PropertyDetails and store its value in a
78// variable with the given name. If the argument is not a Smi call
79// IllegalOperation and return.
80#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
81 RUNTIME_ASSERT(args[index]->IsSmi()); \
82 PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
83
84
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085// Assert that the given argument has a valid value for a LanguageMode
86// and store it in a LanguageMode variable with the given name.
87#define CONVERT_LANGUAGE_MODE_ARG_CHECKED(name, index) \
88 RUNTIME_ASSERT(args[index]->IsSmi()); \
89 RUNTIME_ASSERT(is_valid_language_mode(args.smi_at(index))); \
90 LanguageMode name = static_cast<LanguageMode>(args.smi_at(index));
Emily Bernierd0a1eb72015-03-24 16:35:39 -040091
92
93// Assert that the given argument is a number within the Int32 range
94// and convert it to int32_t. If the argument is not an Int32 call
95// IllegalOperation and return.
96#define CONVERT_INT32_ARG_CHECKED(name, index) \
97 RUNTIME_ASSERT(args[index]->IsNumber()); \
98 int32_t name = 0; \
99 RUNTIME_ASSERT(args[index]->ToInt32(&name));
100
101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102// Cast the given argument to PropertyAttributes and store its value in a
103// variable with the given name. If the argument is not a Smi call or the
104// enum value is out of range, call IllegalOperation and return.
105#define CONVERT_PROPERTY_ATTRIBUTES_CHECKED(name, index) \
106 RUNTIME_ASSERT(args[index]->IsSmi()); \
107 RUNTIME_ASSERT( \
108 (args.smi_at(index) & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); \
109 PropertyAttributes name = static_cast<PropertyAttributes>(args.smi_at(index));
110
111
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400112// A mechanism to return a pair of Object pointers in registers (if possible).
113// How this is achieved is calling convention-dependent.
114// All currently supported x86 compiles uses calling conventions that are cdecl
115// variants where a 64-bit value is returned in two 32-bit registers
116// (edx:eax on ia32, r1:r0 on ARM).
117// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
118// In Win64 calling convention, a struct of two pointers is returned in memory,
119// allocated by the caller, and passed as a pointer in a hidden first parameter.
120#ifdef V8_HOST_ARCH_64_BIT
121struct ObjectPair {
122 Object* x;
123 Object* y;
124};
125
126
127static inline ObjectPair MakePair(Object* x, Object* y) {
128 ObjectPair result = {x, y};
129 // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
130 // In Win64 they are assigned to a hidden first argument.
131 return result;
132}
133#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
134// For x32 a 128-bit struct return is done as rax and rdx from the ObjectPair
135// are used in the full codegen and Crankshaft compiler. An alternative is
136// using uint64_t and modifying full codegen and Crankshaft compiler.
137struct ObjectPair {
138 Object* x;
139 uint32_t x_upper;
140 Object* y;
141 uint32_t y_upper;
142};
143
144
145static inline ObjectPair MakePair(Object* x, Object* y) {
146 ObjectPair result = {x, 0, y, 0};
147 // Pointers x and y returned in rax and rdx, in x32-abi.
148 return result;
149}
150#else
151typedef uint64_t ObjectPair;
152static inline ObjectPair MakePair(Object* x, Object* y) {
153#if defined(V8_TARGET_LITTLE_ENDIAN)
154 return reinterpret_cast<uint32_t>(x) |
155 (reinterpret_cast<ObjectPair>(y) << 32);
156#elif defined(V8_TARGET_BIG_ENDIAN)
157 return reinterpret_cast<uint32_t>(y) |
158 (reinterpret_cast<ObjectPair>(x) << 32);
159#else
160#error Unknown endianness
161#endif
162}
163#endif
164
Ben Murdoch097c5b22016-05-18 11:27:45 +0100165
166// A mechanism to return a triple of Object pointers. In all calling
167// conventions, a struct of two pointers is returned in memory,
168// allocated by the caller, and passed as a pointer in a hidden first parameter.
169struct ObjectTriple {
170 Object* x;
171 Object* y;
172 Object* z;
173};
174
175static inline ObjectTriple MakeTriple(Object* x, Object* y, Object* z) {
176 ObjectTriple result = {x, y, z};
177 // ObjectTriple is assigned to a hidden first argument.
178 return result;
179}
180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181} // namespace internal
182} // namespace v8
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400183
184#endif // V8_RUNTIME_RUNTIME_UTILS_H_