diff options
Diffstat (limited to 'deps/v8/src/runtime/runtime-utils.h')
-rw-r--r-- | deps/v8/src/runtime/runtime-utils.h | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/deps/v8/src/runtime/runtime-utils.h b/deps/v8/src/runtime/runtime-utils.h new file mode 100644 index 0000000000..a7e74ac316 --- /dev/null +++ b/deps/v8/src/runtime/runtime-utils.h @@ -0,0 +1,146 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_RUNTIME_UTILS_H_ +#define V8_RUNTIME_UTILS_H_ + + +namespace v8 { +namespace internal { + +#define RUNTIME_ASSERT(value) \ + if (!(value)) return isolate->ThrowIllegalOperation(); + +#define RUNTIME_ASSERT_HANDLIFIED(value, T) \ + if (!(value)) { \ + isolate->ThrowIllegalOperation(); \ + return MaybeHandle<T>(); \ + } + +// Cast the given object to a value of the specified type and store +// it in a variable with the given name. If the object is not of the +// expected type call IllegalOperation and return. +#define CONVERT_ARG_CHECKED(Type, name, index) \ + RUNTIME_ASSERT(args[index]->Is##Type()); \ + Type* name = Type::cast(args[index]); + +#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \ + RUNTIME_ASSERT(args[index]->Is##Type()); \ + Handle<Type> name = args.at<Type>(index); + +#define CONVERT_NUMBER_ARG_HANDLE_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsNumber()); \ + Handle<Object> name = args.at<Object>(index); + +// Cast the given object to a boolean and store it in a variable with +// the given name. If the object is not a boolean call IllegalOperation +// and return. +#define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsBoolean()); \ + bool name = args[index]->IsTrue(); + +// Cast the given argument to a Smi and store its value in an int variable +// with the given name. If the argument is not a Smi call IllegalOperation +// and return. +#define CONVERT_SMI_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsSmi()); \ + int name = args.smi_at(index); + +// Cast the given argument to a double and store it in a variable with +// the given name. If the argument is not a number (as opposed to +// the number not-a-number) call IllegalOperation and return. +#define CONVERT_DOUBLE_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsNumber()); \ + double name = args.number_at(index); + +// Call the specified converter on the object *comand store the result in +// a variable of the specified type with the given name. If the +// object is not a Number call IllegalOperation and return. +#define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ + RUNTIME_ASSERT(obj->IsNumber()); \ + type name = NumberTo##Type(obj); + + +// Cast the given argument to PropertyDetails and store its value in a +// variable with the given name. If the argument is not a Smi call +// IllegalOperation and return. +#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsSmi()); \ + PropertyDetails name = PropertyDetails(Smi::cast(args[index])); + + +// Assert that the given argument has a valid value for a StrictMode +// and store it in a StrictMode variable with the given name. +#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsSmi()); \ + RUNTIME_ASSERT(args.smi_at(index) == STRICT || \ + args.smi_at(index) == SLOPPY); \ + StrictMode name = static_cast<StrictMode>(args.smi_at(index)); + + +// Assert that the given argument is a number within the Int32 range +// and convert it to int32_t. If the argument is not an Int32 call +// IllegalOperation and return. +#define CONVERT_INT32_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsNumber()); \ + int32_t name = 0; \ + RUNTIME_ASSERT(args[index]->ToInt32(&name)); + + +// A mechanism to return a pair of Object pointers in registers (if possible). +// How this is achieved is calling convention-dependent. +// All currently supported x86 compiles uses calling conventions that are cdecl +// variants where a 64-bit value is returned in two 32-bit registers +// (edx:eax on ia32, r1:r0 on ARM). +// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax. +// In Win64 calling convention, a struct of two pointers is returned in memory, +// allocated by the caller, and passed as a pointer in a hidden first parameter. +#ifdef V8_HOST_ARCH_64_BIT +struct ObjectPair { + Object* x; + Object* y; +}; + + +static inline ObjectPair MakePair(Object* x, Object* y) { + ObjectPair result = {x, y}; + // Pointers x and y returned in rax and rdx, in AMD-x64-abi. + // In Win64 they are assigned to a hidden first argument. + return result; +} +#elif V8_TARGET_ARCH_X64 && V8_TARGET_ARCH_32_BIT +// For x32 a 128-bit struct return is done as rax and rdx from the ObjectPair +// are used in the full codegen and Crankshaft compiler. An alternative is +// using uint64_t and modifying full codegen and Crankshaft compiler. +struct ObjectPair { + Object* x; + uint32_t x_upper; + Object* y; + uint32_t y_upper; +}; + + +static inline ObjectPair MakePair(Object* x, Object* y) { + ObjectPair result = {x, 0, y, 0}; + // Pointers x and y returned in rax and rdx, in x32-abi. + return result; +} +#else +typedef uint64_t ObjectPair; +static inline ObjectPair MakePair(Object* x, Object* y) { +#if defined(V8_TARGET_LITTLE_ENDIAN) + return reinterpret_cast<uint32_t>(x) | + (reinterpret_cast<ObjectPair>(y) << 32); +#elif defined(V8_TARGET_BIG_ENDIAN) + return reinterpret_cast<uint32_t>(y) | + (reinterpret_cast<ObjectPair>(x) << 32); +#else +#error Unknown endianness +#endif +} +#endif +} +} // namespace v8::internal + +#endif // V8_RUNTIME_UTILS_H_ |