Revert runtime lowering of wasm SIMD ops

This CL reverts the runtime lowering introduced here -
https://codereview.chromium.org/1991143002/
Additional ops to the runtime pass will cause GC issues as WASM frames may
have outgoing arguments to runtime calls that have pointers that aren't scanned.

Preserving decoding of SIMD opcodes and macros for native implementations.

R=bbudge@chromium.org, mtrofin@chromium.org, bradnelson@chromium.org

Review-Url: https://codereview.chromium.org/2235013002
Cr-Commit-Position: refs/heads/master@{#38564}
This commit is contained in:
gdeepti 2016-08-10 14:39:04 -07:00 committed by Commit bot
parent 375bf0eb19
commit fe555065ea
10 changed files with 4 additions and 374 deletions

View File

@ -1119,8 +1119,6 @@ v8_source_set("v8_base") {
"src/compiler/scheduler.h", "src/compiler/scheduler.h",
"src/compiler/select-lowering.cc", "src/compiler/select-lowering.cc",
"src/compiler/select-lowering.h", "src/compiler/select-lowering.h",
"src/compiler/simd-lowering.cc",
"src/compiler/simd-lowering.h",
"src/compiler/simplified-lowering.cc", "src/compiler/simplified-lowering.cc",
"src/compiler/simplified-lowering.h", "src/compiler/simplified-lowering.h",
"src/compiler/simplified-operator-reducer.cc", "src/compiler/simplified-operator-reducer.cc",

View File

@ -1,116 +0,0 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/compiler/simd-lowering.h"
namespace v8 {
namespace internal {
namespace compiler {
SimdLowering::~SimdLowering() {}
void SimdLowering::InitializeSignatures() {
// Initialize signatures for runtime calls
const int kReturnCount = 1;
const int kBinop = 2;
const int kSimd32x4 = 4;
const int kSimd16x8 = 8;
const int kSimd8x16 = 16;
ConversionSignature::Builder CreateInt32x4Builder(zone_, kReturnCount,
kSimd32x4);
ConversionSignature::Builder CreateFloat32x4Builder(zone_, kReturnCount,
kSimd32x4);
ConversionSignature::Builder CreateInt16x8Builder(zone_, kReturnCount,
kSimd16x8);
ConversionSignature::Builder CreateInt8x16Builder(zone_, kReturnCount,
kSimd8x16);
ConversionSignature::Builder ExtractLaneIntBuilder(zone_, kReturnCount,
kBinop);
ConversionSignature::Builder ExtractLaneFloatBuilder(zone_, kReturnCount,
kBinop);
ConversionSignature::Builder DefaultBuilder(zone_, kReturnCount, kSimd8x16);
// Initialize Signatures for create functions
for (int i = 0; i < kSimd32x4; i++) {
CreateInt32x4Builder.AddParam(Conversion::kInt32);
CreateFloat32x4Builder.AddParam(Conversion::kFloat32);
}
CreateInt32x4Builder.AddReturn(Conversion::kOpaque);
SigCreateInt32x4 = CreateInt32x4Builder.Build();
CreateFloat32x4Builder.AddReturn(Conversion::kOpaque);
SigCreateFloat32x4 = CreateFloat32x4Builder.Build();
for (int i = 0; i < kSimd16x8; i++) {
CreateInt16x8Builder.AddParam(Conversion::kInt32);
}
CreateInt16x8Builder.AddReturn(Conversion::kOpaque);
SigCreateInt16x8 = CreateInt16x8Builder.Build();
for (int i = 0; i < kSimd8x16; i++) {
CreateInt8x16Builder.AddParam(Conversion::kInt32);
}
CreateInt8x16Builder.AddReturn(Conversion::kOpaque);
SigCreateInt8x16 = CreateInt8x16Builder.Build();
// Initialize signatures for ExtractLane functions
ExtractLaneIntBuilder.AddParam(Conversion::kOpaque);
ExtractLaneIntBuilder.AddParam(Conversion::kInt32);
ExtractLaneIntBuilder.AddReturn(Conversion::kInt32);
SigExtractLaneInt = ExtractLaneIntBuilder.Build();
}
Reduction SimdLowering::Reduce(Node* node) {
// For now lower everything to runtime calls.
switch (node->opcode()) {
case IrOpcode::kCreateInt32x4: {
return Replace(builder_->ChangeToRuntimeCall(
node, Runtime::kCreateInt32x4, SigCreateInt32x4));
}
case IrOpcode::kCreateInt16x8: {
return Replace(builder_->ChangeToRuntimeCall(
node, Runtime::kCreateInt16x8, SigCreateInt16x8));
}
case IrOpcode::kCreateInt8x16: {
return Replace(builder_->ChangeToRuntimeCall(
node, Runtime::kCreateInt8x16, SigCreateInt8x16));
}
case IrOpcode::kCreateFloat32x4: {
return Replace(builder_->ChangeToRuntimeCall(
node, Runtime::kCreateFloat32x4, SigCreateFloat32x4));
}
case IrOpcode::kInt8x16ExtractLane:
case IrOpcode::kInt16x8ExtractLane:
case IrOpcode::kInt32x4ExtractLane: {
return Replace(builder_->ChangeToRuntimeCall(
node, Runtime::kInt32x4ExtractLane, SigExtractLaneInt));
}
case IrOpcode::kFloat32x4ExtractLane: {
return Replace(builder_->ChangeToRuntimeCall(
node, Runtime::kFloat32x4ExtractLane, SigExtractLaneFloat));
}
default: { break; }
}
// TODO(gdeepti): Implement and test.
// Assume the others are all just simd in and out.
switch (node->opcode()) {
#define F(Opcode) \
case IrOpcode::k##Opcode: { \
return Replace( \
builder_->ChangeToRuntimeCall(node, Runtime::k##Opcode, SigDefault)); \
}
MACHINE_SIMD_RETURN_SIMD_OP_LIST(F)
MACHINE_SIMD_RETURN_BOOL_OP_LIST(F)
#undef F
default: { return NoChange(); }
}
UNREACHABLE();
return NoChange();
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -1,46 +0,0 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_SIMD_LOWERING_H_
#define V8_COMPILER_SIMD_LOWERING_H_
#include "src/compiler/graph-reducer.h"
#include "src/compiler/wasm-compiler.h"
#include "src/runtime/runtime.h"
namespace v8 {
namespace internal {
namespace compiler {
typedef Signature<Conversion> ConversionSignature;
class SimdLowering final : public Reducer {
public:
SimdLowering(Zone* zone, WasmGraphBuilder* builder)
: builder_(builder), zone_(zone) {
InitializeSignatures();
}
virtual ~SimdLowering();
Reduction Reduce(Node* node) override;
private:
void InitializeSignatures();
ConversionSignature* SigCreateInt32x4;
ConversionSignature* SigCreateFloat32x4;
ConversionSignature* SigCreateInt16x8;
ConversionSignature* SigCreateInt8x16;
ConversionSignature* SigExtractLaneInt;
ConversionSignature* SigExtractLaneFloat;
ConversionSignature* SigDefault;
WasmGraphBuilder* builder_;
Zone* zone_;
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_SIMD_LOWERING_H_

View File

@ -24,7 +24,6 @@
#include "src/compiler/machine-operator.h" #include "src/compiler/machine-operator.h"
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/pipeline.h" #include "src/compiler/pipeline.h"
#include "src/compiler/simd-lowering.h"
#include "src/compiler/source-position.h" #include "src/compiler/source-position.h"
#include "src/compiler/zone-pool.h" #include "src/compiler/zone-pool.h"
@ -2211,12 +2210,6 @@ Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) {
} }
} }
Node* WasmGraphBuilder::BuildChangeTaggedToInt32(Node* value) {
value = BuildChangeTaggedToFloat64(value);
value = graph()->NewNode(jsgraph()->machine()->ChangeFloat64ToInt32(), value);
return value;
}
Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context, Node* WasmGraphBuilder::BuildJavaScriptToNumber(Node* node, Node* context,
Node* effect, Node* control) { Node* effect, Node* control) {
Callable callable = CodeFactory::ToNumber(jsgraph()->isolate()); Callable callable = CodeFactory::ToNumber(jsgraph()->isolate());
@ -2656,12 +2649,6 @@ Node* WasmGraphBuilder::MemSize(uint32_t offset) {
} }
} }
Node* WasmGraphBuilder::DefaultS128Value() {
Node* zero = jsgraph()->Int32Constant(0);
return graph()->NewNode(jsgraph()->machine()->CreateInt32x4(), zero, zero,
zero, zero);
}
Node* WasmGraphBuilder::FunctionTable(uint32_t index) { Node* WasmGraphBuilder::FunctionTable(uint32_t index) {
DCHECK(module_ && module_->instance && DCHECK(module_ && module_->instance &&
index < module_->instance->function_tables.size()); index < module_->instance->function_tables.size());
@ -2675,79 +2662,6 @@ Node* WasmGraphBuilder::FunctionTable(uint32_t index) {
return function_tables_[index]; return function_tables_[index];
} }
Node* WasmGraphBuilder::ChangeToRuntimeCall(Node* node,
Runtime::FunctionId function_id,
Signature<Conversion>* signature) {
SimplifiedOperatorBuilder simplified(jsgraph()->zone());
const Runtime::Function* function = Runtime::FunctionForId(function_id);
CallDescriptor* desc = Linkage::GetRuntimeCallDescriptor(
jsgraph()->zone(), function_id, function->nargs, Operator::kNoProperties,
CallDescriptor::kNoFlags);
const int kInputSize = 16;
const int kDefaultFunctionParams = 6;
Node* inputs[kInputSize + kDefaultFunctionParams];
DCHECK_LE(function->nargs + kDefaultFunctionParams,
static_cast<int>(arraysize(inputs)));
// Either there are control + effect or not.
DCHECK(node->InputCount() == function->nargs ||
node->InputCount() == function->nargs + 2);
int index = 0;
inputs[index++] = jsgraph()->CEntryStubConstant(function->result_size);
for (int i = 0; i < function->nargs; ++i) {
Node* arg = node->InputAt(i);
switch (signature->GetParam(i)) {
case Conversion::kInt32:
arg = BuildChangeInt32ToTagged(arg);
break;
case Conversion::kFloat32:
arg = jsgraph()->graph()->NewNode(
jsgraph()->machine()->ChangeFloat32ToFloat64(), arg);
arg = BuildChangeFloat64ToTagged(arg);
break;
case Conversion::kFloat64:
arg = BuildChangeFloat64ToTagged(arg);
break;
default:
break;
}
inputs[index++] = arg;
}
inputs[index++] = jsgraph()->ExternalConstant(
ExternalReference(function_id, jsgraph()->isolate()));
inputs[index++] = jsgraph()->Int32Constant(function->nargs);
inputs[index++] = jsgraph()->Constant(module_->instance->context);
// Loads and stores have control and effect, others do not and use
// the start node instead.
if (node->InputCount() == function->nargs + 2) {
inputs[index++] = node->InputAt(function->nargs + 1); // effect
inputs[index++] = node->InputAt(function->nargs + 2); // control
} else {
inputs[index++] = jsgraph()->graph()->start(); // effect
inputs[index++] = jsgraph()->graph()->start(); // control
}
Node* ret = jsgraph()->graph()->NewNode(jsgraph()->common()->Call(desc),
index, inputs);
Conversion return_type = signature->GetReturn();
switch (return_type) {
case Conversion::kInt32:
ret = BuildChangeTaggedToInt32(ret);
break;
case Conversion::kFloat32:
NodeProperties::SetType(ret, Type::Number());
ret = BuildChangeTaggedToFloat64(ret);
ret = jsgraph()->graph()->NewNode(
jsgraph()->machine()->TruncateInt64ToInt32(), ret);
break;
case Conversion::kFloat64:
ret = BuildChangeTaggedToFloat64(ret);
break;
default:
break;
}
return ret;
}
Node* WasmGraphBuilder::GetGlobal(uint32_t index) { Node* WasmGraphBuilder::GetGlobal(uint32_t index) {
MachineType mem_type = MachineType mem_type =
wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index)); wasm::WasmOpcodes::MachineTypeFor(module_->GetGlobalType(index));
@ -2937,20 +2851,15 @@ void WasmGraphBuilder::SetSourcePosition(Node* node,
source_position_table_->SetSourcePosition(node, pos); source_position_table_->SetSourcePosition(node, pos);
} }
MachineOperatorBuilder* WasmGraphBuilder::simd() {
has_simd_ops_ = true;
return jsgraph()->machine();
}
Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode, Node* WasmGraphBuilder::SimdOp(wasm::WasmOpcode opcode,
const NodeVector& inputs) { const NodeVector& inputs) {
switch (opcode) { switch (opcode) {
case wasm::kExprI32x4ExtractLane: case wasm::kExprI32x4ExtractLane:
return graph()->NewNode(simd()->Int32x4ExtractLane(), inputs[0], return graph()->NewNode(jsgraph()->machine()->Int32x4ExtractLane(),
inputs[1]); inputs[0], inputs[1]);
case wasm::kExprI32x4Splat: case wasm::kExprI32x4Splat:
return graph()->NewNode(simd()->CreateInt32x4(), inputs[0], inputs[0], return graph()->NewNode(jsgraph()->machine()->Int32x4ExtractLane(),
inputs[0], inputs[0]); inputs[0], inputs[0], inputs[0], inputs[0]);
default: default:
return graph()->NewNode(UnsupportedOpcode(opcode), nullptr); return graph()->NewNode(UnsupportedOpcode(opcode), nullptr);
} }
@ -3169,20 +3078,6 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
int index = static_cast<int>(function_->func_index); int index = static_cast<int>(function_->func_index);
// Run lowering pass if SIMD ops are present in the function
if (builder.has_simd_ops()) {
SimdLowering simd(jsgraph_->zone(), &builder);
GraphReducer graph_reducer(jsgraph_->zone(), graph);
graph_reducer.AddReducer(&simd);
graph_reducer.ReduceGraph();
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Graph after simd lowering -- " << std::endl;
os << AsRPO(*graph);
}
}
if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) { if (index >= FLAG_trace_wasm_ast_start && index < FLAG_trace_wasm_ast_end) {
OFStream os(stdout); OFStream os(stdout);
PrintAst(isolate_->allocator(), body, os, nullptr); PrintAst(isolate_->allocator(), body, os, nullptr);

View File

@ -24,7 +24,6 @@ class JSGraph;
class Graph; class Graph;
class Operator; class Operator;
class SourcePositionTable; class SourcePositionTable;
class MachineOperatorBuilder;
} // namespace compiler } // namespace compiler
namespace wasm { namespace wasm {
@ -95,7 +94,6 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::ModuleEnv* module,
// Abstracts details of building TurboFan graph nodes for WASM to separate // Abstracts details of building TurboFan graph nodes for WASM to separate
// the WASM decoder from the internal details of TurboFan. // the WASM decoder from the internal details of TurboFan.
class WasmTrapHelper; class WasmTrapHelper;
enum class Conversion { kNone, kOpaque, kInt32, kFloat32, kFloat64 };
typedef ZoneVector<Node*> NodeVector; typedef ZoneVector<Node*> NodeVector;
class WasmGraphBuilder { class WasmGraphBuilder {
public: public:
@ -131,7 +129,6 @@ class WasmGraphBuilder {
Node* Float32Constant(float value); Node* Float32Constant(float value);
Node* Float64Constant(double value); Node* Float64Constant(double value);
Node* HeapConstant(Handle<HeapObject> value); Node* HeapConstant(Handle<HeapObject> value);
Node* DefaultS128Value();
Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right, Node* Binop(wasm::WasmOpcode opcode, Node* left, Node* right,
wasm::WasmCodePosition position = wasm::kNoCodePosition); wasm::WasmCodePosition position = wasm::kNoCodePosition);
Node* Unop(wasm::WasmOpcode opcode, Node* input, Node* Unop(wasm::WasmOpcode opcode, Node* input,
@ -166,8 +163,6 @@ class WasmGraphBuilder {
Node* FromJS(Node* node, Node* context, wasm::LocalType type); Node* FromJS(Node* node, Node* context, wasm::LocalType type);
Node* Invert(Node* node); Node* Invert(Node* node);
Node* FunctionTable(uint32_t index); Node* FunctionTable(uint32_t index);
Node* ChangeToRuntimeCall(Node* node, Runtime::FunctionId function_id,
Signature<Conversion>* signature);
//----------------------------------------------------------------------- //-----------------------------------------------------------------------
// Operations that concern the linear memory. // Operations that concern the linear memory.
@ -201,8 +196,6 @@ class WasmGraphBuilder {
Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs); Node* SimdOp(wasm::WasmOpcode opcode, const NodeVector& inputs);
bool has_simd_ops() { return has_simd_ops_; }
private: private:
static const int kDefaultBufferSize = 16; static const int kDefaultBufferSize = 16;
friend class WasmTrapHelper; friend class WasmTrapHelper;
@ -224,7 +217,6 @@ class WasmGraphBuilder {
SetOncePointer<const Operator> allocate_heap_number_operator_; SetOncePointer<const Operator> allocate_heap_number_operator_;
compiler::SourcePositionTable* source_position_table_ = nullptr; compiler::SourcePositionTable* source_position_table_ = nullptr;
bool has_simd_ops_ = false;
// Internal helper methods. // Internal helper methods.
JSGraph* jsgraph() { return jsgraph_; } JSGraph* jsgraph() { return jsgraph_; }
@ -312,7 +304,6 @@ class WasmGraphBuilder {
Node* BuildJavaScriptToNumber(Node* node, Node* context, Node* effect, Node* BuildJavaScriptToNumber(Node* node, Node* context, Node* effect,
Node* control); Node* control);
Node* BuildChangeInt32ToTagged(Node* value); Node* BuildChangeInt32ToTagged(Node* value);
Node* BuildChangeTaggedToInt32(Node* value);
Node* BuildChangeFloat64ToTagged(Node* value); Node* BuildChangeFloat64ToTagged(Node* value);
Node* BuildChangeTaggedToFloat64(Node* value); Node* BuildChangeTaggedToFloat64(Node* value);
@ -345,9 +336,6 @@ class WasmGraphBuilder {
if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*)); if (buf != buffer) memcpy(buf, buffer, old_count * sizeof(Node*));
return buf; return buf;
} }
// Simd helper functions
MachineOperatorBuilder* simd();
}; };
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal

View File

@ -715,8 +715,6 @@
'compiler/scheduler.h', 'compiler/scheduler.h',
'compiler/select-lowering.cc', 'compiler/select-lowering.cc',
'compiler/select-lowering.h', 'compiler/select-lowering.h',
'compiler/simd-lowering.cc',
'compiler/simd-lowering.h',
'compiler/simplified-lowering.cc', 'compiler/simplified-lowering.cc',
'compiler/simplified-lowering.h', 'compiler/simplified-lowering.h',
'compiler/simplified-operator-reducer.cc', 'compiler/simplified-operator-reducer.cc',

View File

@ -192,7 +192,6 @@
'wasm/test-run-wasm-js.cc', 'wasm/test-run-wasm-js.cc',
'wasm/test-run-wasm-module.cc', 'wasm/test-run-wasm-module.cc',
'wasm/test-run-wasm-relocation.cc', 'wasm/test-run-wasm-relocation.cc',
'wasm/test-run-wasm-simd.cc',
'wasm/test-signatures.h', 'wasm/test-signatures.h',
'wasm/test-wasm-function-name-table.cc', 'wasm/test-wasm-function-name-table.cc',
'wasm/test-wasm-stack.cc', 'wasm/test-wasm-stack.cc',

View File

@ -1,60 +0,0 @@
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdlib.h>
#include <string.h>
#include "src/wasm/encoder.h"
#include "src/wasm/wasm-js.h"
#include "src/wasm/wasm-macro-gen.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "test/cctest/cctest.h"
#include "test/cctest/wasm/test-signatures.h"
using namespace v8::base;
using namespace v8::internal;
using namespace v8::internal::compiler;
using namespace v8::internal::wasm;
namespace {
void TestModule(Zone* zone, WasmModuleBuilder* builder,
int32_t expected_result) {
FLAG_wasm_simd_prototype = true;
FLAG_wasm_num_compilation_tasks = 0;
ZoneBuffer buffer(zone);
builder->WriteTo(buffer);
Isolate* isolate = CcTest::InitIsolateOnce();
HandleScope scope(isolate);
WasmJs::InstallWasmFunctionMap(isolate, isolate->native_context());
int32_t result =
testing::CompileAndRunWasmModule(isolate, buffer.begin(), buffer.end());
CHECK_EQ(expected_result, result);
}
void ExportAsMain(WasmFunctionBuilder* f) {
static const char kMainName[] = "main";
f->SetExported();
f->SetName(kMainName, arraysize(kMainName) - 1);
}
} // namespace
TEST(Run_WasmMoule_simd) {
v8::base::AccountingAllocator allocator;
Zone zone(&allocator);
TestSignatures sigs;
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
uint16_t f_index = builder->AddFunction();
WasmFunctionBuilder* f = builder->FunctionAt(f_index);
f->SetSignature(sigs.i_i());
ExportAsMain(f);
byte code[] = {WASM_SIMD_I32x4_EXTRACT_LANE(
WASM_SIMD_I32x4_SPLAT(WASM_I8(123)), WASM_I8(2))};
f->EmitCode(code, sizeof(code));
TestModule(&zone, builder, 123);
}

View File

@ -1,23 +0,0 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-wasm --wasm-simd-prototype --wasm-num-compilation-tasks=0
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
// TODO(gdeepti): Currently wasm simd ops are tested using runtime calls to
// JS runtime functions, as this needs heap allocation sequential compile is
// triggered here. This is only used for bootstrapping and needs to be removed
// when we have architectuaral/scalar implementations for wasm simd ops.
(function SimdSplatExtractTest() {
var module = new WasmModuleBuilder();
module.addFunction("splatextract", kSig_i_ii)
.addBody([kExprGetLocal, 0, kExprSimdPrefix, kExprI32x4Splat,
kExprI32Const, 1, kExprSimdPrefix, kExprI32x4ExtractLane])
.exportAs("main");
var instance = module.instantiate();
assertEquals(123, instance.exports.main(123, 2));
})();

View File

@ -307,9 +307,6 @@ var kExprI32Ror = 0xb6;
var kExprI32Rol = 0xb7; var kExprI32Rol = 0xb7;
var kExprI64Ror = 0xb8; var kExprI64Ror = 0xb8;
var kExprI64Rol = 0xb9; var kExprI64Rol = 0xb9;
var kExprSimdPrefix = 0xe5;
var kExprI32x4Splat = 0x1b;
var kExprI32x4ExtractLane = 0x1c;
var kTrapUnreachable = 0; var kTrapUnreachable = 0;
var kTrapMemOutOfBounds = 1; var kTrapMemOutOfBounds = 1;