Line data Source code
1 : // 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 :
8 : #include "src/base/logging.h"
9 : #include "src/globals.h"
10 : #include "src/objects.h"
11 : #include "src/runtime/runtime.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 :
16 : // Cast the given object to a value of the specified type and store
17 : // it in a variable with the given name. If the object is not of the
18 : // expected type we crash safely.
19 : #define CONVERT_ARG_CHECKED(Type, name, index) \
20 : CHECK(args[index]->Is##Type()); \
21 : Type name = Type::cast(args[index]);
22 :
23 : #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
24 : CHECK(args[index]->Is##Type()); \
25 : Handle<Type> name = args.at<Type>(index);
26 :
27 : #define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \
28 : CHECK(args[index]->IsNumber()); \
29 : Handle<Object> name = args.at(index);
30 :
31 : // Cast the given object to a boolean and store it in a variable with
32 : // the given name. If the object is not a boolean we crash safely.
33 : #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
34 : CHECK(args[index]->IsBoolean()); \
35 : bool name = args[index]->IsTrue(isolate);
36 :
37 : // Cast the given argument to a Smi and store its value in an int variable
38 : // with the given name. If the argument is not a Smi we crash safely.
39 : #define CONVERT_SMI_ARG_CHECKED(name, index) \
40 : CHECK(args[index]->IsSmi()); \
41 : int name = args.smi_at(index);
42 :
43 : // Cast the given argument to a double and store it in a variable with
44 : // the given name. If the argument is not a number (as opposed to
45 : // the number not-a-number) we crash safely.
46 : #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
47 : CHECK(args[index]->IsNumber()); \
48 : double name = args.number_at(index);
49 :
50 : // Cast the given argument to a size_t and store its value in a variable with
51 : // the given name. If the argument is not a size_t we crash safely.
52 : #define CONVERT_SIZE_ARG_CHECKED(name, index) \
53 : CHECK(args[index]->IsNumber()); \
54 : Handle<Object> name##_object = args.at(index); \
55 : size_t name = 0; \
56 : CHECK(TryNumberToSize(*name##_object, &name));
57 :
58 : // Call the specified converter on the object *comand store the result in
59 : // a variable of the specified type with the given name. If the
60 : // object is not a Number we crash safely.
61 : #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
62 : CHECK(obj->IsNumber()); \
63 : type name = NumberTo##Type(obj);
64 :
65 : // Cast the given argument to PropertyDetails and store its value in a
66 : // variable with the given name. If the argument is not a Smi we crash safely.
67 : #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
68 : CHECK(args[index]->IsSmi()); \
69 : PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
70 :
71 : // Assert that the given argument has a valid value for a LanguageMode
72 : // and store it in a LanguageMode variable with the given name.
73 : #define CONVERT_LANGUAGE_MODE_ARG_CHECKED(name, index) \
74 : CHECK(args[index]->IsNumber()); \
75 : int32_t __tmp_##name = 0; \
76 : CHECK(args[index]->ToInt32(&__tmp_##name)); \
77 : CHECK(is_valid_language_mode(__tmp_##name)); \
78 : LanguageMode name = static_cast<LanguageMode>(__tmp_##name);
79 :
80 : // Assert that the given argument is a number within the Int32 range
81 : // and convert it to int32_t. If the argument is not an Int32 we crash safely.
82 : #define CONVERT_INT32_ARG_CHECKED(name, index) \
83 : CHECK(args[index]->IsNumber()); \
84 : int32_t name = 0; \
85 : CHECK(args[index]->ToInt32(&name));
86 :
87 : // Assert that the given argument is a number within the Uint32 range
88 : // and convert it to uint32_t. If the argument is not an Uint32 call
89 : // IllegalOperation and return.
90 : #define CONVERT_UINT32_ARG_CHECKED(name, index) \
91 : CHECK(args[index]->IsNumber()); \
92 : uint32_t name = 0; \
93 : CHECK(args[index]->ToUint32(&name));
94 :
95 : // Cast the given argument to PropertyAttributes and store its value in a
96 : // variable with the given name. If the argument is not a Smi or the
97 : // enum value is out of range, we crash safely.
98 : #define CONVERT_PROPERTY_ATTRIBUTES_CHECKED(name, index) \
99 : CHECK(args[index]->IsSmi()); \
100 : CHECK_EQ(args.smi_at(index) & ~(READ_ONLY | DONT_ENUM | DONT_DELETE), 0); \
101 : PropertyAttributes name = static_cast<PropertyAttributes>(args.smi_at(index));
102 :
103 : // A mechanism to return a pair of Object pointers in registers (if possible).
104 : // How this is achieved is calling convention-dependent.
105 : // All currently supported x86 compiles uses calling conventions that are cdecl
106 : // variants where a 64-bit value is returned in two 32-bit registers
107 : // (edx:eax on ia32, r1:r0 on ARM).
108 : // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
109 : // In Win64 calling convention, a struct of two pointers is returned in memory,
110 : // allocated by the caller, and passed as a pointer in a hidden first parameter.
111 : #ifdef V8_HOST_ARCH_64_BIT
112 : struct ObjectPair {
113 : Address x;
114 : Address y;
115 : };
116 :
117 481959 : static inline ObjectPair MakePair(Object x, Object y) {
118 : ObjectPair result = {x->ptr(), y->ptr()};
119 : // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
120 : // In Win64 they are assigned to a hidden first argument.
121 481959 : return result;
122 : }
123 : #else
124 : typedef uint64_t ObjectPair;
125 : static inline ObjectPair MakePair(Object x, Object y) {
126 : #if defined(V8_TARGET_LITTLE_ENDIAN)
127 : return x->ptr() | (static_cast<ObjectPair>(y->ptr()) << 32);
128 : #elif defined(V8_TARGET_BIG_ENDIAN)
129 : return y->ptr() | (static_cast<ObjectPair>(x->ptr()) << 32);
130 : #else
131 : #error Unknown endianness
132 : #endif
133 : }
134 : #endif
135 :
136 : } // namespace internal
137 : } // namespace v8
138 :
139 : #endif // V8_RUNTIME_RUNTIME_UTILS_H_
|