Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (202362 => 202363)
--- trunk/Source/_javascript_Core/ChangeLog 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-06-23 01:39:01 UTC (rev 202363)
@@ -1,3 +1,55 @@
+2016-06-22 Keith Miller <keith_mil...@apple.com>
+
+ We should have a DFG intrinsic that checks if a value is a TypedArrayView
+ https://bugs.webkit.org/show_bug.cgi?id=159048
+
+ Reviewed by Saam Barati.
+
+ This patch adds a new DFG Intrinsic that checks if a value is a TypedArrayView.
+ The intrinsic, IsTypedArrayView, works in the same way that the other Is<insert-type>
+ DFG nodes work. Additionally, a new builtin function isTypedArrayView has been added.
+ These changes are needed to fix regressions in %TypedArray%.prototype.subarray.
+
+ * builtins/BuiltinNames.h:
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileIsTypedArrayView):
+ * dfg/DFGSpeculativeJIT.h:
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+ (JSC::FTL::DFG::LowerDFGToB3::compileIsTypedArrayView):
+ (JSC::FTL::DFG::LowerDFGToB3::isTypedArrayView):
+ * runtime/Intrinsic.h:
+ * runtime/JSGlobalObject.cpp:
+ (JSC::JSGlobalObject::init):
+ * runtime/JSTypedArrayViewPrototype.cpp:
+ (JSC::typedArrayViewPrivateFuncIsTypedArrayView):
+ * runtime/JSTypedArrayViewPrototype.h:
+ * tests/stress/istypedarrayview-intrinsic.js: Added.
+ (makeFn):
+ (typedArrays.forEach):
+ (let.test):
+ (test):
+
2016-06-21 Anders Carlsson <ander...@apple.com>
Fix build.
Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (202362 => 202363)
--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -121,6 +121,7 @@
macro(thisNumberValue) \
macro(newTargetLocal) \
macro(derivedConstructor) \
+ macro(isTypedArrayView) \
macro(isBoundFunction) \
macro(hasInstanceBoundFunction) \
macro(instanceOf) \
Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -1035,7 +1035,8 @@
case IsObject:
case IsObjectOrNull:
case IsFunction:
- case IsRegExpObject: {
+ case IsRegExpObject:
+ case IsTypedArrayView: {
AbstractValue child = forNode(node->child1());
if (child.value()) {
bool constantWasSet = true;
@@ -1097,6 +1098,9 @@
case IsEmpty:
setConstant(node, jsBoolean(child.value().isEmpty()));
break;
+ case IsTypedArrayView:
+ setConstant(node, jsBoolean(child.value().isObject() && isTypedView(child.value().getObject()->classInfo()->typedArrayStorageType)));
+ break;
default:
constantWasSet = false;
break;
@@ -1268,6 +1272,19 @@
}
break;
+ case IsTypedArrayView:
+ if (!(child.m_type & ~SpecTypedArrayView)) {
+ setConstant(node, jsBoolean(true));
+ constantWasSet = true;
+ break;
+ }
+ if (!(child.m_type & SpecTypedArrayView)) {
+ setConstant(node, jsBoolean(false));
+ constantWasSet = true;
+ break;
+ }
+ break;
+
default:
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -2314,6 +2314,14 @@
return true;
}
+ case IsTypedArrayViewIntrinsic: {
+ ASSERT(argumentCountIncludingThis == 2);
+
+ insertChecks();
+ set(VirtualRegister(resultOperand), addToGraph(IsTypedArrayView, OpInfo(prediction), get(virtualRegisterForArgument(1, registerOffset))));
+ return true;
+ }
+
case StringPrototypeReplaceIntrinsic: {
if (argumentCountIncludingThis != 3)
return false;
Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -172,6 +172,7 @@
case IsString:
case IsObject:
case IsRegExpObject:
+ case IsTypedArrayView:
case LogicalNot:
case CheckInBounds:
case DoubleRep:
Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -165,6 +165,7 @@
case IsObjectOrNull:
case IsFunction:
case IsRegExpObject:
+ case IsTypedArrayView:
case TypeOf:
case LogicalNot:
case ToPrimitive:
Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -1547,6 +1547,7 @@
case DeleteById:
case DeleteByVal:
case IsJSArray:
+ case IsTypedArrayView:
case IsEmpty:
case IsUndefined:
case IsBoolean:
Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -317,6 +317,7 @@
macro(IsObjectOrNull, NodeResultBoolean) \
macro(IsFunction, NodeResultBoolean) \
macro(IsRegExpObject, NodeResultBoolean) \
+ macro(IsTypedArrayView, NodeResultBoolean) \
macro(TypeOf, NodeResultJS) \
macro(LogicalNot, NodeResultBoolean) \
macro(ToPrimitive, NodeResultJS | NodeMustGenerate) \
Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -792,7 +792,8 @@
case IsObject:
case IsObjectOrNull:
case IsFunction:
- case IsRegExpObject: {
+ case IsRegExpObject:
+ case IsTypedArrayView: {
setPrediction(SpecBoolean);
break;
}
Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -266,6 +266,7 @@
case IsObjectOrNull:
case IsFunction:
case IsRegExpObject:
+ case IsTypedArrayView:
case TypeOf:
case LogicalNot:
case CallObjectConstructor:
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -3455,6 +3455,36 @@
blessedBooleanResult(resultGPR, node);
}
+void SpeculativeJIT::compileIsTypedArrayView(Node* node)
+{
+ JSValueOperand value(this, node->child1());
+#if USE(JSVALUE64)
+ GPRTemporary result(this, Reuse, value);
+#else
+ GPRTemporary result(this, Reuse, value, PayloadWord);
+#endif
+
+ JSValueRegs valueRegs = value.jsValueRegs();
+ GPRReg resultGPR = result.gpr();
+
+ JITCompiler::Jump isNotCell = m_jit.branchIfNotCell(valueRegs);
+
+ m_jit.load8(JITCompiler::Address(valueRegs.payloadGPR(), JSCell::typeInfoTypeOffset()), resultGPR);
+ m_jit.sub32(TrustedImm32(Int8ArrayType), resultGPR);
+ m_jit.compare32(JITCompiler::BelowOrEqual,
+ resultGPR,
+ TrustedImm32(Float64ArrayType - Int8ArrayType),
+ resultGPR);
+ blessBoolean(resultGPR);
+ JITCompiler::Jump done = m_jit.jump();
+
+ isNotCell.link(&m_jit);
+ moveFalseTo(resultGPR);
+
+ done.link(&m_jit);
+ blessedBooleanResult(resultGPR, node);
+}
+
void SpeculativeJIT::compileCallObjectConstructor(Node* node)
{
RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -754,6 +754,7 @@
void compileIsJSArray(Node*);
void compileIsRegExpObject(Node*);
+ void compileIsTypedArrayView(Node*);
void emitCall(Node*);
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -4733,6 +4733,11 @@
break;
}
+ case IsTypedArrayView: {
+ compileIsTypedArrayView(node);
+ break;
+ }
+
case TypeOf: {
compileTypeOf(node);
break;
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -4658,6 +4658,11 @@
break;
}
+ case IsTypedArrayView: {
+ compileIsTypedArrayView(node);
+ break;
+ }
+
case TypeOf: {
compileTypeOf(node);
break;
Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -187,6 +187,7 @@
case IsObjectOrNull:
case IsFunction:
case IsRegExpObject:
+ case IsTypedArrayView:
case CheckTypeInfoFlags:
case OverridesHasInstance:
case InstanceOf:
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -900,6 +900,9 @@
case IsRegExpObject:
compileIsRegExpObject();
break;
+ case IsTypedArrayView:
+ compileIsTypedArrayView();
+ break;
case TypeOf:
compileTypeOf();
break;
@@ -6107,6 +6110,24 @@
setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult));
}
+ void compileIsTypedArrayView()
+ {
+ LValue value = lowJSValue(m_node->child1());
+
+ LBasicBlock isCellCase = m_out.newBlock();
+ LBasicBlock continuation = m_out.newBlock();
+
+ ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
+ m_out.branch(isCell(value, provenType(m_node->child1())), unsure(isCellCase), unsure(continuation));
+
+ LBasicBlock lastNext = m_out.appendTo(isCellCase, continuation);
+ ValueFromBlock cellResult = m_out.anchor(isTypedArrayView(value, provenType(m_node->child1())));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setBoolean(m_out.phi(m_out.boolean, notCellResult, cellResult));
+ }
+
void compileTypeOf()
{
Edge child = m_node->child1();
@@ -10076,6 +10097,18 @@
m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
m_out.constInt32(ArrayType));
}
+
+ LValue isTypedArrayView(LValue cell, SpeculatedType type = SpecFullTop)
+ {
+ if (LValue proven = isProvenValue(type & SpecCell, SpecTypedArrayView))
+ return proven;
+ LValue jsType = m_out.sub(
+ m_out.load8ZeroExt32(cell, m_heaps.JSCell_typeInfoType),
+ m_out.constInt32(Int8ArrayType));
+ return m_out.belowOrEqual(
+ jsType,
+ m_out.constInt32(Float64ArrayType - Int8ArrayType));
+ }
LValue isObject(LValue cell, SpeculatedType type = SpecFullTop)
{
Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (202362 => 202363)
--- trunk/Source/_javascript_Core/runtime/Intrinsic.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -60,6 +60,7 @@
FRoundIntrinsic,
TruncIntrinsic,
IsRegExpObjectIntrinsic,
+ IsTypedArrayViewIntrinsic,
BoundThisNoArgsFunctionCallIntrinsic,
// Getter intrinsics.
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -655,6 +655,7 @@
JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength);
JSFunction* privateFuncTypedArrayGetOriginalConstructor = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor);
JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
+ JSFunction* privateFuncIsTypedArrayView = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncIsTypedArrayView, IsTypedArrayViewIntrinsic);
JSFunction* privateFuncIsBoundFunction = JSFunction::create(vm, this, 0, String(), isBoundFunction);
JSFunction* privateFuncHasInstanceBoundFunction = JSFunction::create(vm, this, 0, String(), hasInstanceBoundFunction);
JSFunction* privateFuncInstanceOf = JSFunction::create(vm, this, 0, String(), objectPrivateFuncInstanceOf);
@@ -703,6 +704,7 @@
GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArrayLengthPrivateName(), privateFuncTypedArrayLength, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArrayGetOriginalConstructorPrivateName(), privateFuncTypedArrayGetOriginalConstructor, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().typedArraySortPrivateName(), privateFuncTypedArraySort, DontEnum | DontDelete | ReadOnly),
+ GlobalPropertyInfo(vm.propertyNames->builtinNames().isTypedArrayViewPrivateName(), privateFuncIsTypedArrayView, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().isBoundFunctionPrivateName(), privateFuncIsBoundFunction, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().hasInstanceBoundFunctionPrivateName(), privateFuncHasInstanceBoundFunction, DontEnum | DontDelete | ReadOnly),
GlobalPropertyInfo(vm.propertyNames->builtinNames().instanceOfPrivateName(), privateFuncInstanceOf, DontEnum | DontDelete | ReadOnly),
Modified: trunk/Source/_javascript_Core/runtime/JSTypedArrayViewPrototype.cpp (202362 => 202363)
--- trunk/Source/_javascript_Core/runtime/JSTypedArrayViewPrototype.cpp 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/runtime/JSTypedArrayViewPrototype.cpp 2016-06-23 01:39:01 UTC (rev 202363)
@@ -64,6 +64,12 @@
RELEASE_ASSERT_NOT_REACHED(); \
} while (false)
+EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncIsTypedArrayView(ExecState* exec)
+{
+ JSValue value = exec->uncheckedArgument(0);
+ return JSValue::encode(jsBoolean(value.isCell() && isTypedView(value.asCell()->classInfo()->typedArrayStorageType)));
+}
+
EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncLength(ExecState* exec)
{
JSArrayBufferView* thisObject = jsDynamicCast<JSArrayBufferView*>(exec->argument(0));
Modified: trunk/Source/_javascript_Core/runtime/JSTypedArrayViewPrototype.h (202362 => 202363)
--- trunk/Source/_javascript_Core/runtime/JSTypedArrayViewPrototype.h 2016-06-23 01:13:45 UTC (rev 202362)
+++ trunk/Source/_javascript_Core/runtime/JSTypedArrayViewPrototype.h 2016-06-23 01:39:01 UTC (rev 202363)
@@ -46,6 +46,7 @@
static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
};
+EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncIsTypedArrayView(ExecState*);
EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncSort(ExecState*);
EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncLength(ExecState*);
EncodedJSValue JSC_HOST_CALL typedArrayViewPrivateFuncGetOriginalConstructor(ExecState*);
Added: trunk/Source/_javascript_Core/tests/stress/istypedarrayview-intrinsic.js (0 => 202363)
--- trunk/Source/_javascript_Core/tests/stress/istypedarrayview-intrinsic.js (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/istypedarrayview-intrinsic.js 2016-06-23 01:39:01 UTC (rev 202363)
@@ -0,0 +1,75 @@
+let typedArrays = [Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array];
+
+function makeFn(dontInline) {
+ let foo = createBuiltin(`(function (a) { "use strict"; return @isTypedArrayView(a); })`);
+ if (dontInline)
+ noInline(foo)
+ return foo;
+}
+
+typedArrays.forEach(function() {
+ let test = Function(
+ `
+ let foo = makeFn();
+ let bar = makeFn(true);
+ let view = new Int8Array(10);
+
+ for (i = 0; i < 100000; i++) {
+ if (!foo(view))
+ throw new Error(i);
+ if (!bar(view))
+ throw new Error(i);
+ }
+ `
+ );
+ test();
+});
+
+typedArrays.forEach(constructor1 => {
+ typedArrays.forEach(constructor2 => {
+ let test = Function(
+ `
+ let foo = makeFn();
+ let bar = makeFn(true);
+ let view1 = new ${constructor1.name}(10);
+ let view2 = new ${constructor2.name}(10);
+
+ for (i = 0; i < 100000; i++) {
+ let view = i % 2 === 0 ? view1 : view2;
+ if (!foo(view))
+ throw new Error(i);
+ if (!bar(view))
+ throw new Error(i);
+ }
+ `
+ );
+ test();
+ });
+});
+
+let test = function() {
+ let foo = makeFn();
+ let bar = makeFn(true);
+ for (i = 0; i < 100000; i++) {
+ if (foo(true))
+ throw new Error(i);
+ if (bar(true))
+ throw new Error(i);
+ }
+}
+test();
+
+test = function() {
+ let bar = makeFn(true);
+ let view = new Int8Array(10);
+ let obj = new DataView(new ArrayBuffer(10));
+ for (i = 0; i < 100000; i++) {
+ if (i % 2 === 0) {
+ if (!foo(view))
+ throw new Error(i);
+ } else {
+ if (foo(obj))
+ throw new Error(i);
+ }
+ }
+}