Commit c1ee6247 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

[turbofan] Some javascript operators are globally shared singletons.

Also cleanup the interface, and make the parameter class/accessors
explicit to work-around the type-unsafety of OpParameter<T>.

TEST=compiler-unittests,cctest,mjsunit
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/613683002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24322 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 40a968be
...@@ -520,6 +520,7 @@ source_set("v8_base") { ...@@ -520,6 +520,7 @@ source_set("v8_base") {
"src/compiler/js-graph.h", "src/compiler/js-graph.h",
"src/compiler/js-inlining.cc", "src/compiler/js-inlining.cc",
"src/compiler/js-inlining.h", "src/compiler/js-inlining.h",
"src/compiler/js-operator.cc",
"src/compiler/js-operator.h", "src/compiler/js-operator.h",
"src/compiler/js-typed-lowering.cc", "src/compiler/js-typed-lowering.cc",
"src/compiler/js-typed-lowering.h", "src/compiler/js-typed-lowering.h",
......
...@@ -75,7 +75,7 @@ bool AstGraphBuilder::CreateGraph() { ...@@ -75,7 +75,7 @@ bool AstGraphBuilder::CreateGraph() {
// Emit tracing call if requested to do so. // Emit tracing call if requested to do so.
if (FLAG_trace) { if (FLAG_trace) {
NewNode(javascript()->Runtime(Runtime::kTraceEnter, 0)); NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
} }
// Visit implicit declaration of the function name. // Visit implicit declaration of the function name.
...@@ -87,7 +87,7 @@ bool AstGraphBuilder::CreateGraph() { ...@@ -87,7 +87,7 @@ bool AstGraphBuilder::CreateGraph() {
VisitDeclarations(scope->declarations()); VisitDeclarations(scope->declarations());
// TODO(mstarzinger): This should do an inlined stack check. // TODO(mstarzinger): This should do an inlined stack check.
Node* node = NewNode(javascript()->Runtime(Runtime::kStackGuard, 0)); Node* node = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0));
PrepareFrameState(node, BailoutId::FunctionEntry()); PrepareFrameState(node, BailoutId::FunctionEntry());
// Visit statements in the function body. // Visit statements in the function body.
...@@ -98,7 +98,7 @@ bool AstGraphBuilder::CreateGraph() { ...@@ -98,7 +98,7 @@ bool AstGraphBuilder::CreateGraph() {
if (FLAG_trace) { if (FLAG_trace) {
// TODO(mstarzinger): Only traces implicit return. // TODO(mstarzinger): Only traces implicit return.
Node* return_value = jsgraph()->UndefinedConstant(); Node* return_value = jsgraph()->UndefinedConstant();
NewNode(javascript()->Runtime(Runtime::kTraceExit, 1), return_value); NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
} }
// Return 'undefined' in case we can fall off the end. // Return 'undefined' in case we can fall off the end.
...@@ -643,20 +643,20 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { ...@@ -643,20 +643,20 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
// TODO(dcarney): should do a fast enum cache check here to skip runtime. // TODO(dcarney): should do a fast enum cache check here to skip runtime.
environment()->Push(obj); environment()->Push(obj);
Node* cache_type = ProcessArguments( Node* cache_type = ProcessArguments(
javascript()->Runtime(Runtime::kGetPropertyNamesFast, 1), 1); javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), 1);
// TODO(dcarney): these next runtime calls should be removed in favour of // TODO(dcarney): these next runtime calls should be removed in favour of
// a few simplified instructions. // a few simplified instructions.
environment()->Push(obj); environment()->Push(obj);
environment()->Push(cache_type); environment()->Push(cache_type);
Node* cache_pair = Node* cache_pair =
ProcessArguments(javascript()->Runtime(Runtime::kForInInit, 2), 2); ProcessArguments(javascript()->CallRuntime(Runtime::kForInInit, 2), 2);
// cache_type may have been replaced. // cache_type may have been replaced.
Node* cache_array = NewNode(common()->Projection(0), cache_pair); Node* cache_array = NewNode(common()->Projection(0), cache_pair);
cache_type = NewNode(common()->Projection(1), cache_pair); cache_type = NewNode(common()->Projection(1), cache_pair);
environment()->Push(cache_type); environment()->Push(cache_type);
environment()->Push(cache_array); environment()->Push(cache_array);
Node* cache_length = ProcessArguments( Node* cache_length = ProcessArguments(
javascript()->Runtime(Runtime::kForInCacheArrayLength, 2), 2); javascript()->CallRuntime(Runtime::kForInCacheArrayLength, 2), 2);
{ {
// TODO(dcarney): this check is actually supposed to be for the // TODO(dcarney): this check is actually supposed to be for the
// empty enum case only. // empty enum case only.
...@@ -692,8 +692,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { ...@@ -692,8 +692,8 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
environment()->Push(cache_array); environment()->Push(cache_array);
environment()->Push(cache_type); environment()->Push(cache_type);
environment()->Push(index); environment()->Push(index);
Node* pair = Node* pair = ProcessArguments(
ProcessArguments(javascript()->Runtime(Runtime::kForInNext, 4), 4); javascript()->CallRuntime(Runtime::kForInNext, 4), 4);
Node* value = NewNode(common()->Projection(0), pair); Node* value = NewNode(common()->Projection(0), pair);
Node* should_filter = NewNode(common()->Projection(1), pair); Node* should_filter = NewNode(common()->Projection(1), pair);
environment()->Push(value); environment()->Push(value);
...@@ -719,7 +719,7 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { ...@@ -719,7 +719,7 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
// result is either the string key or Smi(0) indicating the property // result is either the string key or Smi(0) indicating the property
// is gone. // is gone.
Node* res = ProcessArguments( Node* res = ProcessArguments(
javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), 3); javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3);
// TODO(jarin): provide real bailout id. // TODO(jarin): provide real bailout id.
PrepareFrameState(res, BailoutId::None()); PrepareFrameState(res, BailoutId::None());
Node* property_missing = NewNode(javascript()->StrictEqual(), res, Node* property_missing = NewNode(javascript()->StrictEqual(), res,
...@@ -785,7 +785,7 @@ void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { ...@@ -785,7 +785,7 @@ void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
// TODO(turbofan): Do we really need a separate reloc-info for this? // TODO(turbofan): Do we really need a separate reloc-info for this?
Node* node = NewNode(javascript()->Runtime(Runtime::kDebugBreak, 0)); Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0));
PrepareFrameState(node, stmt->DebugBreakId()); PrepareFrameState(node, stmt->DebugBreakId());
} }
...@@ -806,7 +806,7 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { ...@@ -806,7 +806,7 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
Node* info = jsgraph()->Constant(shared_info); Node* info = jsgraph()->Constant(shared_info);
Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant() Node* pretenure = expr->pretenure() ? jsgraph()->TrueConstant()
: jsgraph()->FalseConstant(); : jsgraph()->FalseConstant();
const Operator* op = javascript()->Runtime(Runtime::kNewClosure, 3); const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3);
Node* value = NewNode(op, context, info, pretenure); Node* value = NewNode(op, context, info, pretenure);
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
} }
...@@ -859,7 +859,7 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { ...@@ -859,7 +859,7 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
Node* pattern = jsgraph()->Constant(expr->pattern()); Node* pattern = jsgraph()->Constant(expr->pattern());
Node* flags = jsgraph()->Constant(expr->flags()); Node* flags = jsgraph()->Constant(expr->flags());
const Operator* op = const Operator* op =
javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4); javascript()->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
Node* literal = NewNode(op, literals_array, literal_index, pattern, flags); Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(literal); ast_context()->ProduceValue(literal);
...@@ -876,7 +876,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -876,7 +876,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* literal_index = jsgraph()->Constant(expr->literal_index()); Node* literal_index = jsgraph()->Constant(expr->literal_index());
Node* constants = jsgraph()->Constant(expr->constant_properties()); Node* constants = jsgraph()->Constant(expr->constant_properties());
Node* flags = jsgraph()->Constant(expr->ComputeFlags()); Node* flags = jsgraph()->Constant(expr->ComputeFlags());
const Operator* op = javascript()->Runtime(Runtime::kCreateObjectLiteral, 4); const Operator* op =
javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
Node* literal = NewNode(op, literals_array, literal_index, constants, flags); Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
// The object is expected on the operand stack during computation of the // The object is expected on the operand stack during computation of the
...@@ -925,7 +926,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -925,7 +926,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* receiver = environment()->Pop(); Node* receiver = environment()->Pop();
if (property->emit_store()) { if (property->emit_store()) {
Node* strict = jsgraph()->Constant(SLOPPY); Node* strict = jsgraph()->Constant(SLOPPY);
const Operator* op = javascript()->Runtime(Runtime::kSetProperty, 4); const Operator* op =
javascript()->CallRuntime(Runtime::kSetProperty, 4);
NewNode(op, receiver, key, value, strict); NewNode(op, receiver, key, value, strict);
} }
break; break;
...@@ -936,7 +938,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -936,7 +938,8 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* value = environment()->Pop(); Node* value = environment()->Pop();
Node* receiver = environment()->Pop(); Node* receiver = environment()->Pop();
if (property->emit_store()) { if (property->emit_store()) {
const Operator* op = javascript()->Runtime(Runtime::kSetPrototype, 2); const Operator* op =
javascript()->CallRuntime(Runtime::kSetPrototype, 2);
NewNode(op, receiver, value); NewNode(op, receiver, value);
} }
break; break;
...@@ -962,14 +965,15 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { ...@@ -962,14 +965,15 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* name = environment()->Pop(); Node* name = environment()->Pop();
Node* attr = jsgraph()->Constant(NONE); Node* attr = jsgraph()->Constant(NONE);
const Operator* op = const Operator* op =
javascript()->Runtime(Runtime::kDefineAccessorPropertyUnchecked, 5); javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
Node* call = NewNode(op, literal, name, getter, setter, attr); Node* call = NewNode(op, literal, name, getter, setter, attr);
PrepareFrameState(call, it->first->id()); PrepareFrameState(call, it->first->id());
} }
// Transform literals that contain functions to fast properties. // Transform literals that contain functions to fast properties.
if (expr->has_function()) { if (expr->has_function()) {
const Operator* op = javascript()->Runtime(Runtime::kToFastProperties, 1); const Operator* op =
javascript()->CallRuntime(Runtime::kToFastProperties, 1);
NewNode(op, literal); NewNode(op, literal);
} }
...@@ -987,7 +991,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -987,7 +991,8 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Node* literal_index = jsgraph()->Constant(expr->literal_index()); Node* literal_index = jsgraph()->Constant(expr->literal_index());
Node* constants = jsgraph()->Constant(expr->constant_elements()); Node* constants = jsgraph()->Constant(expr->constant_elements());
Node* flags = jsgraph()->Constant(expr->ComputeFlags()); Node* flags = jsgraph()->Constant(expr->ComputeFlags());
const Operator* op = javascript()->Runtime(Runtime::kCreateArrayLiteral, 4); const Operator* op =
javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
Node* literal = NewNode(op, literals_array, literal_index, constants, flags); Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
// The array and the literal index are both expected on the operand stack // The array and the literal index are both expected on the operand stack
...@@ -1166,7 +1171,7 @@ void AstGraphBuilder::VisitYield(Yield* expr) { ...@@ -1166,7 +1171,7 @@ void AstGraphBuilder::VisitYield(Yield* expr) {
void AstGraphBuilder::VisitThrow(Throw* expr) { void AstGraphBuilder::VisitThrow(Throw* expr) {
VisitForValue(expr->exception()); VisitForValue(expr->exception());
Node* exception = environment()->Pop(); Node* exception = environment()->Pop();
const Operator* op = javascript()->Runtime(Runtime::kThrow, 1); const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
Node* value = NewNode(op, exception); Node* value = NewNode(op, exception);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -1213,7 +1218,8 @@ void AstGraphBuilder::VisitCall(Call* expr) { ...@@ -1213,7 +1218,8 @@ void AstGraphBuilder::VisitCall(Call* expr) {
Variable* variable = callee->AsVariableProxy()->var(); Variable* variable = callee->AsVariableProxy()->var();
DCHECK(variable->location() == Variable::LOOKUP); DCHECK(variable->location() == Variable::LOOKUP);
Node* name = jsgraph()->Constant(variable->name()); Node* name = jsgraph()->Constant(variable->name());
const Operator* op = javascript()->Runtime(Runtime::kLoadLookupSlot, 2); const Operator* op =
javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
Node* pair = NewNode(op, current_context(), name); Node* pair = NewNode(op, current_context(), name);
callee_value = NewNode(common()->Projection(0), pair); callee_value = NewNode(common()->Projection(0), pair);
receiver_value = NewNode(common()->Projection(1), pair); receiver_value = NewNode(common()->Projection(1), pair);
...@@ -1278,7 +1284,7 @@ void AstGraphBuilder::VisitCall(Call* expr) { ...@@ -1278,7 +1284,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
Node* strict = jsgraph()->Constant(strict_mode()); Node* strict = jsgraph()->Constant(strict_mode());
Node* position = jsgraph()->Constant(info()->scope()->start_position()); Node* position = jsgraph()->Constant(info()->scope()->start_position());
const Operator* op = const Operator* op =
javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5); javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
Node* pair = NewNode(op, callee, source, receiver, strict, position); Node* pair = NewNode(op, callee, source, receiver, strict, position);
PrepareFrameState(pair, expr->EvalOrLookupId(), PrepareFrameState(pair, expr->EvalOrLookupId(),
OutputFrameStateCombine::PokeAt(arg_count + 1)); OutputFrameStateCombine::PokeAt(arg_count + 1));
...@@ -1291,7 +1297,7 @@ void AstGraphBuilder::VisitCall(Call* expr) { ...@@ -1291,7 +1297,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
} }
// Create node to perform the function call. // Create node to perform the function call.
const Operator* call = javascript()->Call(args->length() + 2, flags); const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
Node* value = ProcessArguments(call, args->length() + 2); Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -1306,7 +1312,7 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) { ...@@ -1306,7 +1312,7 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
VisitForValues(args); VisitForValues(args);
// Create node to perform the construct call. // Create node to perform the construct call.
const Operator* call = javascript()->CallNew(args->length() + 1); const Operator* call = javascript()->CallConstruct(args->length() + 1);
Node* value = ProcessArguments(call, args->length() + 1); Node* value = ProcessArguments(call, args->length() + 1);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -1334,7 +1340,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) { ...@@ -1334,7 +1340,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
VisitForValues(args); VisitForValues(args);
// Create node to perform the JS runtime call. // Create node to perform the JS runtime call.
const Operator* call = javascript()->Call(args->length() + 2, flags); const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
Node* value = ProcessArguments(call, args->length() + 2); Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -1357,7 +1363,7 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) { ...@@ -1357,7 +1363,7 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
// Create node to perform the runtime call. // Create node to perform the runtime call.
Runtime::FunctionId functionId = function->function_id; Runtime::FunctionId functionId = function->function_id;
const Operator* call = javascript()->Runtime(functionId, args->length()); const Operator* call = javascript()->CallRuntime(functionId, args->length());
Node* value = ProcessArguments(call, args->length()); Node* value = ProcessArguments(call, args->length());
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -1571,7 +1577,7 @@ void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { ...@@ -1571,7 +1577,7 @@ void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
DeclareGlobalsStrictMode::encode(strict_mode()); DeclareGlobalsStrictMode::encode(strict_mode());
Node* flags = jsgraph()->Constant(encoded_flags); Node* flags = jsgraph()->Constant(encoded_flags);
Node* pairs = jsgraph()->Constant(data); Node* pairs = jsgraph()->Constant(data);
const Operator* op = javascript()->Runtime(Runtime::kDeclareGlobals, 3); const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 3);
NewNode(op, current_context(), pairs, flags); NewNode(op, current_context(), pairs, flags);
globals()->Rewind(0); globals()->Rewind(0);
} }
...@@ -1680,6 +1686,11 @@ void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { ...@@ -1680,6 +1686,11 @@ void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
} }
StrictMode AstGraphBuilder::strict_mode() const {
return info()->strict_mode();
}
Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) { Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
DCHECK(environment()->stack_height() >= arity); DCHECK(environment()->stack_height() >= arity);
Node** all = info()->zone()->NewArray<Node*>(arity); Node** all = info()->zone()->NewArray<Node*>(arity);
...@@ -1724,7 +1735,7 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { ...@@ -1724,7 +1735,7 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
// Allocate and initialize a new arguments object. // Allocate and initialize a new arguments object.
Node* callee = GetFunctionClosure(); Node* callee = GetFunctionClosure();
const Operator* op = javascript()->Runtime(Runtime::kNewArguments, 1); const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1);
Node* object = NewNode(op, callee); Node* object = NewNode(op, callee);
// Assign the object to the arguments variable. // Assign the object to the arguments variable.
...@@ -1831,7 +1842,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, ...@@ -1831,7 +1842,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
(contextual_mode == CONTEXTUAL) (contextual_mode == CONTEXTUAL)
? Runtime::kLoadLookupSlot ? Runtime::kLoadLookupSlot
: Runtime::kLoadLookupSlotNoReferenceError; : Runtime::kLoadLookupSlotNoReferenceError;
const Operator* op = javascript()->Runtime(function_id, 2); const Operator* op = javascript()->CallRuntime(function_id, 2);
Node* pair = NewNode(op, current_context(), name); Node* pair = NewNode(op, current_context(), name);
PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1)); PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1));
return NewNode(common()->Projection(0), pair); return NewNode(common()->Projection(0), pair);
...@@ -1864,7 +1875,8 @@ Node* AstGraphBuilder::BuildVariableDelete( ...@@ -1864,7 +1875,8 @@ Node* AstGraphBuilder::BuildVariableDelete(
case Variable::LOOKUP: { case Variable::LOOKUP: {
// Dynamic lookup of context variable (anywhere in the chain). // Dynamic lookup of context variable (anywhere in the chain).
Node* name = jsgraph()->Constant(variable->name()); Node* name = jsgraph()->Constant(variable->name());
const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2); const Operator* op =
javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
Node* result = NewNode(op, current_context(), name); Node* result = NewNode(op, current_context(), name);
PrepareFrameState(result, bailout_id, state_combine); PrepareFrameState(result, bailout_id, state_combine);
return result; return result;
...@@ -1950,7 +1962,8 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value, ...@@ -1950,7 +1962,8 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
Node* strict = jsgraph()->Constant(strict_mode()); Node* strict = jsgraph()->Constant(strict_mode());
// TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
// initializations of const declarations. // initializations of const declarations.
const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4); const Operator* op =
javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
Node* store = NewNode(op, value, current_context(), name, strict); Node* store = NewNode(op, value, current_context(), name, strict);
PrepareFrameState(store, bailout_id); PrepareFrameState(store, bailout_id);
return store; return store;
...@@ -1995,7 +2008,8 @@ Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable, ...@@ -1995,7 +2008,8 @@ Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
BailoutId bailout_id) { BailoutId bailout_id) {
// TODO(mstarzinger): Should be unified with the VisitThrow implementation. // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
Node* variable_name = jsgraph()->Constant(variable->name()); Node* variable_name = jsgraph()->Constant(variable->name());
const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1); const Operator* op =
javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
Node* call = NewNode(op, variable_name); Node* call = NewNode(op, variable_name);
PrepareFrameState(call, bailout_id); PrepareFrameState(call, bailout_id);
return call; return call;
......
...@@ -131,8 +131,8 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor { ...@@ -131,8 +131,8 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
SetOncePointer<Node> function_closure_; SetOncePointer<Node> function_closure_;
SetOncePointer<Node> function_context_; SetOncePointer<Node> function_context_;
CompilationInfo* info() { return info_; } CompilationInfo* info() const { return info_; }
StrictMode strict_mode() { return info()->strict_mode(); } inline StrictMode strict_mode() const;
JSGraph* jsgraph() { return jsgraph_; } JSGraph* jsgraph() { return jsgraph_; }
JSOperatorBuilder* javascript() { return jsgraph_->javascript(); } JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
ZoneList<Handle<Object> >* globals() { return &globals_; } ZoneList<Handle<Object> >* globals() { return &globals_; }
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "src/compiler/change-lowering.h" #include "src/compiler/change-lowering.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/machine-operator.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
'instruction-selector-unittest.cc', 'instruction-selector-unittest.cc',
'instruction-selector-unittest.h', 'instruction-selector-unittest.h',
'js-builtin-reducer-unittest.cc', 'js-builtin-reducer-unittest.cc',
'js-operator-unittest.cc',
'machine-operator-reducer-unittest.cc', 'machine-operator-reducer-unittest.cc',
'machine-operator-unittest.cc', 'machine-operator-unittest.cc',
'simplified-operator-reducer-unittest.cc', 'simplified-operator-reducer-unittest.cc',
......
...@@ -69,8 +69,9 @@ TEST_F(JSBuiltinReducerTest, MathAbs) { ...@@ -69,8 +69,9 @@ TEST_F(JSBuiltinReducerTest, MathAbs) {
TRACED_FOREACH(Type*, t0, kNumberTypes) { TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0); Node* p0 = Parameter(t0, 0);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), Node* call =
fun, UndefinedConstant(), p0); graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant(), p0);
Reduction r = Reduce(call); Reduction r = Reduce(call);
if (t0->Is(Type::Unsigned32())) { if (t0->Is(Type::Unsigned32())) {
...@@ -102,8 +103,9 @@ TEST_F(JSBuiltinReducerTest, MathSqrt) { ...@@ -102,8 +103,9 @@ TEST_F(JSBuiltinReducerTest, MathSqrt) {
TRACED_FOREACH(Type*, t0, kNumberTypes) { TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0); Node* p0 = Parameter(t0, 0);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), Node* call =
fun, UndefinedConstant(), p0); graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant(), p0);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -120,8 +122,9 @@ TEST_F(JSBuiltinReducerTest, MathMax0) { ...@@ -120,8 +122,9 @@ TEST_F(JSBuiltinReducerTest, MathMax0) {
Handle<JSFunction> f(isolate()->context()->math_max_fun()); Handle<JSFunction> f(isolate()->context()->math_max_fun());
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = graph()->NewNode(javascript()->Call(2, NO_CALL_FUNCTION_FLAGS), Node* call =
fun, UndefinedConstant()); graph()->NewNode(javascript()->CallFunction(2, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant());
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -135,8 +138,9 @@ TEST_F(JSBuiltinReducerTest, MathMax1) { ...@@ -135,8 +138,9 @@ TEST_F(JSBuiltinReducerTest, MathMax1) {
TRACED_FOREACH(Type*, t0, kNumberTypes) { TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0); Node* p0 = Parameter(t0, 0);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), Node* call =
fun, UndefinedConstant(), p0); graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant(), p0);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
...@@ -153,9 +157,9 @@ TEST_F(JSBuiltinReducerTest, MathMax2) { ...@@ -153,9 +157,9 @@ TEST_F(JSBuiltinReducerTest, MathMax2) {
Node* p0 = Parameter(t0, 0); Node* p0 = Parameter(t0, 0);
Node* p1 = Parameter(t1, 1); Node* p1 = Parameter(t1, 1);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = Node* call = graph()->NewNode(
graph()->NewNode(javascript()->Call(4, NO_CALL_FUNCTION_FLAGS), fun, javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun,
UndefinedConstant(), p0, p1); UndefinedConstant(), p0, p1);
Reduction r = Reduce(call); Reduction r = Reduce(call);
if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) { if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
...@@ -189,9 +193,9 @@ TEST_F(JSBuiltinReducerTest, MathImul) { ...@@ -189,9 +193,9 @@ TEST_F(JSBuiltinReducerTest, MathImul) {
Node* p0 = Parameter(t0, 0); Node* p0 = Parameter(t0, 0);
Node* p1 = Parameter(t1, 1); Node* p1 = Parameter(t1, 1);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = Node* call = graph()->NewNode(
graph()->NewNode(javascript()->Call(4, NO_CALL_FUNCTION_FLAGS), fun, javascript()->CallFunction(4, NO_CALL_FUNCTION_FLAGS), fun,
UndefinedConstant(), p0, p1); UndefinedConstant(), p0, p1);
Reduction r = Reduce(call); Reduction r = Reduce(call);
if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) { if (t0->Is(Type::Integral32()) && t1->Is(Type::Integral32())) {
...@@ -222,8 +226,9 @@ TEST_F(JSBuiltinReducerTest, MathFround) { ...@@ -222,8 +226,9 @@ TEST_F(JSBuiltinReducerTest, MathFround) {
TRACED_FOREACH(Type*, t0, kNumberTypes) { TRACED_FOREACH(Type*, t0, kNumberTypes) {
Node* p0 = Parameter(t0, 0); Node* p0 = Parameter(t0, 0);
Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f)); Node* fun = HeapConstant(Unique<HeapObject>::CreateUninitialized(f));
Node* call = graph()->NewNode(javascript()->Call(3, NO_CALL_FUNCTION_FLAGS), Node* call =
fun, UndefinedConstant(), p0); graph()->NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
fun, UndefinedConstant(), p0);
Reduction r = Reduce(call); Reduction r = Reduce(call);
ASSERT_TRUE(r.Changed()); ASSERT_TRUE(r.Changed());
......
...@@ -67,11 +67,11 @@ Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) { ...@@ -67,11 +67,11 @@ Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) {
return Reducer::NoChange(); return Reducer::NoChange();
} }
ContextAccess access = OpParameter<ContextAccess>(node); const ContextAccess& access = ContextAccessOf(node->op());
// Find the right parent context. // Find the right parent context.
Context* context = *m.Value().handle(); Context* context = *m.Value().handle();
for (int i = access.depth(); i > 0; --i) { for (size_t i = access.depth(); i > 0; --i) {
context = context->previous(); context = context->previous();
} }
...@@ -88,8 +88,8 @@ Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) { ...@@ -88,8 +88,8 @@ Reduction JSContextSpecializer::ReduceJSLoadContext(Node* node) {
node->ReplaceInput(0, jsgraph_->Constant(context_handle)); node->ReplaceInput(0, jsgraph_->Constant(context_handle));
return Reducer::Changed(node); return Reducer::Changed(node);
} }
Handle<Object> value = Handle<Object> value = Handle<Object>(
Handle<Object>(context->get(access.index()), info_->isolate()); context->get(static_cast<int>(access.index())), info_->isolate());
// Even though the context slot is immutable, the context might have escaped // Even though the context slot is immutable, the context might have escaped
// before the function to which it belongs has initialized the slot. // before the function to which it belongs has initialized the slot.
...@@ -115,7 +115,7 @@ Reduction JSContextSpecializer::ReduceJSStoreContext(Node* node) { ...@@ -115,7 +115,7 @@ Reduction JSContextSpecializer::ReduceJSStoreContext(Node* node) {
return Reducer::NoChange(); return Reducer::NoChange();
} }
ContextAccess access = OpParameter<ContextAccess>(node); const ContextAccess& access = ContextAccessOf(node->op());
// The access does not have to look up a parent, nothing to fold. // The access does not have to look up a parent, nothing to fold.
if (access.depth() == 0) { if (access.depth() == 0) {
...@@ -124,7 +124,7 @@ Reduction JSContextSpecializer::ReduceJSStoreContext(Node* node) { ...@@ -124,7 +124,7 @@ Reduction JSContextSpecializer::ReduceJSStoreContext(Node* node) {
// Find the right parent context. // Find the right parent context.
Context* context = *m.Value().handle(); Context* context = *m.Value().handle();
for (int i = access.depth(); i > 0; --i) { for (size_t i = access.depth(); i > 0; --i) {
context = context->previous(); context = context->previous();
} }
......
...@@ -281,9 +281,9 @@ void JSGenericLowering::LowerJSLoadProperty(Node* node) { ...@@ -281,9 +281,9 @@ void JSGenericLowering::LowerJSLoadProperty(Node* node) {
void JSGenericLowering::LowerJSLoadNamed(Node* node) { void JSGenericLowering::LowerJSLoadNamed(Node* node) {
LoadNamedParameters p = OpParameter<LoadNamedParameters>(node); const LoadNamedParameters& p = LoadNamedParametersOf(node->op());
Callable callable = CodeFactory::LoadIC(isolate(), p.contextual_mode); Callable callable = CodeFactory::LoadIC(isolate(), p.contextual_mode());
PatchInsertInput(node, 1, jsgraph()->HeapConstant(p.name)); PatchInsertInput(node, 1, jsgraph()->HeapConstant(p.name()));
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite);
} }
...@@ -296,9 +296,9 @@ void JSGenericLowering::LowerJSStoreProperty(Node* node) { ...@@ -296,9 +296,9 @@ void JSGenericLowering::LowerJSStoreProperty(Node* node) {
void JSGenericLowering::LowerJSStoreNamed(Node* node) { void JSGenericLowering::LowerJSStoreNamed(Node* node) {
StoreNamedParameters params = OpParameter<StoreNamedParameters>(node); const StoreNamedParameters& p = StoreNamedParametersOf(node->op());
Callable callable = CodeFactory::StoreIC(isolate(), params.strict_mode); Callable callable = CodeFactory::StoreIC(isolate(), p.strict_mode());
PatchInsertInput(node, 1, jsgraph()->HeapConstant(params.name)); PatchInsertInput(node, 1, jsgraph()->HeapConstant(p.name()));
ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite); ReplaceWithStubCall(node, callable, CallDescriptor::kPatchableCallSite);
} }
...@@ -330,10 +330,10 @@ void JSGenericLowering::LowerJSInstanceOf(Node* node) { ...@@ -330,10 +330,10 @@ void JSGenericLowering::LowerJSInstanceOf(Node* node) {
void JSGenericLowering::LowerJSLoadContext(Node* node) { void JSGenericLowering::LowerJSLoadContext(Node* node) {
ContextAccess access = OpParameter<ContextAccess>(node); const ContextAccess& access = ContextAccessOf(node->op());
// TODO(mstarzinger): Use simplified operators instead of machine operators // TODO(mstarzinger): Use simplified operators instead of machine operators
// here so that load/store optimization can be applied afterwards. // here so that load/store optimization can be applied afterwards.
for (int i = 0; i < access.depth(); ++i) { for (size_t i = 0; i < access.depth(); ++i) {
node->ReplaceInput( node->ReplaceInput(
0, graph()->NewNode( 0, graph()->NewNode(
machine()->Load(kMachAnyTagged), machine()->Load(kMachAnyTagged),
...@@ -341,16 +341,17 @@ void JSGenericLowering::LowerJSLoadContext(Node* node) { ...@@ -341,16 +341,17 @@ void JSGenericLowering::LowerJSLoadContext(Node* node) {
Int32Constant(Context::SlotOffset(Context::PREVIOUS_INDEX)), Int32Constant(Context::SlotOffset(Context::PREVIOUS_INDEX)),
NodeProperties::GetEffectInput(node))); NodeProperties::GetEffectInput(node)));
} }
node->ReplaceInput(1, Int32Constant(Context::SlotOffset(access.index()))); node->ReplaceInput(
1, Int32Constant(Context::SlotOffset(static_cast<int>(access.index()))));
PatchOperator(node, machine()->Load(kMachAnyTagged)); PatchOperator(node, machine()->Load(kMachAnyTagged));
} }
void JSGenericLowering::LowerJSStoreContext(Node* node) { void JSGenericLowering::LowerJSStoreContext(Node* node) {
ContextAccess access = OpParameter<ContextAccess>(node); const ContextAccess& access = ContextAccessOf(node->op());
// TODO(mstarzinger): Use simplified operators instead of machine operators // TODO(mstarzinger): Use simplified operators instead of machine operators
// here so that load/store optimization can be applied afterwards. // here so that load/store optimization can be applied afterwards.
for (int i = 0; i < access.depth(); ++i) { for (size_t i = 0; i < access.depth(); ++i) {
node->ReplaceInput( node->ReplaceInput(
0, graph()->NewNode( 0, graph()->NewNode(
machine()->Load(kMachAnyTagged), machine()->Load(kMachAnyTagged),
...@@ -359,7 +360,8 @@ void JSGenericLowering::LowerJSStoreContext(Node* node) { ...@@ -359,7 +360,8 @@ void JSGenericLowering::LowerJSStoreContext(Node* node) {
NodeProperties::GetEffectInput(node))); NodeProperties::GetEffectInput(node)));
} }
node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1)); node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1));
node->ReplaceInput(1, Int32Constant(Context::SlotOffset(access.index()))); node->ReplaceInput(
1, Int32Constant(Context::SlotOffset(static_cast<int>(access.index()))));
PatchOperator(node, machine()->Store(StoreRepresentation(kMachAnyTagged, PatchOperator(node, machine()->Store(StoreRepresentation(kMachAnyTagged,
kFullWriteBarrier))); kFullWriteBarrier)));
} }
...@@ -382,11 +384,11 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) { ...@@ -382,11 +384,11 @@ void JSGenericLowering::LowerJSCallConstruct(Node* node) {
void JSGenericLowering::LowerJSCallFunction(Node* node) { void JSGenericLowering::LowerJSCallFunction(Node* node) {
CallParameters p = OpParameter<CallParameters>(node); const CallFunctionParameters& p = CallFunctionParametersOf(node->op());
CallFunctionStub stub(isolate(), p.arity - 2, p.flags); CallFunctionStub stub(isolate(), static_cast<int>(p.arity() - 2), p.flags());
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
CallDescriptor* desc = CallDescriptor* desc = linkage()->GetStubCallDescriptor(
linkage()->GetStubCallDescriptor(d, p.arity - 1, FlagsForNode(node)); d, static_cast<int>(p.arity() - 1), FlagsForNode(node));
Node* stub_code = CodeConstant(stub.GetCode()); Node* stub_code = CodeConstant(stub.GetCode());
PatchInsertInput(node, 0, stub_code); PatchInsertInput(node, 0, stub_code);
PatchOperator(node, common()->Call(desc)); PatchOperator(node, common()->Call(desc));
...@@ -394,9 +396,8 @@ void JSGenericLowering::LowerJSCallFunction(Node* node) { ...@@ -394,9 +396,8 @@ void JSGenericLowering::LowerJSCallFunction(Node* node) {
void JSGenericLowering::LowerJSCallRuntime(Node* node) { void JSGenericLowering::LowerJSCallRuntime(Node* node) {
Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(node); const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
int arity = OperatorProperties::GetValueInputCount(node->op()); ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
ReplaceWithRuntimeCall(node, function, arity);
} }
} // namespace compiler } // namespace compiler
......
...@@ -5,13 +5,12 @@ ...@@ -5,13 +5,12 @@
#ifndef V8_COMPILER_JS_GENERIC_LOWERING_H_ #ifndef V8_COMPILER_JS_GENERIC_LOWERING_H_
#define V8_COMPILER_JS_GENERIC_LOWERING_H_ #define V8_COMPILER_JS_GENERIC_LOWERING_H_
#include "src/v8.h"
#include "src/allocation.h" #include "src/allocation.h"
#include "src/code-factory.h" #include "src/code-factory.h"
#include "src/compiler/graph.h" #include "src/compiler/graph.h"
#include "src/compiler/graph-reducer.h" #include "src/compiler/graph-reducer.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/opcodes.h" #include "src/compiler/opcodes.h"
namespace v8 { namespace v8 {
......
// 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.
#include "src/compiler/js-operator.h"
#include "src/compiler/operator-properties-inl.h"
#include "src/test/test-utils.h"
namespace v8 {
namespace internal {
namespace compiler {
// -----------------------------------------------------------------------------
// Shared operators.
namespace {
struct SharedOperator {
const Operator* (JSOperatorBuilder::*constructor)();
IrOpcode::Value opcode;
Operator::Properties properties;
int value_input_count;
int frame_state_input_count;
int effect_input_count;
int control_input_count;
int value_output_count;
int effect_output_count;
};
std::ostream& operator<<(std::ostream& os, const SharedOperator& sop) {
return os << IrOpcode::Mnemonic(sop.opcode);
}
const SharedOperator kSharedOperators[] = {
#define SHARED(Name, properties, value_input_count, frame_state_input_count, \
effect_input_count, control_input_count, value_output_count, \
effect_output_count) \
{ \
&JSOperatorBuilder::Name, IrOpcode::kJS##Name, properties, \
value_input_count, frame_state_input_count, effect_input_count, \
control_input_count, value_output_count, effect_output_count \
}
SHARED(Equal, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(NotEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(StrictEqual, Operator::kPure, 2, 0, 0, 0, 1, 0),
SHARED(StrictNotEqual, Operator::kPure, 2, 0, 0, 0, 1, 0),
SHARED(LessThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(GreaterThan, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(LessThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(GreaterThanOrEqual, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(BitwiseOr, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(BitwiseXor, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(BitwiseAnd, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(ShiftLeft, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(ShiftRight, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(ShiftRightLogical, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(Add, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(Subtract, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(Multiply, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(Divide, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(Modulus, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(UnaryNot, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(ToBoolean, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(ToNumber, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(ToString, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(ToName, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(ToObject, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(Create, Operator::kEliminatable, 0, 0, 1, 0, 1, 1),
SHARED(LoadProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(HasProperty, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0),
SHARED(InstanceOf, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
SHARED(Debugger, Operator::kNoProperties, 0, 0, 1, 1, 0, 1),
SHARED(CreateFunctionContext, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(CreateWithContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
SHARED(CreateBlockContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
SHARED(CreateModuleContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1),
SHARED(CreateGlobalContext, Operator::kNoProperties, 2, 0, 1, 1, 1, 1)
#undef SHARED
};
} // namespace
class JSSharedOperatorTest
: public TestWithZone,
public ::testing::WithParamInterface<SharedOperator> {};
TEST_P(JSSharedOperatorTest, InstancesAreGloballyShared) {
const SharedOperator& sop = GetParam();
JSOperatorBuilder javascript1(zone());
JSOperatorBuilder javascript2(zone());
EXPECT_EQ((javascript1.*sop.constructor)(), (javascript2.*sop.constructor)());
}
TEST_P(JSSharedOperatorTest, NumberOfInputsAndOutputs) {
JSOperatorBuilder javascript(zone());
const SharedOperator& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)();
const int context_input_count = 1;
// TODO(jarin): Get rid of this hack.
const int frame_state_input_count =
FLAG_turbo_deoptimization ? sop.frame_state_input_count : 0;
EXPECT_EQ(sop.value_input_count, OperatorProperties::GetValueInputCount(op));
EXPECT_EQ(context_input_count, OperatorProperties::GetContextInputCount(op));
EXPECT_EQ(frame_state_input_count,
OperatorProperties::GetFrameStateInputCount(op));
EXPECT_EQ(sop.effect_input_count,
OperatorProperties::GetEffectInputCount(op));
EXPECT_EQ(sop.control_input_count,
OperatorProperties::GetControlInputCount(op));
EXPECT_EQ(sop.value_input_count + context_input_count +
frame_state_input_count + sop.effect_input_count +
sop.control_input_count,
OperatorProperties::GetTotalInputCount(op));
EXPECT_EQ(sop.value_output_count,
OperatorProperties::GetValueOutputCount(op));
EXPECT_EQ(sop.effect_output_count,
OperatorProperties::GetEffectOutputCount(op));
EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
}
TEST_P(JSSharedOperatorTest, OpcodeIsCorrect) {
JSOperatorBuilder javascript(zone());
const SharedOperator& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)();
EXPECT_EQ(sop.opcode, op->opcode());
}
TEST_P(JSSharedOperatorTest, Properties) {
JSOperatorBuilder javascript(zone());
const SharedOperator& sop = GetParam();
const Operator* op = (javascript.*sop.constructor)();
EXPECT_EQ(sop.properties, op->properties());
}
INSTANTIATE_TEST_CASE_P(JSOperatorTest, JSSharedOperatorTest,
::testing::ValuesIn(kSharedOperators));
} // namespace compiler
} // namespace internal
} // namespace v8
// 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.
#include "src/compiler/js-operator.h"
#include <limits>
#include "src/base/lazy-instance.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
namespace v8 {
namespace internal {
namespace compiler {
const CallFunctionParameters& CallFunctionParametersOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSCallFunction, op->opcode());
return OpParameter<CallFunctionParameters>(op);
}
const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSCallRuntime, op->opcode());
return OpParameter<CallRuntimeParameters>(op);
}
ContextAccess::ContextAccess(size_t depth, size_t index, bool immutable)
: immutable_(immutable),
depth_(static_cast<uint16_t>(depth)),
index_(static_cast<uint32_t>(index)) {
DCHECK(depth <= std::numeric_limits<uint16_t>::max());
DCHECK(index <= std::numeric_limits<uint32_t>::max());
}
bool operator==(const ContextAccess& lhs, const ContextAccess& rhs) {
return lhs.depth() == rhs.depth() && lhs.index() == rhs.index() &&
lhs.immutable() == rhs.immutable();
}
bool operator!=(const ContextAccess& lhs, const ContextAccess& rhs) {
return !(lhs == rhs);
}
const ContextAccess& ContextAccessOf(const Operator* op) {
DCHECK(op->opcode() == IrOpcode::kJSLoadContext ||
op->opcode() == IrOpcode::kJSStoreContext);
return OpParameter<ContextAccess>(op);
}
const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode());
return OpParameter<LoadNamedParameters>(op);
}
const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSStoreNamed, op->opcode());
return OpParameter<StoreNamedParameters>(op);
}
// Specialization for static parameters of type {ContextAccess}.
template <>
struct StaticParameterTraits<ContextAccess> {
static std::ostream& PrintTo(std::ostream& os, const ContextAccess& access) {
return os << access.depth() << "," << access.index()
<< (access.immutable() ? ",imm" : "");
}
static int HashCode(const ContextAccess& access) {
return static_cast<int>((access.depth() << 16) | (access.index() & 0xffff));
}
static bool Equals(const ContextAccess& lhs, const ContextAccess& rhs) {
return lhs == rhs;
}
};
// Specialization for static parameters of type {Runtime::FunctionId}.
template <>
struct StaticParameterTraits<Runtime::FunctionId> {
static std::ostream& PrintTo(std::ostream& os, Runtime::FunctionId val) {
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;
}
};
#define SHARED_OP_LIST(V) \
V(Equal, Operator::kNoProperties, 2, 1) \
V(NotEqual, Operator::kNoProperties, 2, 1) \
V(StrictEqual, Operator::kPure, 2, 1) \
V(StrictNotEqual, Operator::kPure, 2, 1) \
V(LessThan, Operator::kNoProperties, 2, 1) \
V(GreaterThan, Operator::kNoProperties, 2, 1) \
V(LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(GreaterThanOrEqual, Operator::kNoProperties, 2, 1) \
V(BitwiseOr, Operator::kNoProperties, 2, 1) \
V(BitwiseXor, Operator::kNoProperties, 2, 1) \
V(BitwiseAnd, Operator::kNoProperties, 2, 1) \
V(ShiftLeft, Operator::kNoProperties, 2, 1) \
V(ShiftRight, Operator::kNoProperties, 2, 1) \
V(ShiftRightLogical, Operator::kNoProperties, 2, 1) \
V(Add, Operator::kNoProperties, 2, 1) \
V(Subtract, Operator::kNoProperties, 2, 1) \
V(Multiply, Operator::kNoProperties, 2, 1) \
V(Divide, Operator::kNoProperties, 2, 1) \
V(Modulus, Operator::kNoProperties, 2, 1) \
V(UnaryNot, Operator::kNoProperties, 1, 1) \
V(ToBoolean, Operator::kNoProperties, 1, 1) \
V(ToNumber, Operator::kNoProperties, 1, 1) \
V(ToString, Operator::kNoProperties, 1, 1) \
V(ToName, Operator::kNoProperties, 1, 1) \
V(ToObject, Operator::kNoProperties, 1, 1) \
V(Yield, Operator::kNoProperties, 1, 1) \
V(Create, Operator::kEliminatable, 0, 1) \
V(LoadProperty, Operator::kNoProperties, 2, 1) \
V(HasProperty, Operator::kNoProperties, 2, 1) \
V(TypeOf, Operator::kPure, 1, 1) \
V(InstanceOf, Operator::kNoProperties, 2, 1) \
V(Debugger, Operator::kNoProperties, 0, 0) \
V(CreateFunctionContext, Operator::kNoProperties, 1, 1) \
V(CreateWithContext, Operator::kNoProperties, 2, 1) \
V(CreateBlockContext, Operator::kNoProperties, 2, 1) \
V(CreateModuleContext, Operator::kNoProperties, 2, 1) \
V(CreateGlobalContext, Operator::kNoProperties, 2, 1)
struct JSOperatorBuilderImpl FINAL {
#define SHARED(Name, properties, value_input_count, value_output_count) \
struct Name##Operator FINAL : public SimpleOperator { \
Name##Operator() \
: SimpleOperator(IrOpcode::kJS##Name, properties, value_input_count, \
value_output_count, "JS" #Name) {} \
}; \
Name##Operator k##Name##Operator;
SHARED_OP_LIST(SHARED)
#undef SHARED
};
static base::LazyInstance<JSOperatorBuilderImpl>::type kImpl =
LAZY_INSTANCE_INITIALIZER;
JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
: impl_(kImpl.Get()), zone_(zone) {}
#define SHARED(Name, properties, value_input_count, value_output_count) \
const Operator* JSOperatorBuilder::Name() { return &impl_.k##Name##Operator; }
SHARED_OP_LIST(SHARED)
#undef SHARED
const Operator* JSOperatorBuilder::CallFunction(size_t arity,
CallFunctionFlags flags) {
CallFunctionParameters parameters(arity, flags);
return new (zone()) Operator1<CallFunctionParameters>(
IrOpcode::kJSCallFunction, Operator::kNoProperties,
static_cast<int>(parameters.arity()), 1, "JSCallFunction", parameters);
}
const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
size_t arity) {
CallRuntimeParameters parameters(id, arity);
const Runtime::Function* f = Runtime::FunctionForId(parameters.id());
int arguments = static_cast<int>(parameters.arity());
DCHECK(f->nargs == -1 || f->nargs == arguments);
return new (zone()) Operator1<CallRuntimeParameters>(
IrOpcode::kJSCallRuntime, Operator::kNoProperties, arguments,
f->result_size, "JSCallRuntime", parameters);
}
const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
return new (zone())
Operator1<int>(IrOpcode::kJSCallConstruct, Operator::kNoProperties,
arguments, 1, "JSCallConstruct", arguments);
}
const Operator* JSOperatorBuilder::LoadNamed(const Unique<Name>& name,
ContextualMode contextual_mode) {
LoadNamedParameters parameters(name, contextual_mode);
return new (zone()) Operator1<LoadNamedParameters>(
IrOpcode::kJSLoadNamed, Operator::kNoProperties, 1, 1, "JSLoadNamed",
parameters);
}
const Operator* JSOperatorBuilder::StoreProperty(StrictMode strict_mode) {
return new (zone())
Operator1<StrictMode>(IrOpcode::kJSStoreProperty, Operator::kNoProperties,
3, 0, "JSStoreProperty", strict_mode);
}
const Operator* JSOperatorBuilder::StoreNamed(StrictMode strict_mode,
const Unique<Name>& name) {
StoreNamedParameters parameters(strict_mode, name);
return new (zone()) Operator1<StoreNamedParameters>(
IrOpcode::kJSStoreNamed, Operator::kNoProperties, 2, 0, "JSStoreNamed",
parameters);
}
const Operator* JSOperatorBuilder::DeleteProperty(StrictMode strict_mode) {
return new (zone()) Operator1<StrictMode>(IrOpcode::kJSDeleteProperty,
Operator::kNoProperties, 2, 1,
"JSDeleteProperty", strict_mode);
}
const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
bool immutable) {
ContextAccess access(depth, index, immutable);
return new (zone()) Operator1<ContextAccess>(
IrOpcode::kJSLoadContext, Operator::kEliminatable | Operator::kNoWrite, 1,
1, "JSLoadContext", access);
}
const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
ContextAccess access(depth, index, false);
return new (zone()) Operator1<ContextAccess>(IrOpcode::kJSStoreContext,
Operator::kNoProperties, 2, 0,
"JSStoreContext", access);
}
const Operator* JSOperatorBuilder::CreateCatchContext(
const Unique<String>& name) {
return new (zone()) Operator1<Unique<String> >(
IrOpcode::kJSCreateCatchContext, Operator::kNoProperties, 1, 1,
"JSCreateCatchContext", name);
}
} // namespace compiler
} // namespace internal
} // namespace v8
...@@ -5,28 +5,63 @@ ...@@ -5,28 +5,63 @@
#ifndef V8_COMPILER_JS_OPERATOR_H_ #ifndef V8_COMPILER_JS_OPERATOR_H_
#define V8_COMPILER_JS_OPERATOR_H_ #define V8_COMPILER_JS_OPERATOR_H_
#include "src/compiler/linkage.h" #include "src/runtime/runtime.h"
#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
#include "src/unique.h" #include "src/unique.h"
#include "src/zone.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace compiler { namespace compiler {
// Forward declarations.
class Operator;
struct JSOperatorBuilderImpl;
// Defines the arity and the call flags for a JavaScript function call. This is
// used as a parameter by JSCallFunction operators.
class CallFunctionParameters FINAL {
public:
CallFunctionParameters(size_t arity, CallFunctionFlags flags)
: arity_(arity), flags_(flags) {}
size_t arity() const { return arity_; }
CallFunctionFlags flags() const { return flags_; }
private:
const size_t arity_;
const CallFunctionFlags flags_;
};
const CallFunctionParameters& CallFunctionParametersOf(const Operator* op);
// Defines the arity and the ID for a runtime function call. This is used as a
// parameter by JSCallRuntime operators.
class CallRuntimeParameters FINAL {
public:
CallRuntimeParameters(Runtime::FunctionId id, size_t arity)
: id_(id), arity_(arity) {}
Runtime::FunctionId id() const { return id_; }
size_t arity() const { return arity_; }
private:
const Runtime::FunctionId id_;
const size_t arity_;
};
const CallRuntimeParameters& CallRuntimeParametersOf(const Operator* op);
// Defines the location of a context slot relative to a specific scope. This is // 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 // used as a parameter by JSLoadContext and JSStoreContext operators and allows
// accessing a context-allocated variable without keeping track of the scope. // accessing a context-allocated variable without keeping track of the scope.
class ContextAccess { class ContextAccess FINAL {
public: public:
ContextAccess(int depth, int index, bool immutable) ContextAccess(size_t depth, size_t index, bool immutable);
: immutable_(immutable), depth_(depth), index_(index) {
DCHECK(0 <= depth && depth <= kMaxUInt16); size_t depth() const { return depth_; }
DCHECK(0 <= index && static_cast<uint32_t>(index) <= kMaxUInt32); size_t index() const { return index_; }
}
int depth() const { return depth_; }
int index() const { return index_; }
bool immutable() const { return immutable_; } bool immutable() const { return immutable_; }
private: private:
...@@ -37,194 +72,121 @@ class ContextAccess { ...@@ -37,194 +72,121 @@ class ContextAccess {
const uint32_t index_; const uint32_t index_;
}; };
bool operator==(const ContextAccess& lhs, const ContextAccess& rhs);
bool operator!=(const ContextAccess& lhs, const ContextAccess& rhs);
const ContextAccess& ContextAccessOf(const Operator* op);
// Defines the property being loaded from an object by a named load. This is // Defines the property being loaded from an object by a named load. This is
// used as a parameter by JSLoadNamed operators. // used as a parameter by JSLoadNamed operators.
struct LoadNamedParameters { class LoadNamedParameters FINAL {
Unique<Name> name; public:
ContextualMode contextual_mode; LoadNamedParameters(const Unique<Name>& name, ContextualMode contextual_mode)
}; : name_(name), contextual_mode_(contextual_mode) {}
// Defines the arity and the call flags for a JavaScript function call. This is const Unique<Name>& name() const { return name_; }
// used as a parameter by JSCall operators. ContextualMode contextual_mode() const { return contextual_mode_; }
struct CallParameters {
int arity; private:
CallFunctionFlags flags; const Unique<Name> name_;
const ContextualMode contextual_mode_;
}; };
const LoadNamedParameters& LoadNamedParametersOf(const Operator* op);
// Defines the property being stored to an object by a named store. This is // Defines the property being stored to an object by a named store. This is
// used as a parameter by JSStoreNamed operators. // used as a parameter by JSStoreNamed operators.
struct StoreNamedParameters { class StoreNamedParameters FINAL {
StrictMode strict_mode; public:
Unique<Name> name; StoreNamedParameters(StrictMode strict_mode, const Unique<Name>& name)
: strict_mode_(strict_mode), name_(name) {}
StrictMode strict_mode() const { return strict_mode_; }
const Unique<Name>& name() const { return name_; }
private:
const StrictMode strict_mode_;
const Unique<Name> name_;
}; };
const StoreNamedParameters& StoreNamedParametersOf(const Operator* op);
// Interface for building JavaScript-level operators, e.g. directly from the // Interface for building JavaScript-level operators, e.g. directly from the
// AST. Most operators have no parameters, thus can be globally shared for all // AST. Most operators have no parameters, thus can be globally shared for all
// graphs. // graphs.
class JSOperatorBuilder { class JSOperatorBuilder FINAL {
public: public:
explicit JSOperatorBuilder(Zone* zone) : zone_(zone) {} explicit JSOperatorBuilder(Zone* zone);
#define SIMPLE(name, properties, inputs, outputs) \ const Operator* Equal();
return new (zone_) \ const Operator* NotEqual();
SimpleOperator(IrOpcode::k##name, properties, inputs, outputs, #name); const Operator* StrictEqual();
const Operator* StrictNotEqual();
#define NOPROPS(name, inputs, outputs) \ const Operator* LessThan();
SIMPLE(name, Operator::kNoProperties, inputs, outputs) const Operator* GreaterThan();
const Operator* LessThanOrEqual();
#define OP1(name, ptype, pname, properties, inputs, outputs) \ const Operator* GreaterThanOrEqual();
return new (zone_) Operator1<ptype>(IrOpcode::k##name, properties, inputs, \ const Operator* BitwiseOr();
outputs, #name, pname) const Operator* BitwiseXor();
const Operator* BitwiseAnd();
#define BINOP(name) NOPROPS(name, 2, 1) const Operator* ShiftLeft();
#define UNOP(name) NOPROPS(name, 1, 1) const Operator* ShiftRight();
const Operator* ShiftRightLogical();
#define PURE_BINOP(name) SIMPLE(name, Operator::kPure, 2, 1) const Operator* Add();
const Operator* Subtract();
const Operator* Equal() { BINOP(JSEqual); } const Operator* Multiply();
const Operator* NotEqual() { BINOP(JSNotEqual); } const Operator* Divide();
const Operator* StrictEqual() { PURE_BINOP(JSStrictEqual); } const Operator* Modulus();
const Operator* StrictNotEqual() { PURE_BINOP(JSStrictNotEqual); }
const Operator* LessThan() { BINOP(JSLessThan); } const Operator* UnaryNot();
const Operator* GreaterThan() { BINOP(JSGreaterThan); } const Operator* ToBoolean();
const Operator* LessThanOrEqual() { BINOP(JSLessThanOrEqual); } const Operator* ToNumber();
const Operator* GreaterThanOrEqual() { BINOP(JSGreaterThanOrEqual); } const Operator* ToString();
const Operator* BitwiseOr() { BINOP(JSBitwiseOr); } const Operator* ToName();
const Operator* BitwiseXor() { BINOP(JSBitwiseXor); } const Operator* ToObject();
const Operator* BitwiseAnd() { BINOP(JSBitwiseAnd); } const Operator* Yield();
const Operator* ShiftLeft() { BINOP(JSShiftLeft); }
const Operator* ShiftRight() { BINOP(JSShiftRight); } const Operator* Create();
const Operator* ShiftRightLogical() { BINOP(JSShiftRightLogical); }
const Operator* Add() { BINOP(JSAdd); } const Operator* CallFunction(size_t arity, CallFunctionFlags flags);
const Operator* Subtract() { BINOP(JSSubtract); } const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
const Operator* Multiply() { BINOP(JSMultiply); }
const Operator* Divide() { BINOP(JSDivide); } const Operator* CallConstruct(int arguments);
const Operator* Modulus() { BINOP(JSModulus); }
const Operator* LoadProperty();
const Operator* UnaryNot() { UNOP(JSUnaryNot); } const Operator* LoadNamed(const Unique<Name>& name,
const Operator* ToBoolean() { UNOP(JSToBoolean); } ContextualMode contextual_mode = NOT_CONTEXTUAL);
const Operator* ToNumber() { UNOP(JSToNumber); }
const Operator* ToString() { UNOP(JSToString); } const Operator* StoreProperty(StrictMode strict_mode);
const Operator* ToName() { UNOP(JSToName); } const Operator* StoreNamed(StrictMode strict_mode, const Unique<Name>& name);
const Operator* ToObject() { UNOP(JSToObject); }
const Operator* Yield() { UNOP(JSYield); } const Operator* DeleteProperty(StrictMode strict_mode);
const Operator* Create() { SIMPLE(JSCreate, Operator::kEliminatable, 0, 1); } const Operator* HasProperty();
const Operator* Call(int arguments, CallFunctionFlags flags) { const Operator* LoadContext(size_t depth, size_t index, bool immutable);
CallParameters parameters = {arguments, flags}; const Operator* StoreContext(size_t depth, size_t index);
OP1(JSCallFunction, CallParameters, parameters, Operator::kNoProperties,
arguments, 1); const Operator* TypeOf();
} const Operator* InstanceOf();
const Operator* Debugger();
const Operator* CallNew(int arguments) {
return new (zone_)
Operator1<int>(IrOpcode::kJSCallConstruct, Operator::kNoProperties,
arguments, 1, "JSCallConstruct", arguments);
}
const Operator* LoadProperty() { BINOP(JSLoadProperty); }
const Operator* LoadNamed(Unique<Name> name,
ContextualMode contextual_mode = NOT_CONTEXTUAL) {
LoadNamedParameters parameters = {name, contextual_mode};
OP1(JSLoadNamed, LoadNamedParameters, parameters, Operator::kNoProperties,
1, 1);
}
const Operator* StoreProperty(StrictMode strict_mode) {
OP1(JSStoreProperty, StrictMode, strict_mode, Operator::kNoProperties, 3,
0);
}
const Operator* StoreNamed(StrictMode strict_mode, Unique<Name> name) {
StoreNamedParameters parameters = {strict_mode, name};
OP1(JSStoreNamed, StoreNamedParameters, parameters, Operator::kNoProperties,
2, 0);
}
const Operator* DeleteProperty(StrictMode strict_mode) {
OP1(JSDeleteProperty, StrictMode, strict_mode, Operator::kNoProperties, 2,
1);
}
const Operator* HasProperty() { NOPROPS(JSHasProperty, 2, 1); }
const 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);
}
const Operator* StoreContext(uint16_t depth, uint32_t index) {
ContextAccess access(depth, index, false);
OP1(JSStoreContext, ContextAccess, access, Operator::kNoProperties, 2, 0);
}
const Operator* TypeOf() { SIMPLE(JSTypeOf, Operator::kPure, 1, 1); }
const Operator* InstanceOf() { NOPROPS(JSInstanceOf, 2, 1); }
const Operator* Debugger() { NOPROPS(JSDebugger, 0, 0); }
// TODO(titzer): nail down the static parts of each of these context flavors. // TODO(titzer): nail down the static parts of each of these context flavors.
const Operator* CreateFunctionContext() { const Operator* CreateFunctionContext();
NOPROPS(JSCreateFunctionContext, 1, 1); const Operator* CreateCatchContext(const Unique<String>& name);
} const Operator* CreateWithContext();
const Operator* CreateCatchContext(Unique<String> name) { const Operator* CreateBlockContext();
OP1(JSCreateCatchContext, Unique<String>, name, Operator::kNoProperties, 1, const Operator* CreateModuleContext();
1); const Operator* CreateGlobalContext();
}
const Operator* CreateWithContext() { NOPROPS(JSCreateWithContext, 2, 1); }
const Operator* CreateBlockContext() { NOPROPS(JSCreateBlockContext, 2, 1); }
const Operator* CreateModuleContext() {
NOPROPS(JSCreateModuleContext, 2, 1);
}
const Operator* CreateGlobalContext() {
NOPROPS(JSCreateGlobalContext, 2, 1);
}
const Operator* Runtime(Runtime::FunctionId function, int arguments) {
const Runtime::Function* f = Runtime::FunctionForId(function);
DCHECK(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: private:
Zone* zone_; Zone* zone() const { return zone_; }
};
// Specialization for static parameters of type {ContextAccess}.
template <>
struct StaticParameterTraits<ContextAccess> {
static std::ostream& PrintTo(std::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}. const JSOperatorBuilderImpl& impl_;
template <> Zone* const zone_;
struct StaticParameterTraits<Runtime::FunctionId> {
static std::ostream& PrintTo(std::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 compiler } // namespace compiler
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/compiler/machine-operator-reducer.h" #include "src/compiler/machine-operator-reducer.h"
#include "src/base/bits.h" #include "src/base/bits.h"
#include "src/codegen.h"
#include "src/compiler/generic-node-inl.h" #include "src/compiler/generic-node-inl.h"
#include "src/compiler/graph.h" #include "src/compiler/graph.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/compiler/common-operator.h" #include "src/compiler/common-operator.h"
#include "src/compiler/js-operator.h" #include "src/compiler/js-operator.h"
#include "src/compiler/linkage.h"
#include "src/compiler/opcodes.h" #include "src/compiler/opcodes.h"
#include "src/compiler/operator-properties.h" #include "src/compiler/operator-properties.h"
...@@ -40,8 +41,8 @@ inline bool OperatorProperties::HasFrameStateInput(const Operator* op) { ...@@ -40,8 +41,8 @@ inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
case IrOpcode::kFrameState: case IrOpcode::kFrameState:
return true; return true;
case IrOpcode::kJSCallRuntime: { case IrOpcode::kJSCallRuntime: {
Runtime::FunctionId function = OpParameter<Runtime::FunctionId>(op); const CallRuntimeParameters& p = CallRuntimeParametersOf(op);
return Linkage::NeedsFrameState(function); return Linkage::NeedsFrameState(p.id());
} }
// Strict equality cannot lazily deoptimize. // Strict equality cannot lazily deoptimize.
......
...@@ -557,7 +557,7 @@ Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { ...@@ -557,7 +557,7 @@ Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
// bound. // bound.
// TODO(rossberg): Could use scope info to fix upper bounds for constant // TODO(rossberg): Could use scope info to fix upper bounds for constant
// bindings if we know that this code is never shared. // bindings if we know that this code is never shared.
for (int i = access.depth(); i > 0; --i) { for (size_t i = access.depth(); i > 0; --i) {
if (context_type->IsContext()) { if (context_type->IsContext()) {
context_type = context_type->AsContext()->Outer(); context_type = context_type->AsContext()->Outer();
if (context_type->IsConstant()) { if (context_type->IsConstant()) {
...@@ -571,7 +571,8 @@ Bounds Typer::Visitor::TypeJSLoadContext(Node* node) { ...@@ -571,7 +571,8 @@ Bounds Typer::Visitor::TypeJSLoadContext(Node* node) {
return Bounds::Unbounded(zone()); return Bounds::Unbounded(zone());
} else { } else {
Handle<Object> value = Handle<Object> value =
handle(context.ToHandleChecked()->get(access.index()), isolate()); handle(context.ToHandleChecked()->get(static_cast<int>(access.index())),
isolate());
Type* lower = TypeConstant(value); Type* lower = TypeConstant(value);
return Bounds(lower, Type::Any(zone())); return Bounds(lower, Type::Any(zone()));
} }
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define V8_RUNTIME_H_ #define V8_RUNTIME_H_
#include "src/allocation.h" #include "src/allocation.h"
#include "src/objects.h"
#include "src/zone.h" #include "src/zone.h"
namespace v8 { namespace v8 {
......
...@@ -95,8 +95,8 @@ TEST(ReduceJSLoadContext) { ...@@ -95,8 +95,8 @@ TEST(ReduceJSLoadContext) {
HeapObjectMatcher<Context> match(new_context_input); HeapObjectMatcher<Context> match(new_context_input);
CHECK_EQ(*native, *match.Value().handle()); CHECK_EQ(*native, *match.Value().handle());
ContextAccess access = OpParameter<ContextAccess>(r.replacement()); ContextAccess access = OpParameter<ContextAccess>(r.replacement());
CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index()));
CHECK_EQ(0, access.depth()); CHECK_EQ(0, static_cast<int>(access.depth()));
CHECK_EQ(false, access.immutable()); CHECK_EQ(false, access.immutable());
} }
...@@ -175,8 +175,8 @@ TEST(ReduceJSStoreContext) { ...@@ -175,8 +175,8 @@ TEST(ReduceJSStoreContext) {
HeapObjectMatcher<Context> match(new_context_input); HeapObjectMatcher<Context> match(new_context_input);
CHECK_EQ(*native, *match.Value().handle()); CHECK_EQ(*native, *match.Value().handle());
ContextAccess access = OpParameter<ContextAccess>(r.replacement()); ContextAccess access = OpParameter<ContextAccess>(r.replacement());
CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, access.index()); CHECK_EQ(Context::GLOBAL_EVAL_FUN_INDEX, static_cast<int>(access.index()));
CHECK_EQ(0, access.depth()); CHECK_EQ(0, static_cast<int>(access.depth()));
CHECK_EQ(false, access.immutable()); CHECK_EQ(false, access.immutable());
} }
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "test/cctest/cctest.h" #include "test/cctest/cctest.h"
#include "src/base/utils/random-number-generator.h" #include "src/base/utils/random-number-generator.h"
#include "src/codegen.h"
#include "src/compiler/graph-inl.h" #include "src/compiler/graph-inl.h"
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator-reducer.h" #include "src/compiler/machine-operator-reducer.h"
......
...@@ -431,6 +431,7 @@ ...@@ -431,6 +431,7 @@
'../../src/compiler/js-graph.h', '../../src/compiler/js-graph.h',
'../../src/compiler/js-inlining.cc', '../../src/compiler/js-inlining.cc',
'../../src/compiler/js-inlining.h', '../../src/compiler/js-inlining.h',
'../../src/compiler/js-operator.cc',
'../../src/compiler/js-operator.h', '../../src/compiler/js-operator.h',
'../../src/compiler/js-typed-lowering.cc', '../../src/compiler/js-typed-lowering.cc',
'../../src/compiler/js-typed-lowering.h', '../../src/compiler/js-typed-lowering.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment