[JAEGER] Merge from Tracemonkey.

This commit is contained in:
David Mandelin 2010-08-27 11:35:42 -07:00
Родитель 7969f93360 56b9256565
Коммит ed5cb37cc3
2 изменённых файлов: 251 добавлений и 24 удалений

Просмотреть файл

@ -821,11 +821,8 @@ class TypedArrayTemplate
static JSBool
fun_slice(JSContext *cx, uintN argc, Value *vp)
{
Value *argv;
JSObject *obj;
argv = JS_ARGV(cx, vp);
obj = ComputeThisFromVp(cx, vp);
Value *argv = JS_ARGV(cx, vp);
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp+2))
return false;
@ -896,6 +893,86 @@ class TypedArrayTemplate
return true;
}
/* set(array[, offset]) */
static JSBool
fun_set(JSContext *cx, uintN argc, Value *vp)
{
Value *argv = JS_ARGV(cx, vp);
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp+2))
return false;
if (obj->getClass() != fastClass()) {
// someone tried to apply this set() to the wrong class
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_INCOMPATIBLE_METHOD,
fastClass()->name, "set", obj->getClass()->name);
return false;
}
ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj);
if (!tarray)
return true;
// these are the default values
int32_t offset = 0;
if (argc > 1) {
if (!ValueToInt32(cx, argv[1], &offset))
return false;
if (offset < 0 || uint32_t(offset) > tarray->length) {
// the given offset is bogus
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
}
// first arg must be either a typed array or a JS array
if (!argv[0].isObject()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
JSObject *arg0 = argv[0].toObjectOrNull();
if (js_IsTypedArray(arg0)) {
TypedArray *src = TypedArray::fromJSObject(arg0);
if (!src ||
src->length > tarray->length - offset)
{
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
tarray->copyFrom(src, offset);
} else if (arg0->wrappedObject(cx)->isArray()) {
jsuint len;
if (!js_GetLengthProperty(cx, arg0, &len))
return false;
// avoid overflow; we know that offset <= length
if (len > tarray->length - offset) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
if (!tarray->copyFrom(cx, arg0, len, offset))
return false;
} else {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_TYPED_ARRAY_BAD_ARGS);
return false;
}
vp->setUndefined();
return true;
}
static ThisTypeArray *
fromJSObject(JSObject *obj)
{
@ -930,9 +1007,9 @@ class TypedArrayTemplate
//printf ("Constructing with type %d other %p offset %d length %d\n", type, other, byteOffset, length);
if (JS_IsArrayObject(cx, other)) {
if (other->wrappedObject(cx)->isArray()) {
jsuint len;
if (!JS_GetArrayLength(cx, other, &len))
if (!js_GetLengthProperty(cx, other, &len))
return false;
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), len))
return false;
@ -946,8 +1023,7 @@ class TypedArrayTemplate
if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), tarray->length))
return false;
if (!copyFrom(tarray))
return false;
copyFrom(tarray);
} else if (other->getClass() == &ArrayBuffer::jsclass) {
ArrayBuffer *abuf = ArrayBuffer::fromJSObject(other);
@ -1067,9 +1143,11 @@ class TypedArrayTemplate
}
bool
copyFrom(JSContext *cx, JSObject *ar, jsuint len)
copyFrom(JSContext *cx, JSObject *ar, jsuint len, jsuint offset = 0)
{
NativeType *dest = static_cast<NativeType*>(data);
JS_ASSERT(offset <= length);
JS_ASSERT(len <= length - offset);
NativeType *dest = static_cast<NativeType*>(data) + offset;
if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) {
JS_ASSERT(ar->getArrayLength() == len);
@ -1092,63 +1170,71 @@ class TypedArrayTemplate
return true;
}
bool
copyFrom(TypedArray *tarray)
void
copyFrom(TypedArray *tarray, jsuint offset = 0)
{
NativeType *dest = static_cast<NativeType*>(data);
JS_ASSERT(offset <= length);
JS_ASSERT(tarray->length <= length - offset);
if (tarray->buffer == buffer) {
copyFromWithOverlap(tarray, offset);
return;
}
NativeType *dest = static_cast<NativeType*>(data) + offset;
if (tarray->type == type) {
memcpy(dest, tarray->data, tarray->byteLength);
return true;
return;
}
uintN srclen = tarray->length;
switch (tarray->type) {
case TypedArray::TYPE_INT8: {
int8 *src = static_cast<int8*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_UINT8:
case TypedArray::TYPE_UINT8_CLAMPED: {
uint8 *src = static_cast<uint8*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_INT16: {
int16 *src = static_cast<int16*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_UINT16: {
uint16 *src = static_cast<uint16*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_INT32: {
int32 *src = static_cast<int32*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_UINT32: {
uint32 *src = static_cast<uint32*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_FLOAT32: {
float *src = static_cast<float*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_FLOAT64: {
double *src = static_cast<double*>(tarray->data);
for (uintN i = 0; i < length; ++i)
for (uintN i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
@ -1156,8 +1242,81 @@ class TypedArrayTemplate
JS_NOT_REACHED("copyFrom with a TypedArray of unknown type");
break;
}
}
return true;
void
copyFromWithOverlap(TypedArray *tarray, jsuint offset = 0)
{
JS_ASSERT(offset < length);
NativeType *dest = static_cast<NativeType*>(data) + offset;
if (tarray->type == type) {
memmove(dest, tarray->data, tarray->byteLength);
return;
}
// We have to make a copy of the source array here, since
// there's overlap, and we have to convert types.
void *srcbuf = js_malloc(tarray->byteLength);
memcpy(srcbuf, tarray->data, tarray->byteLength);
switch (tarray->type) {
case TypedArray::TYPE_INT8: {
int8 *src = (int8*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_UINT8:
case TypedArray::TYPE_UINT8_CLAMPED: {
uint8 *src = (uint8*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_INT16: {
int16 *src = (int16*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_UINT16: {
uint16 *src = (uint16*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_INT32: {
int32 *src = (int32*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_UINT32: {
uint32 *src = (uint32*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_FLOAT32: {
float *src = (float*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArray::TYPE_FLOAT64: {
double *src = (double*) srcbuf;
for (uintN i = 0; i < tarray->length; ++i)
*dest++ = NativeType(*src++);
break;
}
default:
JS_NOT_REACHED("copyFromWithOverlap with a TypedArray of unknown type");
break;
}
js_free(srcbuf);
}
bool
@ -1325,6 +1484,7 @@ JSPropertySpec TypedArray::jsprops[] = {
#define IMPL_TYPED_ARRAY_STATICS(_typedArray) \
template<> JSFunctionSpec _typedArray::jsfuncs[] = { \
JS_FN("slice", _typedArray::fun_slice, 2, 0), \
JS_FN("set", _typedArray::fun_set, 2, 0), \
JS_FS_END \
}

Просмотреть файл

@ -230,6 +230,73 @@ function test()
check(function() !(a[3] == a[3]));
check(function() a[4] == 1);
// test set()
var empty = new Int32Array(0);
a = new Int32Array(9);
empty.set([]);
empty.set([], 0);
checkThrows(function() empty.set([1]));
checkThrows(function() empty.set([1], 0));
checkThrows(function() empty.set([1], 1));
a.set([]);
a.set([], 3);
a.set([], 9);
a.set(empty);
a.set(empty, 3);
a.set(empty, 9);
a.set(Array.prototype);
checkThrows(function() a.set(empty, 100));
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10]));
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10], 0));
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10], 0x7fffffff));
checkThrows(function() a.set([1,2,3,4,5,6,7,8,9,10], 0xffffffff));
checkThrows(function() a.set([1,2,3,4,5,6], 6));
checkThrows(function() a.set(new Array(0x7fffffff)));
checkThrows(function() a.set([1,2,3], 2147483647));
checkThrows(function() a.set(ArrayBuffer.prototype));
checkThrows(function() a.set(UInt16Array.prototype));
checkThrows(function() a.set(Int32Array.prototype));
a.set([1,2,3]);
a.set([4,5,6], 3);
check(function()
a[0] == 1 && a[1] == 2 && a[2] == 3 &&
a[3] == 4 && a[4] == 5 && a[5] == 6 &&
a[6] == 0 && a[7] == 0 && a[8] == 0);
b = new Float32Array([7,8,9]);
a.set(b, 0);
a.set(b, 3);
check(function()
a[0] == 7 && a[1] == 8 && a[2] == 9 &&
a[3] == 7 && a[4] == 8 && a[5] == 9 &&
a[6] == 0 && a[7] == 0 && a[8] == 0);
a.set(a.slice(0,3), 6);
check(function()
a[0] == 7 && a[1] == 8 && a[2] == 9 &&
a[3] == 7 && a[4] == 8 && a[5] == 9 &&
a[6] == 7 && a[7] == 8 && a[8] == 9);
a.set([1,2,3,4,5,6,7,8,9]);
a.set(a.slice(0,6), 3);
check(function()
a[0] == 1 && a[1] == 2 && a[2] == 3 &&
a[3] == 1 && a[4] == 2 && a[5] == 3 &&
a[6] == 4 && a[7] == 5 && a[8] == 6);
a.set(a.slice(3,9), 0);
check(function()
a[0] == 1 && a[1] == 2 && a[2] == 3 &&
a[3] == 4 && a[4] == 5 && a[5] == 6 &&
a[6] == 4 && a[7] == 5 && a[8] == 6);
a = new ArrayBuffer(0x10);
checkThrows(function() new Uint32Array(buffer, 4, 0x3FFFFFFF));