Permalink
Browse files

Merge branch 'typed-array-clusterfuck'

  • Loading branch information...
2 parents 84d342c + cc5a057 commit 08741b4489ff945b117ebee0333c7eb7a6177c2e @phoboslab committed Dec 12, 2015
Showing with 588 additions and 7,704 deletions.
  1. +20 −38 Ejecta.xcodeproj/project.pbxproj
  2. +9 −0 README.md
  3. +6 −3 Source/Ejecta/EJCanvas/2D/EJBindingImageData.m
  4. +50 −31 Source/Ejecta/EJCanvas/WebGL/EJBindingCanvasContextWebGL.m
  5. +4 −3 Source/Ejecta/EJCanvas/WebGL/EJConvertWebGL.m
  6. +3 −2 Source/Ejecta/EJConvert.h
  7. +8 −18 Source/Ejecta/EJConvert.m
  8. +75 −0 Source/Ejecta/EJConvertTypedArray.h
  9. +395 −0 Source/Ejecta/EJConvertTypedArray.m
  10. +10 −2 Source/Ejecta/EJJavaScriptView.m
  11. +3 −5 Source/Ejecta/EJUtils/EJBindingHttpRequest.m
  12. +5 −6 Source/Ejecta/EJUtils/EJBindingWebSocket.m
  13. +0 −1 Source/lib/ios/JavaScriptCore.framework/Headers
  14. +0 −1 Source/lib/ios/JavaScriptCore.framework/JavaScriptCore
  15. +0 −147 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSBase.h
  16. +0 −230 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSContext.h
  17. +0 −158 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSContextRef.h
  18. +0 −152 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSExport.h
  19. +0 −83 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSManagedValue.h
  20. +0 −694 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSObjectRef.h
  21. +0 −145 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSStringRef.h
  22. +0 −60 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSStringRefCF.h
  23. +0 −73 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSTypedArray.h
  24. +0 −667 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSValue.h
  25. +0 −301 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSValueRef.h
  26. +0 −82 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JSVirtualMachine.h
  27. +0 −36 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JavaScript.h
  28. +0 −42 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/JavaScriptCore.h
  29. +0 −925 Source/lib/ios/JavaScriptCore.framework/Versions/A/Headers/WebKitAvailability.h
  30. BIN Source/lib/ios/JavaScriptCore.framework/Versions/A/JavaScriptCore
  31. +0 −1 Source/lib/ios/JavaScriptCore.framework/Versions/Current
  32. +0 −1 Source/lib/tvos/JavaScriptCore.framework/Headers
  33. +0 −1 Source/lib/tvos/JavaScriptCore.framework/JavaScriptCore
  34. +0 −147 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSBase.h
  35. +0 −230 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSContext.h
  36. +0 −158 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSContextRef.h
  37. +0 −152 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSExport.h
  38. +0 −83 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSManagedValue.h
  39. +0 −694 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSObjectRef.h
  40. +0 −145 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSStringRef.h
  41. +0 −60 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSStringRefCF.h
  42. +0 −73 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSTypedArray.h
  43. +0 −667 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSValue.h
  44. +0 −301 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSValueRef.h
  45. +0 −82 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JSVirtualMachine.h
  46. +0 −36 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JavaScript.h
  47. +0 −42 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/JavaScriptCore.h
  48. +0 −925 Source/lib/tvos/JavaScriptCore.framework/Versions/A/Headers/WebKitAvailability.h
  49. BIN Source/lib/tvos/JavaScriptCore.framework/Versions/A/JavaScriptCore
  50. +0 −1 Source/lib/tvos/JavaScriptCore.framework/Versions/Current
Oops, something went wrong.
View
@@ -1,3 +1,12 @@
+# About The typed-array-clusterfuck Branch
+
+This branch of Ejecta uses the JavaScriptCore library provided by the system. This mainly means two things: The resulting binary will be much smaller and Typed Arrays are extremely slow.
+
+On 32bit systems reading/writing large Typed Arrays will be pretty much unusably slow. On 64bit systems it's highly optimized to take about 8ms for reading for 1MB of data and about 20ms for writing. This _may_ be ok for simple WebGL stuff or if you don't use g`et/setImageData()` on the Canvas2D context much.
+
+This branch of Ejecta _may_ be AppStore compatible for tvOS. I'm still waiting on the review, but at least the binary upload didn't fail like with the main branch.
+
+
# Ejecta
Ejecta is a fast, open source JavaScript, Canvas & Audio implementation for iOS. Think of it as a Browser that can only display a Canvas element.
@@ -1,6 +1,6 @@
#import "EJBindingImageData.h"
#import "EJJavaScriptView.h"
-#import <JavaScriptCore/JSTypedArray.h>
+#import "EJConvertTypedArray.h"
@implementation EJBindingImageData
@synthesize imageData;
@@ -28,7 +28,7 @@ - (EJImageData *)imageData {
int byteLength = imageData.width * imageData.height * 4;
[EJTexture
- premultiplyPixels:JSObjectGetTypedArrayDataPtr(scriptView.jsGlobalContext, dataArray, NULL)
+ premultiplyPixels:JSObjectGetTypedArrayData(scriptView.jsGlobalContext, dataArray).bytes
to:imageData.pixels.mutableBytes
byteLength:byteLength format:GL_RGBA];
}
@@ -48,10 +48,13 @@ - (EJTexture *)texture {
dataArray = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeUint8ClampedArray, byteLength);
JSValueProtect(ctx, dataArray);
+ NSMutableData *unPremultiplied = [NSMutableData dataWithLength:byteLength];
[EJTexture
unPremultiplyPixels:imageData.pixels.bytes
- to:JSObjectGetTypedArrayDataPtr(ctx, dataArray, NULL)
+ to:unPremultiplied.mutableBytes
byteLength:byteLength format:GL_RGBA];
+
+ JSObjectSetTypedArrayData(ctx, dataArray, unPremultiplied);
}
return dataArray;
}
@@ -6,7 +6,7 @@
#import "EJConvertWebGL.h"
#import "EJJavaScriptView.h"
-#import <JavaScriptCore/JSTypedArray.h>
+#import "EJConvertTypedArray.h"
@implementation EJBindingCanvasContextWebGL
@@ -365,10 +365,10 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
glBufferData(target, psize, NULL, usage);
}
else if( JSValueIsObject(ctx, argv[1]) ) {
- size_t size;
- GLvoid *buffer = JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)argv[1], &size);
- if( buffer ) {
- glBufferData(target, size, buffer, usage);
+ NSData *data = JSObjectGetTypedArrayData(ctx, (JSObjectRef)argv[1]);
+ if( data ) {
+ const GLvoid *buffer = data.bytes;
+ glBufferData(target, data.length, buffer, usage);
}
}
@@ -383,10 +383,10 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
GLenum target = JSValueToNumberFast(ctx, argv[0]);
GLintptr offset = JSValueToNumberFast(ctx, argv[1]);
- size_t size;
- GLvoid *buffer = JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)argv[2], &size);
- if( buffer ) {
- glBufferSubData(target, offset, size, buffer);
+ NSData *data = JSObjectGetTypedArrayData(ctx, (JSObjectRef)argv[2]);
+ if( data ) {
+ const GLvoid *buffer = data.bytes;
+ glBufferSubData(target, offset, data.length, buffer);
}
return NULL;
}
@@ -726,6 +726,7 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
int intbuffer[4];
float floatvalue;
JSValueRef arrayArgs[4];
+ NSMutableData *data;
switch( pname ) {
// Float32Array (with 0 elements)
@@ -737,28 +738,40 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
case GL_ALIASED_LINE_WIDTH_RANGE:
case GL_ALIASED_POINT_SIZE_RANGE:
case GL_DEPTH_RANGE:
+ data = [[NSMutableData alloc] initWithLength:2 * sizeof(GLfloat)];
+ glGetFloatv(pname, data.mutableBytes);
ret = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeFloat32Array, 2);
- glGetFloatv(pname, JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)ret, NULL));
+ JSObjectSetTypedArrayData(ctx, (JSObjectRef)ret, data);
+ [data release];
break;
// Float32Array (with 4 values)
case GL_BLEND_COLOR:
case GL_COLOR_CLEAR_VALUE:
+ data = [[NSMutableData alloc] initWithLength:4 * sizeof(GLfloat)];
+ glGetFloatv(pname, data.mutableBytes);
ret = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeFloat32Array, 4);
- glGetFloatv(pname, JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)ret, NULL));
+ JSObjectSetTypedArrayData(ctx, (JSObjectRef)ret, data);
+ [data release];
break;
// Int32Array (with 2 values)
case GL_MAX_VIEWPORT_DIMS:
+ data = [[NSMutableData alloc] initWithLength:2 * sizeof(GLint)];
+ glGetIntegerv(pname, data.mutableBytes);
ret = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeInt32Array, 2);
- glGetIntegerv(pname, JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)ret, NULL));
+ JSObjectSetTypedArrayData(ctx, (JSObjectRef)ret, data);
+ [data release];
break;
// Int32Array (with 4 values)
case GL_SCISSOR_BOX:
case GL_VIEWPORT:
+ data = [[NSMutableData alloc] initWithLength:4 * sizeof(GLint)];
+ glGetIntegerv(pname, data.mutableBytes);
ret = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeInt32Array, 4);
- glGetIntegerv(pname, JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)ret, NULL));
+ JSObjectSetTypedArrayData(ctx, (JSObjectRef)ret, data);
+ [data release];
break;
// boolean[] (with 4 values)
@@ -1147,15 +1160,21 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
// Float32Array
if( type == GL_FLOAT ) {
array = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeFloat32Array, size);
- void *buffer = JSObjectGetTypedArrayDataPtr(ctx, array, NULL);
- glGetUniformfv(program, uniform, buffer);
+ NSMutableData *data = [[NSMutableData alloc] initWithLength:size * sizeof(GLfloat)];
+ glGetUniformfv(program, uniform, data.mutableBytes);
+
+ JSObjectSetTypedArrayData(ctx, array, data);
+ [data release];
}
// Int32Array
else if( type == GL_INT ) {
array = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeInt32Array, size);
- void *buffer = JSObjectGetTypedArrayDataPtr(ctx, array, NULL);
- glGetUniformiv(program, uniform, buffer);
+ NSMutableData *data = [[NSMutableData alloc] initWithLength:size * sizeof(GLint)];
+ glGetUniformiv(program, uniform, data.mutableBytes);
+
+ JSObjectSetTypedArrayData(ctx, array, data);
+ [data release];
}
// boolean[]
@@ -1202,8 +1221,10 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
}
else if( pname == GL_CURRENT_VERTEX_ATTRIB ) {
JSObjectRef array = JSObjectMakeTypedArray(ctx, kJSTypedArrayTypeFloat32Array, 4);
- GLint *values = JSObjectGetTypedArrayDataPtr(ctx, array, NULL);
- glGetVertexAttribiv(index, pname, values);
+ NSMutableData *data = [[NSMutableData alloc] initWithLength:4 * sizeof(GLfloat)];
+ glGetVertexAttribiv(index, pname, data.mutableBytes);
+ JSObjectSetTypedArrayData(ctx, array, data);
+ [data release];
return array;
}
else {
@@ -1302,13 +1323,11 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
scriptView.currentRenderingContext = renderingContext;
- size_t size;
- void *pixels = JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)argv[6], &size);
-
GLuint bytesPerPixel = EJGetBytesPerPixel(type, format);
- if( bytesPerPixel && size >= width * height * bytesPerPixel ) {
- glReadPixels(x, y, width, height, format, type, pixels);
- }
+ NSMutableData *data = [[NSMutableData alloc] initWithLength:width*height*bytesPerPixel];
+ glReadPixels(x, y, width, height, format, type, data.mutableBytes);
+ JSObjectSetTypedArrayData(ctx, (JSObjectRef)argv[6], data);
+ [data release];
return NULL;
}
@@ -1463,10 +1482,10 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
if( border == 0 && EJ_ARRAY_MATCHES_TYPE(arrayType, type) ) {
int bytesPerPixel = EJGetBytesPerPixel(type, format);
- size_t byteLength;
- void *pixels = JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)argv[8], &byteLength);
+ NSMutableData *data = JSObjectGetTypedArrayData(ctx, (JSObjectRef)argv[8]);
+ void *pixels = data.mutableBytes;
- if( bytesPerPixel && byteLength >= width * height * bytesPerPixel ) {
+ if( bytesPerPixel && data.length >= width * height * bytesPerPixel ) {
if( unpackFlipY ) {
[EJTexture flipPixelsY:pixels bytesPerRow:(width * bytesPerPixel) rows:height];
}
@@ -1595,10 +1614,10 @@ - (void)deleteVertexArray:(GLuint)vertexArray {
if( EJ_ARRAY_MATCHES_TYPE(arrayType, type) ) {
int bytesPerPixel = EJGetBytesPerPixel(type, format);
- size_t byteLength;
- void *pixels = JSObjectGetTypedArrayDataPtr(ctx, (JSObjectRef)argv[8], &byteLength);
+ NSMutableData *data = JSObjectGetTypedArrayData(ctx, (JSObjectRef)argv[8]);
+ void *pixels = data.mutableBytes;
- if( bytesPerPixel && byteLength >= width * height * bytesPerPixel ) {
+ if( bytesPerPixel && data.length >= width * height * bytesPerPixel ) {
if( unpackFlipY ) {
[EJTexture flipPixelsY:pixels bytesPerRow:(width * bytesPerPixel) rows:height];
}
@@ -1,6 +1,6 @@
#import "EJConvertWebGL.h"
#import "EJConvert.h"
-#import <JavaScriptCore/JSTypedArray.h>
+#import "EJConvertTypedArray.h"
// FIXME: use C++ with a template?
#define CREATE_JS_VALUE_TO_ARRAY_FUNC(NAME, TYPE, ARRAY_TYPE) \
@@ -10,8 +10,9 @@
} \
JSObjectRef jsObject = (JSObjectRef)value; \
if( JSObjectGetTypedArrayType(ctx, jsObject) == ARRAY_TYPE ) { \
- size_t byteLength; \
- TYPE *arrayValue = JSObjectGetTypedArrayDataPtr(ctx, jsObject, &byteLength); \
+ NSMutableData *data = JSObjectGetTypedArrayData(ctx, jsObject); \
+ size_t byteLength = data.length; \
+ TYPE *arrayValue = data.mutableBytes; \
GLsizei count = (GLsizei)(byteLength/sizeof(TYPE)); \
if( arrayValue && count && (count % elementSize) == 0 ) { \
*numElements = count / elementSize; \
@@ -19,8 +19,9 @@ static inline void *JSValueGetPrivate(JSValueRef v) {
// undefined) will crash the app. So we check for these first.
#if __LP64__
- #define JSValueTagMask (0xffff000000000000ll | 0x2ll)
- return !((int64_t)v & JSValueTagMask) ? JSObjectGetPrivate((JSObjectRef)v) : NULL;
+ return !((int64_t)v & 0xffff000000000002ll)
+ ? JSObjectGetPrivate((JSObjectRef)v)
+ : NULL;
#else
return JSObjectGetPrivate((JSObjectRef)v);
#endif
@@ -24,9 +24,11 @@ JSValueRef NSStringToJSValue( JSContextRef ctx, NSString *string ) {
// This functions comes in a 64bit and 32bit flavor, since the NaN-Boxing
// in JSC works a bit differently on each platforms. For an explanation
// of the taggging refer to JSC/runtime/JSCJSValue.h
+// The 32bit version just calls the normal JSValueToNumber() function
+// and is thus a lot slower.
-#if __LP64__ // arm64 version
- double JSValueToNumberFast(JSContextRef ctx, JSValueRef v) {
+double JSValueToNumberFast(JSContextRef ctx, JSValueRef v) {
+ #if __LP64__ // arm64 version
union {
int64_t asInt64;
double asDouble;
@@ -50,22 +52,10 @@ JSValueRef NSStringToJSValue( JSContextRef ctx, NSString *string ) {
else {
return 0; // false, undefined, null, object
}
- }
-#else // armv7 version
- double JSValueToNumberFast( JSContextRef ctx, JSValueRef v ) {
- struct {
- unsigned char cppClassData[4];
- union {
- double asDouble;
- struct { int32_t asInt; int32_t tag; } asBits;
- } payload;
- } *decoded = (void *)v;
-
- return decoded->payload.asBits.tag < 0xfffffff9
- ? decoded->payload.asDouble
- : decoded->payload.asBits.asInt;
- }
-#endif
+ #else // armv7 version
+ return JSValueToNumber(ctx, v, NULL);
+ #endif
+}
void JSValueUnprotectSafe( JSContextRef ctx, JSValueRef v ) {
if( ctx && v ) {
@@ -0,0 +1,75 @@
+#import <Foundation/Foundation.h>
+#import <JavaScriptCore/JavaScriptCore.h>
+
+/*!
+@enum JSType
+@abstract A constant identifying the Typed Array type of a JSValue.
+@constant kJSTypedArrayTypeNone Not a Typed Array.
+@constant kJSTypedArrayTypeInt8Array Int8Array
+@constant kJSTypedArrayTypeInt16Array Int16Array
+@constant kJSTypedArrayTypeInt32Array Int32Array
+@constant kJSTypedArrayTypeUint8Array Int8Array
+@constant kJSTypedArrayTypeUint8ClampedArray Int8ClampedArray
+@constant kJSTypedArrayTypeUint16Array Uint16Array
+@constant kJSTypedArrayTypeUint32Array Uint32Array
+@constant kJSTypedArrayTypeFloat32Array Float32Array
+@constant kJSTypedArrayTypeFloat64Array Float64Array
+@constant kJSTypedArrayTypeArrayBuffer ArrayBuffer
+*/
+typedef enum {
+ kJSTypedArrayTypeNone = 0,
+ kJSTypedArrayTypeInt8Array = 1,
+ kJSTypedArrayTypeInt16Array = 2,
+ kJSTypedArrayTypeInt32Array = 3,
+ kJSTypedArrayTypeUint8Array = 4,
+ kJSTypedArrayTypeUint8ClampedArray = 5,
+ kJSTypedArrayTypeUint16Array = 6,
+ kJSTypedArrayTypeUint32Array = 7,
+ kJSTypedArrayTypeFloat32Array = 8,
+ kJSTypedArrayTypeFloat64Array = 9,
+ kJSTypedArrayTypeArrayBuffer = 10
+} JSTypedArrayType;
+
+/*!
+@function
+@abstract Setup the JSContext for use of the Typed Array functions.
+@param ctx The execution context to use
+*/
+void JSContextPrepareTypedArrayAPI(JSContextRef ctx);
+
+/*!
+@function
+@abstract Returns a JavaScript value's Typed Array type
+@param ctx The execution context to use.
+@param value The JSObject whose Typed Array type you want to obtain.
+@result A value of type JSTypedArrayType that identifies value's Typed Array type
+*/
+JSTypedArrayType JSObjectGetTypedArrayType(JSContextRef ctx, JSObjectRef object);
+
+/*!
+@function
+@abstract Creates an empty JavaScript Typed Array with the given number of elements
+@param ctx The execution context to use.
+@param arrayType A value of type JSTypedArrayType identifying the type of array you want to create
+@param numElements The number of elements for the array.
+@result A JSObjectRef that is a Typed Array or NULL if there was an error
+*/
+JSObjectRef JSObjectMakeTypedArray(JSContextRef ctx, JSTypedArrayType arrayType, size_t numElements);
+
+/*!
+@function
+@abstract Returns a copy of the Typed Array's data
+@param ctx The execution context to use.
+@param value The JSObject whose Typed Array data you want to obtain.
+@result A copy of the Typed Array's data or NULL if the JSObject is not a Typed Array
+*/
+NSMutableData *JSObjectGetTypedArrayData(JSContextRef ctx, JSObjectRef object);
+
+/*!
+@function
+@abstract Replaces a Typed Array's data
+@param ctx The execution context to use.
+@param value The JSObject whose Typed Array data you want to replace
+*/
+void JSObjectSetTypedArrayData(JSContextRef ctx, JSObjectRef object, NSData *data);
+
Oops, something went wrong.

0 comments on commit 08741b4

Please sign in to comment.