blob: 17c78d5a0b5ca5f4c2266b62f04e4c686f2ad4cd [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 Murdochda12d292016-06-02 14:46:10 +01008#include "src/base/logging.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/runtime/runtime.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040010
11namespace v8 {
12namespace internal {
13
Ben Murdochda12d292016-06-02 14:46:10 +010014#ifdef DEBUG
15
16#define RUNTIME_ASSERT(value) \
17 do { \
18 if (!(value)) { \
19 V8_RuntimeError(__FILE__, __LINE__, #value); \
20 return isolate->ThrowIllegalOperation(); \
21 } \
22 } while (0)
23
24#define RUNTIME_ASSERT_HANDLIFIED(value, T) \
25 do { \
26 if (!(value)) { \
27 V8_RuntimeError(__FILE__, __LINE__, #value); \
28 isolate->ThrowIllegalOperation(); \
29 return MaybeHandle<T>(); \
30 } \
31 } while (0)
32
33#else
34
35#define RUNTIME_ASSERT(value) \
36 do { \
37 if (!(value)) { \
38 return isolate->ThrowIllegalOperation(); \
39 } \
40 } while (0)
Emily Bernierd0a1eb72015-03-24 16:35:39 -040041
42#define RUNTIME_ASSERT_HANDLIFIED(value, T) \
Ben Murdochda12d292016-06-02 14:46:10 +010043 do { \
44 if (!(value)) { \
45 isolate->ThrowIllegalOperation(); \
46 return MaybeHandle<T>(); \
47 } \
48 } while (0)
49
50#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051
52// Cast the given object to a value of the specified type and store
53// it in a variable with the given name. If the object is not of the
54// expected type call IllegalOperation and return.
55#define CONVERT_ARG_CHECKED(Type, name, index) \
56 RUNTIME_ASSERT(args[index]->Is##Type()); \
57 Type* name = Type::cast(args[index]);
58
59#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
60 RUNTIME_ASSERT(args[index]->Is##Type()); \
61 Handle<Type> name = args.at<Type>(index);
62
63#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \
64 RUNTIME_ASSERT(args[index]->IsNumber()); \
65 Handle<Object> name = args.at<Object>(index);
66
67// Cast the given object to a boolean and store it in a variable with
68// the given name. If the object is not a boolean call IllegalOperation
69// and return.
70#define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
71 RUNTIME_ASSERT(args[index]->IsBoolean()); \
72 bool name = args[index]->IsTrue();
73
74// Cast the given argument to a Smi and store its value in an int variable
75// with the given name. If the argument is not a Smi call IllegalOperation
76// and return.
77#define CONVERT_SMI_ARG_CHECKED(name, index) \
78 RUNTIME_ASSERT(args[index]->IsSmi()); \
79 int name = args.smi_at(index);
80
81// Cast the given argument to a double and store it in a variable with
82// the given name. If the argument is not a number (as opposed to
83// the number not-a-number) call IllegalOperation and return.
84#define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
85 RUNTIME_ASSERT(args[index]->IsNumber()); \
86 double name = args.number_at(index);
87
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088
89// Cast the given argument to a size_t and store its value in a variable with
90// the given name. If the argument is not a size_t call IllegalOperation and
91// return.
92#define CONVERT_SIZE_ARG_CHECKED(name, index) \
93 RUNTIME_ASSERT(args[index]->IsNumber()); \
94 Handle<Object> name##_object = args.at<Object>(index); \
95 size_t name = 0; \
96 RUNTIME_ASSERT(TryNumberToSize(isolate, *name##_object, &name));
97
98
Emily Bernierd0a1eb72015-03-24 16:35:39 -040099// Call the specified converter on the object *comand store the result in
100// a variable of the specified type with the given name. If the
101// object is not a Number call IllegalOperation and return.
102#define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
103 RUNTIME_ASSERT(obj->IsNumber()); \
104 type name = NumberTo##Type(obj);
105
106
107// Cast the given argument to PropertyDetails and store its value in a
108// variable with the given name. If the argument is not a Smi call
109// IllegalOperation and return.
110#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
111 RUNTIME_ASSERT(args[index]->IsSmi()); \
112 PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
113
114
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115// Assert that the given argument has a valid value for a LanguageMode
116// and store it in a LanguageMode variable with the given name.
117#define CONVERT_LANGUAGE_MODE_ARG_CHECKED(name, index) \
118 RUNTIME_ASSERT(args[index]->IsSmi()); \
119 RUNTIME_ASSERT(is_valid_language_mode(args.smi_at(index))); \
120 LanguageMode name = static_cast<LanguageMode>(args.smi_at(index));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121
122
123// Assert that the given argument is a number within the Int32 range
124// and convert it to int32_t. If the argument is not an Int32 call
125// IllegalOperation and return.
126#define CONVERT_INT32_ARG_CHECKED(name, index) \
127 RUNTIME_ASSERT(args[index]->IsNumber()); \
128 int32_t name = 0; \
129 RUNTIME_ASSERT(args[index]->ToInt32(&name));
130
131
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132// Cast the given argument to PropertyAttributes and store its value in a
133// variable with the given name. If the argument is not a Smi call or the
134// enum value is out of range, call IllegalOperation and return.
135#define CONVERT_PROPERTY_ATTRIBUTES_CHECKED(name, index) \
136 RUNTIME_ASSERT(args[index]->IsSmi()); \
137 RUNTIME_ASSERT( \
138 (args.smi_at(index) & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); \
139 PropertyAttributes name = static_cast<PropertyAttributes>(args.smi_at(index));
140
141
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142// A mechanism to return a pair of Object pointers in registers (if possible).
143// How this is achieved is calling convention-dependent.
144// All currently supported x86 compiles uses calling conventions that are cdecl
145// variants where a 64-bit value is returned in two 32-bit registers
146// (edx:eax on ia32, r1:r0 on ARM).
147// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
148// In Win64 calling convention, a struct of two pointers is returned in memory,
149// allocated by the caller, and passed as a pointer in a hidden first parameter.
150#ifdef V8_HOST_ARCH_64_BIT
151struct ObjectPair {
152 Object* x;
153 Object* y;
154};
155
156
157static inline ObjectPair MakePair(Object* x, Object* y) {
158 ObjectPair result = {x, y};
159 // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
160 // In Win64 they are assigned to a hidden first argument.
161 return result;
162}
163#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT
164// For x32 a 128-bit struct return is done as rax and rdx from the ObjectPair
165// are used in the full codegen and Crankshaft compiler. An alternative is
166// using uint64_t and modifying full codegen and Crankshaft compiler.
167struct ObjectPair {
168 Object* x;
169 uint32_t x_upper;
170 Object* y;
171 uint32_t y_upper;
172};
173
174
175static inline ObjectPair MakePair(Object* x, Object* y) {
176 ObjectPair result = {x, 0, y, 0};
177 // Pointers x and y returned in rax and rdx, in x32-abi.
178 return result;
179}
180#else
181typedef uint64_t ObjectPair;
182static inline ObjectPair MakePair(Object* x, Object* y) {
183#if defined(V8_TARGET_LITTLE_ENDIAN)
184 return reinterpret_cast<uint32_t>(x) |
185 (reinterpret_cast<ObjectPair>(y) << 32);
186#elif defined(V8_TARGET_BIG_ENDIAN)
187 return reinterpret_cast<uint32_t>(y) |
188 (reinterpret_cast<ObjectPair>(x) << 32);
189#else
190#error Unknown endianness
191#endif
192}
193#endif
194
Ben Murdoch097c5b22016-05-18 11:27:45 +0100195
196// A mechanism to return a triple of Object pointers. In all calling
197// conventions, a struct of two pointers is returned in memory,
198// allocated by the caller, and passed as a pointer in a hidden first parameter.
199struct ObjectTriple {
200 Object* x;
201 Object* y;
202 Object* z;
203};
204
205static inline ObjectTriple MakeTriple(Object* x, Object* y, Object* z) {
206 ObjectTriple result = {x, y, z};
207 // ObjectTriple is assigned to a hidden first argument.
208 return result;
209}
210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211} // namespace internal
212} // namespace v8
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400213
214#endif // V8_RUNTIME_RUNTIME_UTILS_H_