8000 Bug fix/remove v8 executor (#4756) · mnemosdev/arangodb@67e7e41 · GitHub
[go: up one dir, main page]

Skip to content

Commit 67e7e41

Browse files
authored
Bug fix/remove v8 executor (arangodb#4756)
1 parent 4b666de commit 67e7e41

26 files changed

+403
-1628
lines changed

arangod/Aql/Ast.cpp

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
#include "Aql/Function.h"
3030
#include "Aql/Graphs.h"
3131
#include "Aql/Query.h"
32-
#include "Aql/V8Executor.h"
3332
#include "Basics/Exceptions.h"
3433
#include "Basics/StringRef.h"
3534
#include "Basics/StringUtils.h"
@@ -2604,28 +2603,6 @@ AstNode* Ast::createArithmeticResultNode(double value) {
26042603
return createNodeValueDouble(value);
26052604
}
26062605

2607-
/// @brief executes an expression with constant parameters in V8
2608-
AstNode* Ast::executeConstExpressionV8(AstNode const* node) {
2609-
// must enter v8 before we can execute any expression
2610-
_query->enterContext();
2611-
ISOLATE;
2612-
v8::HandleScope scope(isolate); // do not delete this!
2613-
2614-
TRI_ASSERT(_query->trx() != nullptr);
2615-
transaction::BuilderLeaser builder(_query->trx());
2616-
2617-
int res = _query->v8Executor()->executeExpression(_query, node, *builder.get());
2618-
2619-
if (res != TRI_ERROR_NO_ERROR) {
2620-
THROW_ARANGO_EXCEPTION(res);
2621-
}
2622-
2623-
// context is not left here, but later
2624-
// this allows re-using the same context for multiple expressions
2625-
2626-
return nodeFromVPack(builder->slice(), true);
2627-
}
2628-
26292606
/// @brief optimizes the unary operators + and -
26302607
/// the unary plus will be converted into a simple value node if the operand of
26312608
/// the operation is a constant number
@@ -2865,17 +2842,12 @@ AstNode* Ast::optimizeBinaryOperatorRelational(AstNode* node) {
28652842
Expression exp(nullptr, this, node);
28662843
FixedVarExpressionContext context;
28672844
bool mustDestroy;
2868-
// execute the expression using the C++ variant
2845+
28692846
AqlValue a = exp.execute(_query->trx(), &context, mustDestroy);
28702847
AqlValueGuard guard(a, mustDestroy);
28712848

2872-
// we cannot create slices from types Range and Docvec easily
2873-
if (!a.isRange() && !a.isDocvec()) {
2874-
return nodeFromVPack(a.slice(), true);
2875-
}
2876-
2877-
// simply fall through to V8 now
2878-
return executeConstExpressionV8(node);
2849+
AqlValueMaterializer materializer(_query->trx());
2850+
return nodeFromVPack(materializer.slice(a, false), true);
28792851
}
28802852

28812853
/// @brief optimizes the binary arithmetic operators +, -, *, / and %
@@ -3146,24 +3118,22 @@ AstNode* Ast::optimizeFunctionCall(AstNode* node) {
31463118
// place. note that the transaction has not necessarily been
31473119
// started yet...
31483120
TRI_ASSERT(_query->trx() != nullptr);
3149-
3150-
if (func->hasImplementation() && node->isSimple()) {
3151-
Expression exp(nullptr, this, node);
3152-
FixedVarExpressionContext context;
3153-
bool mustDestroy;
3154-
// execute the expression using the C++ variant
3155-
AqlValue a = exp.execute(_query->trx(), &context, mustDestroy);
3156-
AqlValueGuard guard(a, mustDestroy);
3157-
3158-
// we cannot create slices from types Range and Docvec easily
3159-
if (!a.isRange() && !a.isDocvec()) {
3160-
return nodeFromVPack(a.slice(), true);
3161-
}
3162-
// simply fall through to V8 now
3121+
3122+
if (node->willUseV8()) {
3123+
// if the expression is going to use V8 internally, we do not
3124+
// bother to optimize it here
3125+
return node;
31633126
}
31643127

3165-
// execute the expression using V8
3166-
return executeConstExpressionV8(node);
3128+
Expression exp(nullptr, this, node);
3129+
FixedVarExpressionContext context;
3130+
bool mustDestroy;
3131+
3132+
AqlValue a = exp.execute(_query->trx(), &context, mustDestroy);
3133+
AqlValueGuard guard(a, mustDestroy);
3134+
3135+
AqlValueMaterializer materializer(_query->trx());
3136+
return nodeFromVPack(materializer.slice(a, false), true);
31673137
}
31683138

31693139
/// @brief optimizes a reference to a variable

arangod/Aql/Ast.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -459,13 +459,9 @@ class Ast {
459459
/// @brief create a number node for an arithmetic result, double
460460
AstNode* createArithmeticResultNode(double);
461461

462-
/// @brief executes an expression with constant parameters in V8
463-
AstNode* executeConstExpressionV8(AstNode const*);
464-
465462
/// @brief optimizes the unary operators + and -
466463
/// the unary plus will be converted into a simple value node if the operand
467-
/// of
468-
/// the operation is a constant number
464+
/// of the operation is a constant number
469465
AstNode* optimizeUnaryOperatorArithmetic(AstNode*);
470466

471467
/// @brief optimizes the unary operator NOT with a non-constant expression

arangod/Aql/AstNode.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,6 @@
4747
#include <velocypack/velocypack-aliases.h>
4848
#include <array>
4949

50-
namespace {
51-
52-
arangodb::StringRef const VIEW_NODE_SUFFIX("\0v", 2);
53-
arangodb::StringRef const COLLECTION_NODE_SUFFIX("\0c", 2);
54-
55-
}
56-
5750
using namespace arangodb::aql;
5851

5952
std::unordered_map<int, std::string const> const AstNode::Operators{
@@ -1542,14 +1535,6 @@ bool AstNode::isSimple() const {
15421535
auto func = static_cast<Function*>(getData());
15431536
TRI_ASSERT(func != nullptr);
15441537

1545-
if (func->implementation == nullptr) {
1546-
// no C++ handler available for function
1547-
setFlag(DETERMINED_SIMPLE);
1548-
return false;
1549-
}
1550-
1551-
TRI_ASSERT(func->implementation != nullptr);
1552-
15531538
TRI_ASSERT(numMembers() == 1);
15541539

15551540
// check if there is a C++ function handler condition
@@ -1584,11 +1569,63 @@ bool AstNode::isSimple() const {
15841569
setFlag(DETERMINED_SIMPLE, VALUE_SIMPLE);
15851570
return true;
15861571
}
1572+
1573+
if (type == NODE_TYPE_FCALL_USER) {
1574+
setFlag(DETERMINED_SIMPLE, VALUE_SIMPLE);
1575+
return true;
1576+
}
15871577

15881578
setFlag(DETERMINED_SIMPLE);
15891579
return false;
15901580
}
15911581

1582+
/// @brief whether or not a node will use V8 internally
1583+
bool AstNode::willUseV8() const {
1584+
if (hasFlag(DETERMINED_V8)) {
1585+
// fast track exit
1586+
return hasFlag(VALUE_V8);
1587+
}
1588+
1589+
if (type == NODE_TYPE_FCALL_USER) {
1590+
// user-defined function will always use v8
1591+
setFlag(DETERMINED_V8, VALUE_V8);
1592+
return true;
1593+
}
1594+
1595+
if (type == NODE_TYPE_FCALL) {
1596+
// some functions have C++ handlers
1597+
// check if the called function is one of them
1598+
auto func = static_cast<Function*>(getData());
1599+
TRI_ASSERT(func != nullptr);
1600+
1601+
if (func->implementation == nullptr) {
1602+
// a function without a V8 implementation
1603+
setFlag(DETERMINED_V8, VALUE_V8);
1604+
return true;
1605+
}
1606+
1607+
if (func->condition && !func->condition()) {
1608+
// a function with an execution condition
1609+
setFlag(DETERMINED_V8, VALUE_V8);
1610+
return true;
1611+
}
1612+
}
1613+
1614+
size_t const n = numMembers();
1615+
1616+
for (size_t i = 0; i < n; ++i) {
1617+
auto member = getMemberUnchecked(i);
1618+
1619+
if (member->willUseV8()) {
1620+
setFlag(DETERMINED_V8, VALUE_V8);
1621+
return true;
1622+
}
1623+
}
1624+
1625+
setFlag(DETERMINED_V8);
1626+
return false;
1627+
}
1628+
15921629
/// @brief whether or not a node has a constant value
15931630
bool AstNode::isConstant() const {
15941631
if (hasFlag(DETERMINED_CONSTANT)) {

arangod/Aql/AstNode.h

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -52,35 +52,26 @@ typedef uint32_t AstNodeFlagsType;
5252
/// the flags are used to prevent repeated calculations of node properties
5353
/// (e.g. is the node value constant, sorted etc.)
5454
enum AstNodeFlagType : AstNodeFlagsType {
55-
DETERMINED_SORTED = 1, // node is a list and its members are sorted asc.
56-
DETERMINED_CONSTANT = 2, // node value is constant (i.e. not dynamic)
57-
DETERMINED_SIMPLE =
58-
4, // node value is simple (i.e. for use in a simple expression)
59-
DETERMINED_THROWS = 8, // node can throw an exception
60-
DETERMINED_NONDETERMINISTIC =
61-
16, // node produces non-deterministic result (e.g. function call nodes)
62-
DETERMINED_RUNONDBSERVER =
63-
32, // node can run on the DB server in a cluster setup
64-
DETERMINED_CHECKUNIQUENESS = 64, // object's keys must be checked for uniqueness
65-
66-
VALUE_SORTED = 128, // node is a list and its members are sorted asc.
67-
VALUE_CONSTANT = 256, // node value is constant (i.e. not dynamic)
68-
VALUE_SIMPLE =
69-
512, // node value is simple (i.e. for use in a simple expression)
70-
VALUE_THROWS = 1024, // node can throw an exception
71-
VALUE_NONDETERMINISTIC = 2048, // node produces non-deterministic result
72-
// (e.g. function call nodes)
73-
VALUE_RUNONDBSERVER =
74-
4096, // node can run on the DB server in a cluster setup
75-
VALUE_CHECKUNIQUENESS = 8192, // object's keys must be checked for uniqueness
76-
77-
FLAG_KEEP_VARIABLENAME = 16384, // node is a reference to a variable name,
78-
// not the variable value (used in KEEP
79-
// nodes)
80-
FLAG_BIND_PARAMETER = 32768, // node was created from a bind parameter
81-
FLAG_FINALIZED = 65536, // node has been finalized and should not be
82-
// modified; only set and checked in
83-
// maintainer mode
55+
DETERMINED_SORTED = 0x0000001, // node is a list and its members are sorted asc.
56+
DETERMINED_CONSTANT = 0x0000002, // node value is constant (i.e. not dynamic)
57+
DETERMINED_SIMPLE = 0x0000004, // node value is simple (i.e. for use in a simple expression)
58+
DETERMINED_THROWS = 0x0000008, // node can throw an exception
59+
DETERMINED_NONDETERMINISTIC = 0x0000010, // node produces non-deterministic result (e.g. function call nodes)
60+
DETERMINED_RUNONDBSERVER = 0x0000020, // node can run on the DB server in a cluster setup
61+
DETERMINED_CHECKUNIQUENESS = 0x0000040, // object's keys must be checked for uniqueness
62+
DETERMINED_V8 = 0x0000080, // node will use V8 internally
63+
64+
VALUE_SORTED = 0x0000100, // node is a list and its members are sorted asc.
65+
VALUE_CONSTANT = 0x0000200, // node value is constant (i.e. not dynamic)
66+
VALUE_SIMPLE = 0x0000400, // node value is simple (i.e. for use in a simple expression)
67+
VALUE_THROWS = 0x0000800, // node can throw an exception
68+
VALUE_NONDETERMINISTIC = 0x0001000, // node produces non-deterministic result (e.g. function call nodes)
69+
VALUE_RUNONDBSERVER = 0x0002000, // node can run on the DB server in a cluster setup
70+
VALUE_CHECKUNIQUENESS = 0x0004000, // object's keys must be checked for uniqueness
71+
VALUE_V8 = 0x0008000, // node will use V8 internally
72+
FLAG_KEEP_VARIABLENAME = 0x0010000, // node is a reference to a variable name, not the variable value (used in KEEP nodes)
73+
FLAG_BIND_PARAMETER = 0x0020000, // node was created from a bind parameter
74+
FLAG_FINALIZED = 0x0040000, // node has been finalized and should not be modified; only set and checked in maintainer mode
8475
};
8576

8677
/// @brief enumeration of AST node value types
@@ -483,6 +474,10 @@ struct AstNode {
483474
/// @brief whether or not a node has a constant value
484475
/// this may also set the FLAG_CONSTANT or the FLAG_DYNAMIC flags for the node
485476
bool isConstant() const;
477+
478+
/// @brief whether or not a node will use V8 internally
479+
/// this may also set the FLAG_V8 flag for the node
480+
bool willUseV8() const;
486481

487482
/// @brief whether or not a node is a simple comparison operator
488483
bool isSimpleComparisonOperator() const;

arangod/Aql/CalculationBlock.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void CalculationBlock::doEvaluation(AqlItemBlock* result) {
155155

156156
TRI_ASSERT(_expression != nullptr);
157157

158-
if (!_expression->isV8()) {
158+
if (!_expression->willUseV8()) {
159159
// an expression that does not require V8
160160
executeExpression(result);
161161
} else {

0 commit comments

Comments
 (0)
0