| Index: src/compiler/js-operator.h
|
| diff --git a/src/compiler/js-operator.h b/src/compiler/js-operator.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..9f4b83a533a26cf2b6b71a4291c96605403f9115
|
| --- /dev/null
|
| +++ b/src/compiler/js-operator.h
|
| @@ -0,0 +1,204 @@
|
| +// Copyright 2013 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_COMPILER_JS_OPERATOR_H_
|
| +#define V8_COMPILER_JS_OPERATOR_H_
|
| +
|
| +#include "src/compiler/opcodes.h"
|
| +#include "src/compiler/operator.h"
|
| +#include "src/unique.h"
|
| +#include "src/zone.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +namespace compiler {
|
| +
|
| +// Defines the location of a context slot relative to a specific scope. This is
|
| +// used as a parameter by JSLoadContext and JSStoreContext operators and allows
|
| +// accessing a context-allocated variable without keeping track of the scope.
|
| +class ContextAccess {
|
| + public:
|
| + ContextAccess(int depth, int index, bool immutable)
|
| + : immutable_(immutable), depth_(depth), index_(index) {
|
| + ASSERT(0 <= depth && depth <= kMaxUInt16);
|
| + ASSERT(0 <= index && static_cast<uint32_t>(index) <= kMaxUInt32);
|
| + }
|
| + int depth() const { return depth_; }
|
| + int index() const { return index_; }
|
| + bool immutable() const { return immutable_; }
|
| +
|
| + private:
|
| + // For space reasons, we keep this tightly packed, otherwise we could just use
|
| + // a simple int/int/bool POD.
|
| + const bool immutable_;
|
| + const uint16_t depth_;
|
| + const uint32_t index_;
|
| +};
|
| +
|
| +// Defines the arity and the call flags for a JavaScript function call. This is
|
| +// used as a parameter by JSCall operators.
|
| +struct CallParameters {
|
| + int arity;
|
| + CallFunctionFlags flags;
|
| +};
|
| +
|
| +// Interface for building JavaScript-level operators, e.g. directly from the
|
| +// AST. Most operators have no parameters, thus can be globally shared for all
|
| +// graphs.
|
| +class JSOperatorBuilder {
|
| + public:
|
| + explicit JSOperatorBuilder(Zone* zone) : zone_(zone) {}
|
| +
|
| +#define SIMPLE(name, properties, inputs, outputs) \
|
| + return new (zone_) \
|
| + SimpleOperator(IrOpcode::k##name, properties, inputs, outputs, #name);
|
| +
|
| +#define NOPROPS(name, inputs, outputs) \
|
| + SIMPLE(name, Operator::kNoProperties, inputs, outputs)
|
| +
|
| +#define OP1(name, ptype, pname, properties, inputs, outputs) \
|
| + return new (zone_) Operator1<ptype>(IrOpcode::k##name, properties, inputs, \
|
| + outputs, #name, pname)
|
| +
|
| +#define BINOP(name) NOPROPS(name, 2, 1)
|
| +#define UNOP(name) NOPROPS(name, 1, 1)
|
| +
|
| +#define PURE_BINOP(name) SIMPLE(name, Operator::kPure, 2, 1)
|
| +
|
| + Operator* Equal() { BINOP(JSEqual); }
|
| + Operator* NotEqual() { BINOP(JSNotEqual); }
|
| + Operator* StrictEqual() { PURE_BINOP(JSStrictEqual); }
|
| + Operator* StrictNotEqual() { PURE_BINOP(JSStrictNotEqual); }
|
| + Operator* LessThan() { BINOP(JSLessThan); }
|
| + Operator* GreaterThan() { BINOP(JSGreaterThan); }
|
| + Operator* LessThanOrEqual() { BINOP(JSLessThanOrEqual); }
|
| + Operator* GreaterThanOrEqual() { BINOP(JSGreaterThanOrEqual); }
|
| + Operator* BitwiseOr() { BINOP(JSBitwiseOr); }
|
| + Operator* BitwiseXor() { BINOP(JSBitwiseXor); }
|
| + Operator* BitwiseAnd() { BINOP(JSBitwiseAnd); }
|
| + Operator* ShiftLeft() { BINOP(JSShiftLeft); }
|
| + Operator* ShiftRight() { BINOP(JSShiftRight); }
|
| + Operator* ShiftRightLogical() { BINOP(JSShiftRightLogical); }
|
| + Operator* Add() { BINOP(JSAdd); }
|
| + Operator* Subtract() { BINOP(JSSubtract); }
|
| + Operator* Multiply() { BINOP(JSMultiply); }
|
| + Operator* Divide() { BINOP(JSDivide); }
|
| + Operator* Modulus() { BINOP(JSModulus); }
|
| +
|
| + Operator* UnaryNot() { UNOP(JSUnaryNot); }
|
| + Operator* ToBoolean() { UNOP(JSToBoolean); }
|
| + Operator* ToNumber() { UNOP(JSToNumber); }
|
| + Operator* ToString() { UNOP(JSToString); }
|
| + Operator* ToName() { UNOP(JSToName); }
|
| + Operator* ToObject() { UNOP(JSToObject); }
|
| + Operator* Yield() { UNOP(JSYield); }
|
| +
|
| + Operator* Create() { SIMPLE(JSCreate, Operator::kEliminatable, 0, 1); }
|
| +
|
| + Operator* Call(int arguments, CallFunctionFlags flags) {
|
| + CallParameters parameters = {arguments, flags};
|
| + OP1(JSCallFunction, CallParameters, parameters, Operator::kNoProperties,
|
| + arguments, 1);
|
| + }
|
| +
|
| + Operator* CallNew(int arguments) {
|
| + return new (zone_)
|
| + Operator1<int>(IrOpcode::kJSCallConstruct, Operator::kNoProperties,
|
| + arguments, 1, "JSCallConstruct", arguments);
|
| + }
|
| +
|
| + Operator* LoadProperty() { BINOP(JSLoadProperty); }
|
| + Operator* LoadNamed(PrintableUnique<Name> name) {
|
| + OP1(JSLoadNamed, PrintableUnique<Name>, name, Operator::kNoProperties, 1,
|
| + 1);
|
| + }
|
| +
|
| + Operator* StoreProperty() { NOPROPS(JSStoreProperty, 3, 0); }
|
| + Operator* StoreNamed(PrintableUnique<Name> name) {
|
| + OP1(JSStoreNamed, PrintableUnique<Name>, name, Operator::kNoProperties, 2,
|
| + 0);
|
| + }
|
| +
|
| + Operator* DeleteProperty(StrictMode strict_mode) {
|
| + OP1(JSDeleteProperty, StrictMode, strict_mode, Operator::kNoProperties, 2,
|
| + 1);
|
| + }
|
| +
|
| + Operator* HasProperty() { NOPROPS(JSHasProperty, 2, 1); }
|
| +
|
| + Operator* LoadContext(uint16_t depth, uint32_t index, bool immutable) {
|
| + ContextAccess access(depth, index, immutable);
|
| + OP1(JSLoadContext, ContextAccess, access,
|
| + Operator::kEliminatable | Operator::kNoWrite, 1, 1);
|
| + }
|
| + Operator* StoreContext(uint16_t depth, uint32_t index) {
|
| + ContextAccess access(depth, index, false);
|
| + OP1(JSStoreContext, ContextAccess, access, Operator::kNoProperties, 2, 1);
|
| + }
|
| +
|
| + Operator* TypeOf() { SIMPLE(JSTypeOf, Operator::kPure, 1, 1); }
|
| + Operator* InstanceOf() { NOPROPS(JSInstanceOf, 2, 1); }
|
| + Operator* Debugger() { NOPROPS(JSDebugger, 0, 0); }
|
| +
|
| + // TODO(titzer): nail down the static parts of each of these context flavors.
|
| + Operator* CreateFunctionContext() { NOPROPS(JSCreateFunctionContext, 1, 1); }
|
| + Operator* CreateCatchContext(PrintableUnique<String> name) {
|
| + OP1(JSCreateCatchContext, PrintableUnique<String>, name,
|
| + Operator::kNoProperties, 1, 1);
|
| + }
|
| + Operator* CreateWithContext() { NOPROPS(JSCreateWithContext, 2, 1); }
|
| + Operator* CreateBlockContext() { NOPROPS(JSCreateBlockContext, 2, 1); }
|
| + Operator* CreateModuleContext() { NOPROPS(JSCreateModuleContext, 2, 1); }
|
| + Operator* CreateGlobalContext() { NOPROPS(JSCreateGlobalContext, 2, 1); }
|
| +
|
| + Operator* Runtime(Runtime::FunctionId function, int arguments) {
|
| + const Runtime::Function* f = Runtime::FunctionForId(function);
|
| + ASSERT(f->nargs == -1 || f->nargs == arguments);
|
| + OP1(JSCallRuntime, Runtime::FunctionId, function, Operator::kNoProperties,
|
| + arguments, f->result_size);
|
| + }
|
| +
|
| +#undef SIMPLE
|
| +#undef NOPROPS
|
| +#undef OP1
|
| +#undef BINOP
|
| +#undef UNOP
|
| +
|
| + private:
|
| + Zone* zone_;
|
| +};
|
| +
|
| +// Specialization for static parameters of type {ContextAccess}.
|
| +template <>
|
| +struct StaticParameterTraits<ContextAccess> {
|
| + static OStream& PrintTo(OStream& os, ContextAccess val) { // NOLINT
|
| + return os << val.depth() << "," << val.index()
|
| + << (val.immutable() ? ",imm" : "");
|
| + }
|
| + static int HashCode(ContextAccess val) {
|
| + return (val.depth() << 16) | (val.index() & 0xffff);
|
| + }
|
| + static bool Equals(ContextAccess a, ContextAccess b) {
|
| + return a.immutable() == b.immutable() && a.depth() == b.depth() &&
|
| + a.index() == b.index();
|
| + }
|
| +};
|
| +
|
| +// Specialization for static parameters of type {Runtime::FunctionId}.
|
| +template <>
|
| +struct StaticParameterTraits<Runtime::FunctionId> {
|
| + static OStream& PrintTo(OStream& os, Runtime::FunctionId val) { // NOLINT
|
| + const Runtime::Function* f = Runtime::FunctionForId(val);
|
| + return os << (f->name ? f->name : "?Runtime?");
|
| + }
|
| + static int HashCode(Runtime::FunctionId val) { return static_cast<int>(val); }
|
| + static bool Equals(Runtime::FunctionId a, Runtime::FunctionId b) {
|
| + return a == b;
|
| + }
|
| +};
|
| +}
|
| +}
|
| +} // namespace v8::internal::compiler
|
| +
|
| +#endif // V8_COMPILER_JS_OPERATOR_H_
|
|
|