cd746c8172
Review URL: https://codereview.chromium.org//12041056 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@17623 260f80e4-7a28-3924-810f-c04153c831b5
173 lines
5.9 KiB
C++
173 lines
5.9 KiB
C++
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#ifndef VM_NATIVE_ARGUMENTS_H_
|
|
#define VM_NATIVE_ARGUMENTS_H_
|
|
|
|
#include "platform/assert.h"
|
|
#include "vm/globals.h"
|
|
#include "vm/stub_code.h"
|
|
|
|
namespace dart {
|
|
|
|
// Forward declarations.
|
|
class BootstrapNatives;
|
|
class Isolate;
|
|
class Object;
|
|
class RawObject;
|
|
class Simulator;
|
|
|
|
|
|
#if defined(TESTING) || defined(DEBUG)
|
|
|
|
#if defined(TARGET_OS_WINDOWS)
|
|
// The compiler may dynamically align the stack on Windows, so do not check.
|
|
#define CHECK_STACK_ALIGNMENT { }
|
|
#else
|
|
#define CHECK_STACK_ALIGNMENT { \
|
|
uword (*func)() = \
|
|
reinterpret_cast<uword (*)()>(StubCode::GetStackPointerEntryPoint()); \
|
|
uword current_sp = func(); \
|
|
ASSERT((OS::ActivationFrameAlignment() == 0) || \
|
|
(Utils::IsAligned(current_sp, OS::ActivationFrameAlignment()))); \
|
|
}
|
|
#endif
|
|
|
|
#else
|
|
|
|
#define CHECK_STACK_ALIGNMENT { }
|
|
|
|
#endif
|
|
|
|
void SetReturnValueHelper(Dart_NativeArguments, Dart_Handle);
|
|
|
|
|
|
// Class NativeArguments is used to access arguments passed in from
|
|
// generated dart code to a runtime function or a dart library native
|
|
// function. It is also used to set the return value if any at the slot
|
|
// reserved for return values.
|
|
// All runtime function/dart library native functions have the
|
|
// following signature:
|
|
// void function_name(NativeArguments arguments);
|
|
// Inside the function, arguments are accessed as follows:
|
|
// const Instance& arg0 = Instance::CheckedHandle(arguments.ArgAt(0));
|
|
// const Smi& arg1 = Smi::CheckedHandle(arguments.ArgAt(1));
|
|
// The return value is set as follows:
|
|
// arguments.SetReturn(result);
|
|
// NOTE: Since we pass 'this' as a pass-by-value argument in the stubs we don't
|
|
// have DISALLOW_COPY_AND_ASSIGN in the class definition and do not make it a
|
|
// subclass of ValueObject.
|
|
class NativeArguments {
|
|
public:
|
|
Isolate* isolate() const { return isolate_; }
|
|
int ArgCount() const { return ArgcBits::decode(argc_tag_); }
|
|
|
|
// Returns true if the arguments are those of an instance function call.
|
|
bool ToInstanceFunction() const {
|
|
return InstanceFunctionBit::decode(argc_tag_);
|
|
}
|
|
|
|
// Returns true if the arguments are those of a closure function call.
|
|
bool ToClosureFunction() const {
|
|
return ClosureFunctionBit::decode(argc_tag_);
|
|
}
|
|
|
|
RawObject* ArgAt(int index) const {
|
|
ASSERT((index >= 0) && (index < ArgCount()));
|
|
return (*argv_)[-index];
|
|
}
|
|
|
|
int NumHiddenArgs() const {
|
|
// For static closure functions, the closure at index 0 is hidden.
|
|
// In the instance closure function case, the receiver is accessed from
|
|
// the context and the closure at index 0 is hidden, so the apparent
|
|
// argument count remains unchanged.
|
|
if (ToClosureFunction() && !ToInstanceFunction()) {
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int NativeArgCount() const {
|
|
return ArgCount() - NumHiddenArgs();
|
|
}
|
|
|
|
RawObject* NativeArgAt(int index) const {
|
|
ASSERT((index >= 0) && (index < NativeArgCount()));
|
|
if ((index == 0) && ToClosureFunction() && ToInstanceFunction()) {
|
|
// Retrieve the receiver from the context.
|
|
const Context& context = Context::Handle(isolate_->top_context());
|
|
return context.At(0);
|
|
} else {
|
|
const int actual_index = index + NumHiddenArgs();
|
|
return ArgAt(actual_index);
|
|
}
|
|
}
|
|
|
|
void SetReturn(const Object& value) const;
|
|
|
|
static intptr_t isolate_offset() {
|
|
return OFFSET_OF(NativeArguments, isolate_);
|
|
}
|
|
static intptr_t argc_tag_offset() {
|
|
return OFFSET_OF(NativeArguments, argc_tag_);
|
|
}
|
|
static intptr_t argv_offset() { return OFFSET_OF(NativeArguments, argv_); }
|
|
static intptr_t retval_offset() {
|
|
return OFFSET_OF(NativeArguments, retval_);
|
|
}
|
|
|
|
static int ParameterCountForResolution(const Function& function) {
|
|
ASSERT(function.is_native());
|
|
ASSERT(!function.IsConstructor()); // Not supported.
|
|
int count = function.NumParameters();
|
|
if (function.is_static() && function.IsClosureFunction()) {
|
|
// The closure object is hidden and not accessible from native code.
|
|
// However, if the function is an instance closure function, the captured
|
|
// receiver located in the context is made accessible in native code at
|
|
// index 0, thereby hidding the closure object at index 0.
|
|
count--;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
static int ComputeArgcTag(const Function& function) {
|
|
ASSERT(function.is_native());
|
|
ASSERT(!function.IsConstructor()); // Not supported.
|
|
int tag = ArgcBits::encode(function.NumParameters());
|
|
tag = InstanceFunctionBit::update(!function.is_static(), tag);
|
|
tag = ClosureFunctionBit::update(function.IsClosureFunction(), tag);
|
|
return tag;
|
|
}
|
|
|
|
private:
|
|
enum ArgcTagBits {
|
|
kArgcBit = 0,
|
|
kArgcSize = 24,
|
|
kInstanceFunctionBit = 24,
|
|
kClosureFunctionBit = 25,
|
|
};
|
|
class ArgcBits : public BitField<int, kArgcBit, kArgcSize> {};
|
|
class InstanceFunctionBit : public BitField<bool, kInstanceFunctionBit, 1> {};
|
|
class ClosureFunctionBit : public BitField<bool, kClosureFunctionBit, 1> {};
|
|
friend class BootstrapNatives;
|
|
friend class Simulator;
|
|
friend void SetReturnValueHelper(Dart_NativeArguments, Dart_Handle);
|
|
|
|
// Since this function is passed a RawObject directly, we need to be
|
|
// exceedingly careful when we use it. If there are any other side
|
|
// effects in the statement that may cause GC, it could lead to
|
|
// bugs.
|
|
void SetReturnUnsafe(RawObject* value) const;
|
|
|
|
Isolate* isolate_; // Current isolate pointer.
|
|
int argc_tag_; // Encodes argument count and invoked native call type.
|
|
RawObject*(*argv_)[]; // Pointer to an array of arguments to runtime call.
|
|
RawObject** retval_; // Pointer to the return value area.
|
|
};
|
|
|
|
} // namespace dart
|
|
|
|
#endif // VM_NATIVE_ARGUMENTS_H_
|