-
Notifications
You must be signed in to change notification settings - Fork 2.2k
new branch for PR, attempted vcc fix, other cleanup #4233
Conversation
Codecov Report
@@ Coverage Diff @@
## develop #4233 +/- ##
===========================================
+ Coverage 67.27% 67.36% +0.08%
===========================================
Files 302 306 +4
Lines 23340 23435 +95
===========================================
+ Hits 15702 15787 +85
- Misses 7638 7648 +10
|
libevm/VM.cpp
Outdated
updateIOGas(); | ||
*m_RP++ = m_PC++; | ||
m_PC = decodeJumpDest(m_code.data(), m_PC); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
too many braces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird. This compiled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No - this is EIP_615 code, which I haven't compiled for a while.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it compiles. Thanks.
libevm/VM.cpp
Outdated
|
||
uint8_t b = ++m_PC; | ||
uint8_t c = ++m_PC; | ||
xput(m_code[b], m_code[c]); ++m_PC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each statement on separate line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
libevm/VM.cpp
Outdated
|
||
uint8_t b = ++m_PC; | ||
uint8_t c = ++m_PC; | ||
xget(m_code[b], m_code[c]); ++m_PC; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
each statement on separate line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
libevm/VM.cpp
Outdated
@@ -1096,7 +1491,7 @@ void VM::interpretCases() | |||
#if EVM_HACK_DUP_64 | |||
*(uint64_t*)m_SPP = *(uint64_t*)(m_SP + n); | |||
#else | |||
m_SPP[0] = m_SP[n]; | |||
new(m_SPP) u256(m_SP[n]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this change for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stack slot being copied into may no longer hold a u256, so we construct a new one in the memory, rather than assign. I added a comment.
void xswizzle(uint8_t); | ||
void xshuffle(uint8_t); | ||
|
||
u256 vtow(uint8_t _b, const u256& _in); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
u256 const&
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sigh
void xshuffle(uint8_t); | ||
|
||
u256 vtow(uint8_t _b, const u256& _in); | ||
void wtov(uint8_t _b, u256 _in, u256& _o_out); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this return u256
, since you've made it for vtow
.
Pass _in
by const reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CHeck comments on implementation. Arguments and returns for this and vtow() are as they need to be/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, the convention for output params is o_out
, without leading underscore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. But I wonder why the inconsistency? Either all arguments should have a leading underscore or they shouldn't.
// | ||
// EVM_TRACE - provides various levels of tracing | ||
|
||
#ifndef EIP_615 | ||
#define EIP_615 false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer defining these in .cmake files instead.
Then we'd be able to build with or without it just by changing cmake command line.
Or maybe it's not even necessary to modify .cmake files. maybe it would be enough just to delete these #defines, then try to build with cmake .. -DEIP_615=true
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably these will stay off in production until EIPs are accepted, and then be removed. So in the meantime it's good to be able to switch configurations with minimal recompilation. That's my main consideration. cmake files might work. Rebuilding with cmake at the top would not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the code again, I still like this pattern. It allows for external configuration (via cmake or whatever) - if a macro has a definition when compiled it is respected, and if it doesn't an appropriate default is chosen. During development I just change the defaults to quickly switch configurations.
libevm/VMSIMD.cpp
Outdated
#define AND( x1, x2) ((x1) & (x2)) | ||
#define OR( x1, x2) ((x1) | (x2)) | ||
#define XOR( x1, x2) ((x1) ^ (x2)) | ||
#define NOT( x1, x2) (~x1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be (~(x1))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
libevm/VMSIMD.cpp
Outdated
#define NOT( x1, x2) (~x1) | ||
#define SHR( x1, x2) ((x1) >> (x2)) | ||
#define SHL( x1, x2) ((x1) << (x2)) | ||
#define ROL( x1, x2) (((x1) << x2)|((x1) >> (sizeof(x1) * 8 - (x2)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be (((x1) << (x2))|...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
libevm/VMSIMD.cpp
Outdated
#define SHR( x1, x2) ((x1) >> (x2)) | ||
#define SHL( x1, x2) ((x1) << (x2)) | ||
#define ROL( x1, x2) (((x1) << x2)|((x1) >> (sizeof(x1) * 8 - (x2)))) | ||
#define ROR( x1, x2) (((x1) >> x2)|((x1) << (sizeof(x1) * 8 - (x2)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be (((x1) << (x2))|...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I regret I couldn't make these work as templates and avoid all these parentheses.
libevm/VMSIMD.cpp
Outdated
|
||
inline uint8_t pow2N(uint8_t n) | ||
{ | ||
static uint8_t exp[6] = { 1, 2, 4, 8, 16, 32 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add assert(n < 6)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we ever turn asserts on? Where? There are a lot of them that could be added to double-check everything for this EIP and 615 that is supposed to be validated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are on in debug build. I build debug all the time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. RelDbg is usually enough for me. I'll put more in for the next PR.
libevm/VMSIMD.cpp
Outdated
void VM::xrol (uint8_t _b) { EVALXOPU(ROL, _b); } | ||
void VM::xror (uint8_t _b) { EVALXOPU(ROR, _b); } | ||
|
||
inline uint8_t pow2N(uint8_t n) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be _n
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sigh
libevm/VMSIMD.cpp
Outdated
for (int j = n, i = n - 1; 0 <= i; --i) | ||
{ | ||
int v = 0; | ||
v = v8x32(m_SPP[0])[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this should be v = v16x16(m_SPP[0])[i];
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, thanks
libevm/VMSIMD.cpp
Outdated
for (int j = n, i = n - 1; 0 <= i; --i) | ||
{ | ||
int v = 0; | ||
v = v8x32(m_SPP[0])[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v32x8
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, thanks
libevm/VMSIMD.cpp
Outdated
for (int j = n, i = n - 1; 0 <= i; --i) | ||
{ | ||
int v = 0; | ||
v = v8x32(m_SPP[0])[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
v64x4
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, thanks
libevm/VMSIMD.cpp
Outdated
break; | ||
case 1: | ||
for (int i = 0; i < m; ++i) | ||
v16x16(m_SPP[0])[i] = v8x32(m_SP[0])[v16x16(m_SP[1])[i] % 16]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, not sure if this is correct, shouldn't source vector and result vector have the same type (which is t
) ?
That is, I think left-hand side here should be v8x32(m_SPP[0])[i]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spec says they can be different. We could take up in the EIP issue whether that is a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, ok, but the code contains only two bytes after XGET opcode, for the type of source vector and the type of get vector (indices vector).
Then this implementation considers result type to be equal get vector type, I find it weird.
For the most general implementation we probably should have 3 bytes following XGET opcode, for types of all 3 vectors?
I'll add a comment to EIP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now, XGET really replaces each index in the stack word with a value from source vector, that's why index vector type and result vector type are the same.
libevm/VMSIMD.cpp
Outdated
{ | ||
case 0: | ||
for (int i = 0; i < m; ++i) | ||
v8x32 (m_SPP[0])[i] = v16x16(m_SP[1])[v8x32 (m_SP[0])[i] % 32]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same problem here, assigning uint16_t
to uint8_t
doesn't look correct.
Left-hand side should be v16x16
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same answer as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To say a little more - XGET is the way to get elements out of a vector. Letting the destination have a different type than the source allows for casting, and I've allowed for both downcasting and upcasting. That's all.
libevm/VMSIMD.cpp
Outdated
break; | ||
case 1: | ||
for (int i = 0; i < m; ++i) | ||
v16x16(m_SPP[0])[v8x32(m_SP[1])[i] % 16] = v8x32(m_SP[0])[i]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this implementation of XPUT considers source vector type to be the same as index vector type (which is t
)
Why not consider source vector type be the same as result vector (which is u
) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here I'm still confused, it reads only two vectors from the stack, but XPUT is supposed to take 3 vectors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed at the EIP I need to clean up the definition, and then I can be sure I have implemented the definition. But this looks wrong, and your suggestion sound right, thanks.
m_SPP[0] = m_SP[n]; | ||
// the stack slot being copied into may no longer hold a u256 | ||
// so we construct a new one in the memory, rather than assign | ||
new(m_SPP) u256(m_SP[n]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So do I understand this correctly, that this is done to avoid copy assignment operator interpreting the data as u256
and somehow corrupting it, since it can be not u256
at all?
But this placement new still calls the copy constructor, and copy constructor will still interpret it as u256
.
Maybe we should memcpy
or std:copy
the bytes here? Which is against the rules since uint256 is not a POD...
But I don't see how placement new helps here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not the source that is the problem - it's a u256. It's the destination that's the problem - it might be a vector. The assignment operator would treat the destination as a u256, which might blow up. Placement new treats it as raw memory. (Then we are just down to the problem that the destination's destructor is not called. For our u256 that is not a problem, but I think we will need XPOP and XPUSH to fix that in general.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But source can also be a vector? Or will validator not allow it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right - it's invalid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh - we will need XDUP and XSWAP too. Either that or implementations will be forced to keep track of the type of every stack slot, and this routine will involve checking the type of the source and destination. In C++ we can fix that by making u256 a POD, but some other languages can't get that close to the metal.
libevm/VMSIMD.cpp
Outdated
for (int i = 0; i < n; ++i) | ||
{ | ||
int j = v8x32(m_SP[0]) [i]; | ||
v8x32 (m_SPP[0])[i] = j < n ? v8x32(m_SP[2]) [j] : v8x32 (m_SP[2])[j % n]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't access source 1 vector, should be j < n ? v8x32(m_SP[1]) [j] : v8x32 (m_SP[2])[j % n];
as I understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so. thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is clearly wrong - the two sides of the condition should be different. But the spec is unclear as to which is which, and the example in the spec is also clearly wrong. So both need fixing. I notice in this spec and others it unclear whether the "first" argument is the first item pushed on the stack or item on the top of the stack - SP[n] versus SP[0].
byte OP; | ||
for (PC = 0; (OP = m_code[PC]); ++PC) | ||
if (OP == byte(Instruction::BEGINSUB)) | ||
Instruction OP; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the changes in this file supposed to go into this PR ? They look not really related to SIMD
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes for SIMD (and some previous ones) broke VMValidate, so I wanted it to compile again. Changes are pretty much small stuff like changed signatures and casts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I think I've finished reviewing it now. Implementations of xput and xshuffle still have errors to fix, after that we could merge.
libevm/VMSIMD.cpp
Outdated
@@ -41,28 +41,30 @@ inline a32x8 const& v32x8 (u256 const& _stack_item) { return (a32x8&) *(a32x8*) | |||
inline a16x16 const& v16x16(u256 const& _stack_item) { return (a16x16&)*(a16x16*)&_stack_item; } | |||
inline a8x32 const& v8x32 (u256 const& _stack_item) { return (a8x32&) *(a8x32*) &_stack_item; } | |||
|
|||
class Pow2Bits enum { BITS_8, BITS_16, BITS_32, BITS_64 }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, this doesn't compile for me at all. Did you intend it to be enum class
? Then BITS_8
etc. will be scoped (should be Pow2Bits::BITS_8
etc. everywhere) and implicit conversion between uint8_t
and Pow2Bits
won't work in switches.
Probably easier to use plain enum, although coding standards discourage it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming: all-uppercase is used only for macros, members should be named something like Bits8
, Bits16
etc.
enum itself probably could be named LaneWidth
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought I'd compiled it, but I did intend enum class, and I was pleasantly surprised not to see the problems you mentioned, so the config macro was probably turned off already. A simple enum is what I'm sure compiled, and it makes sense in the scope of just one file. I'll fix up the names.
libevm/VMSIMD.cpp
Outdated
@@ -169,35 +171,35 @@ u256 VM::vtow(uint8_t _b, const u256& _in) | |||
} | |||
|
|||
// out must be by reference because it is really just memory for a vector | |||
void VM::wtov(uint8_t _b, u256 _in, u256& _o_out) | |||
void VM::wtov(uint8_t _type, u256 _in, u256& _o_out) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming: o_out
libevm/VMSIMD.cpp
Outdated
@@ -426,108 +426,107 @@ void VM::xpush(uint8_t _b) | |||
} | |||
} | |||
|
|||
void VM::xget(uint8_t _b, uint8_t _c) | |||
void VM::xget(uint8_t _src_type, uint8_t _idx_type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming: don't use underscores other than for prefix, should be _srcType
& _idxType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought I'd search and replaced all of these...
libevm/VMSIMD.cpp
Outdated
@@ -538,107 +537,106 @@ void VM::xget(uint8_t _b, uint8_t _c) | |||
} | |||
} | |||
|
|||
void VM::xput(uint8_t _b, uint8_t _c) | |||
void VM::xput(uint8_t _src_type, uint8_t _dst_type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming: _srcType
& _dstType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought I'd search and destroyed all of these too...
Still - better than _b and _c.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A grep on _[a-z]+_[a-z]+
also smoked out some _o_out
and _stack_item
hiding in plain sight.
Travis is going to fail soon - Homebrew is broken. No merging until that is fixed. |
libevm/VMSIMD.cpp
Outdated
switch (width) | ||
{ | ||
case Bits8: | ||
for (int j = 1, i = count - 1; 0 <= i; --i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is j
initialization correct here and in other cases? it will go negative here if count >= 2
It was initializeed as j = n
in earlier commits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I need to dig into this after the AllCoreDevs meeting. This looks like the remains of a merge conflict that I reconciled badly. It should be n
, I think I agree, but n
is gone.
libevm/VMSIMD.cpp
Outdated
switch (width) | ||
{ | ||
case Bits8: | ||
for (int j = 1, i = count - 1; 0 <= i; --i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here too, should it be j = count
?
Thanks, @gumb0 ! |
The specification is here - ethereum/EIPs#616
The previous PR and review is here - /pull/4201
@gumb0 This is the latest code for review.
@pirapira SIMD vectors and operations are typed. I would be very interested in what you have to say about how well the correct use of the types can be validated and otherwise worked with formally.