-
Notifications
You must be signed in to change notification settings - Fork 71
Review of V0.8.4 (part 1) #283
Comments
Thanks for this detailed feedback. I'll work on changes for these errors and clean up the spec generally. Two very substantial things you raise are right upfront in your comment:
If these concerns come back to a performance concern about realm creation time, let's see how implementations get by like this, and we can think about revising it in Stage 4, being the time when we can still make revisions based on implementation feedback. |
About the various equality comparisons: I don't think any of the comparison functions will be all that useful for SIMD.js users. I included them with the current definitions out of a desire for consistency with the rest of the ES spec. The SIMD.js spec is written with an eye to generalization into value types (based on the good suggestion of the committee). I thought that, for value types, it would make sense for equality operations to recurse down into fields for deep structural equality. Are you suggesting that === be defined in terms of calling SameValue on the individual elements of the vector, under the general theory that it would be better to use SameValue everywhere and we're stuck with this legacy === semantics for existing things? I would be OK with that; I was trying to be more conservative initially. |
I spoke with some implementors about the change in equality semantics of === to be more like SameValue. The feedback so far is that it would be more difficult to implement this behavior with good performance, and they would prefer to keep the current semantics. Is there any particular problem caused by the semantics in the draft spec? |
I've updated the draft spec based on the feedback. I'm not sure if all
We could define them, but I'm not sure about a couple things:
This will make it impossible to use in asm.js, and even outside of The class hierarchy also doesn't make sense as some operations are
I added these terms in response to other reviewers who were having
Done
Done
I don't want to write a specification which would dispatch from a
Done
Done (mostly by copying the definitions into new internal algorithms).
Well, I just use the whole definition of Array.prototype.toString. I
Done
I'm not sure where you get that idea. They're supposed to be Number or
That would be reasonable, but I wrote it the way it is currently
Yeah, good point. This is a good argument for the purely spec-internal
Sure, there are all sorts of ways to get -0 in a SIMD vector, just
Eliminated the note.
Why not? This is a natural generalization of scalar ===. Implementors
Moved the material about SIMD primitive values.
Lists are modified all over the place. Generally they're created by
I am not sure why you would think it carries this implication. Things
Actually, ToObject is the only way that SIMD objects are created (just
What part do you think should be moved?
Done
Added one. I can see how it's useful, but to what extent do I need
Made more of an assertion. The [[Cast]] algorithm takes any ES value,
Done (though it's called MathFround for now; we can change that).
Good point, renamed to [[Cast]]
Actually that's on purpose. If you load and then store, for example,
Removed
What kind of assertion?
Oh, infinity is a case I didn't think about. Changed to ToLength.
Is it a problem like this?
Added that
Done
Fixed callers to not invoke it with an abrupt completion.
Fixed domain error; it's all abstract algorithms now.
Done
No, this is purposeful. Some SIMD values don't have flushed denormals.
Fixed.
Yes, hardware treats some ops differently. That's what the spec reflects.
Done
It's always called on integer vectors, so not needed. Added an
Done
Moved abstract operations up
Oops, no those ops shouldn't exist. Fixed the spec.
Fixed layering
Removed integer division
Yes, there are use cases, and this is the semantics. @sunfishcode can
It is just accelerated for floats
Fixed the layering and removed the float32 bitwise ops.
|
OK, I've now renamed MathFround to ToFloat32, and separated out the properties from the constructor. I'm looking forward to the rest of your review. |
The more I think about it, the more I like the idea of the table-based approach and a single SIMD type. That would eliminate the confusion with the _SIMD_Descriptor/_SIMD_Type/_SIMD_Constructor alternation. All that's really left is a cleaner way to refer to _SIMD_Constructor. |
Allen Wirfs-Brock 9/18/2015
(ok, github doesn't like my markdown (which worked fine in my editor. It's more important to get this posted than to debug it. hate markdown!!)
Overall API design concerns
I still have a number of significant issues with the overall design of this API.
from(value)
andfromBits(typedArray)
Section 1 (Subclause 4.3)
Subclause 4.3 historically hasn't tried to list every term used within the specification. Instead, most terminology is defined in the subclauses that introduce the terminology. Lacking an editorial effort to turn 4.3 into a comprehensive glossary, it would probably be best to not add 11 new SIMD related terms within 4.3. Instead, I suggest that you just add three terms that parallel the legacy primitive types:
SIMD value
member of one of the SIMD types
SIMD types
family of types (Float32x4, Int8x16, etc) whose values are homogeneously vectors of numeric or Boolean values.
SIMD objects
members of the Object type that are instances of one of the standard built-in SIMD constructors.
Other terms that are need should be either defined as part of subclause 6.1 (ecma-262 numbering) or wherever the "6 SIMD" section of this draft end up within ecma-262
Section 2 (clause 6)
The SIMD types and values are ECMAScript Language Types and hence, they must be defined as part of subclause 6.1. They should not be in a separate subclause at the same level as the existing 6.1 and 6.2. The SIMD types need to be mentioned in the first paragraph of 6.1 and a new subclass (6.1.8?) ) should be added corresponding to 2.2 in the draft. However, I would structure it considerably differently (use 6.1.4, 6.1.5, and 6.2.2 as models):
Switching to a single SIMD primitive value type also eliminates the need for italic SIMD convention in algorithms. Instead your algorithm can simply access and dispatch on the value of the SIMD primtive value field that identifies its specific subtype.
Section 2.1.1.1 (Subclause 6.1.7.4)
I think we should try to more closely match the conventions established (via Typed Arrays native errors) when extending Table 7 with SIMD intrinsic.
One of those conventions, is to explicitly have a separate table row for each Global intrinsic rather than using a single row to collectively describe sets of intrinsics such as TypedArray or NativeError . Also intrinsic are that are property of globally named objects are typically named using an underscore after the global component of the name. That suggests for the SIMD constructrors we should have rows (lexical-graphically ordered) for: %SIMD_Bool16x8%, %SIMD_Bool32x4%, %SIMD_Bool8x16%, %SIMD_Float32x4%, %SIMD_Int16x8%, %SIMD_Int32x4%, %SIMD_Int8x16%, %SIMD_UInt32x4%, %SIMD_Int16x8%, %SIMD_UInt8x16%.
This proposal also suggests defined named intrinsics for the built-in functions
Array.prototype.joint
,Math.abs
,Math.fround
,Math.max
,Math.min
,Math.sqrt
,Math.imul
. So that they maybe invoked by algorithms defined in this proposal. ECMA-262 and ECMA-402 have generally tried to avoid such direct invocations of specific intrinsic functions because because they can be problematic in some situations (for example, they can have realm locality) issues. For each of these I will suggest (in later sections of this review) alternatives that don't require the introduction of additional named intrinsics.Section 3 (clause 7)
Section 3.1.2 (Subclause 7.1.2) ToBoolean
I'd leave out the NOTE as no comparable explanation is provided for the other argument types. It's find to have in the proposal labeled as "Rationale", but such rationales are not placed in the actual spec. document.
Section 3.1.4 (Subclause 7.1.12) ToString
As a general principal, the definition of primitive operations upon primitive values should only invoke other primitive operations. . This definition of ToString for SIMD values violates that principal by invoking a built-in method (which is not a primitive operations). [Rationale: such a invocation is an up-level dependency within the layered architecture of the specification. This is a potential hazard to future spec. revisions. As changing the definition of a method in the ES library library layer shouldn't implicitly cause a change in the semantics of a primitive value and its associated primitive operations.]
Instead, similarly to the handling of Number values, an algorithm for an abstraction operation (based upon primitive operation) that converts primtive SIMD values to primitive string values should be defined in anew subclause of 7.1.12. such an algorithm is not hard to write. For example, steps 4-9 of 19.2.1.1.1 is an algorithm that converts a List of ECMAScript values to a comma separated string. This can be used as a model for a SIMD ToString algorithm.
The following comments related to the algorithm currently given in section 3.1.4 and may or may not be applicable to the new algorithm I suggested above:
Section 3.1.5 (Subclause 7.1.13) ToObject
This should probably use a new abstract operation that is more explicit about how a SIMD wrapper object is created for a SIMD primitive value.
Section 3.3 (Subclause 7.2.9) SameValue
If a single SIMD primitive type is used, as suggested above, then step 10 can be rewritten as:
Section 3.4 (Subclause 7.2.10) SameValueZero
Do you really want to use SameValueZero to compare the extra vector elements. The only place it would make a difference (in the current ES6 spec) is when using a SIMD value is a Map key or Set element. Do you really want:
It isn't clear that the rationale for why +0 and -0 should be equivalent when used as Map/set keys also applies to the elements of SIMD vectors.
Does SIMD hardward generate -0 values for vector elements?
Section 3.5 (Subclause 7.2.11) Abstract Relational Comparison
Symbols also throw a TypeError when ToNumber or ToString gets applied to them. I'd either eliminate the NOTE or generalize it so it isn't only about SIMD values.
Section 3.7 (Subclause 7.2.13) Strict Equality Comparison
So, what is the value equality semantics you intend for SIMD vectors that have NaN element values. Do you really intend that
Float32x4(NaN,0,0,0)===Float32x4(NaN,0,0,0)
is falseand
Float32x4(0,0,0,0)===Float32x4(-0,0,0,0)
is true?Section 6 SIMD
I think API design considerations mentioned at the top of this review would have a great impact upon this sections. Below, I'll comment of the section, as written.
I suggest that the top level of this section be patterned more exactly after 20.3 The Math Object. In other words just describe the %SIMD% intrinsic object. don't talk about the the vrious SIMD properties (ie, constructor here). Also the material about SIMD primitive values should be in clause 6.
Re: Note 1. Does this actually occur in this spec? I couldn't find and example. It would be cleaner if such lists were never modified... I guess it happens in SIMDcreate. Assuming that is the only place, that's where the note should be.
Note 2: The use of fields suggest that they need to be present as part of the runtime value. A table is better because it does not carry that implication.
Last paragraph
used in the ES6 spec when describing such objects. Instead, they are
called "Number objects", "String objects" etc. You should follow
that same pattern.
"[[Prototype]] is a SIMDConstructor" can't be correct. It must be an appropriate prototype object.
ToObject is not the only way that SIMD objects are created. Another way is using the
new
operator on one of the SIMD constructors.Section 6.1 Internal algorithm
You might consider moving these into the definition of SIMD values in clause 6, but they are probably ok as a subclause here.
Section 6.1.1 SIMDCreate
Section 6.1.2 SIMDToLane
max
ToInt32
to convertlane
values to positive integers. In ES6 we moved away from this because:ToLength
when we want to cast to a non-negative precise integer value. I'd replace step 3 with:Section 6.1.4 SIMDReplaceLane
this abstract operation appears to be only called from one place so you might consider inlining it at it's usage site.
Section 6.1.5 MaybeFlushDenormal
n
is a Boolean value.n
can be an abrupt completion value, I would start both alternatives with the step:Section 6.1.6 SIMDBinaryOp
op
similar to what was discussed for [[CastNumber]] in SIMDCreate. This one is actually worse as there are three different types of incompatible things passed as arguments for this parameter: built-in function objects, abstract operations, mathematical operations (as defined in 5.2. Plus some arguments use higher order abstract operations (SubSaturate, etc) and looks like they have has errors. It's probably best to always pass an abstract operation and if necessary define additional abstract operations to wrap the application of mathematical operations and built-in function invocations.a
andb
element values because they should have already been added using MaybeFlushDenormal.Section 6.1.7 SIMDUnaryOp
op
similar to those noted for SIMDBinaryOpflushDenormal
parameter. It is only false when op is unary minus or the abs function. Does some SIMD hardware treat demoralized values differently for those operations?. It seems like that parameter could be eliminated but maybe I'm missing something.Section 6.1.8 SIMDScalarOp
op
is always an abstract operationa
.Section 6.1.9/10 SIMDLoad/SIMDStore (also 6.2.51 NOTE)
Section 6.2 SIMDConstructor
For consistency (with the Math object organization) this section should probably be titled "Constructor Properties of the SIMD object" and have a subsection for each of the actual constructors.
A constructor(s) and the static methods of that constructor should not be listed at the same list level. See for example 6.2..1 and 6.2.2.
The same subclause level should not contain both static methods of constructors and abstract operations used by those methods. Either list all of the abstract operations in a separate subclause or place the abstract operation in a subclause of the the method that it is most closely associated with (See 21.1.3.14 for an example of this style.
Bool SIMD types issues with many of the static methods
The Bool SIMD types are specified such that there vector elements are ECMAScript Boolean values because their [[CastNumber]], which is used when populating the vector, is ToBoolean.
Many of the SIMD static methods (for example add, division) are not restricted from use upon Bool vector values. This means that the provided algorithms try to apply mathematical operator such as + to ECMAScript Boolean values. Such values out not in the domain sets of those operations.
Do you really want to perform arithmetic on Boolean values? If so, you need to specify the semantics of all of the operators that are applied to them.
Sections 6.2.5, 6.2.5, etc.
Sections 6.2.6 mul
Sections 6.2.6 div
Sections 6.2.11, 6.2.12, maxNum/minNum
Sections 6.2.20, abs
Sections 6.2.21, and, etc.
a
andb
are not parse trees, so you can't apply 12.11.3 to them.MORE TO COME
I'm not done commenting on all of the static methods, but I'm pointing this now to give it visibility before the upcoming TC39 meeting. I'll add additional comments in a followup to this issue.
The text was updated successfully, but these errors were encountered: