Index: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h =================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -202,6 +202,8 @@ void DumpKernels(Stream &strm) const; + void ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute); + void AttemptBreakpointAtKernelName(Stream &strm, const char *name, Error &error, lldb::TargetSP target); void SetBreakAllKernels(bool do_break, lldb::TargetSP target); @@ -220,6 +222,9 @@ protected: + struct ScriptDetails; + struct AllocationDetails; + void InitSearchFilter(lldb::TargetSP target) { if (!m_filtersp) @@ -230,6 +235,10 @@ void LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind); + bool RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr); + + bool EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result); + lldb::BreakpointSP CreateKernelBreakpoint(const ConstString& name); void BreakOnModuleKernels(const lldb_renderscript::RSModuleDescriptorSP rsmodule_sp); @@ -256,9 +265,6 @@ typedef std::shared_ptr RuntimeHookSP; - struct ScriptDetails; - struct AllocationDetails; - lldb::ModuleSP m_libRS; lldb::ModuleSP m_libRSDriver; lldb::ModuleSP m_libRSCpuRef; @@ -292,6 +298,18 @@ void CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context); void CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context); + // + // Helper functions for jitting the runtime + // + bool JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, + unsigned int x = 0, unsigned int y = 0, unsigned int z = 0); + + bool JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr); + + bool JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr); + + bool JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr); + // Search for a script detail object using a target address. // If a script does not currently exist this function will return nullptr. // If 'create' is true and there is no previous script with this address, Index: lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp =================================================================== --- lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ lldb/trunk/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -25,7 +25,7 @@ #include "lldb/Interpreter/CommandObjectMultiword.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Target/RegisterContext.h" - +#include "lldb/Expression/UserExpression.h" #include "lldb/Symbol/VariableList.h" using namespace lldb; @@ -130,26 +130,116 @@ // allocation instance. struct RenderScriptRuntime::AllocationDetails { - ~AllocationDetails () {}; + // Taken from rsDefines.h + enum DataKind + { + RS_KIND_USER, + RS_KIND_PIXEL_L = 7, + RS_KIND_PIXEL_A, + RS_KIND_PIXEL_LA, + RS_KIND_PIXEL_RGB, + RS_KIND_PIXEL_RGBA, + RS_KIND_PIXEL_DEPTH, + RS_KIND_PIXEL_YUV, + RS_KIND_INVALID = 100 + }; + + // Taken from rsDefines.h + enum DataType + { + RS_TYPE_NONE = 0, + RS_TYPE_FLOAT_16, + RS_TYPE_FLOAT_32, + RS_TYPE_FLOAT_64, + RS_TYPE_SIGNED_8, + RS_TYPE_SIGNED_16, + RS_TYPE_SIGNED_32, + RS_TYPE_SIGNED_64, + RS_TYPE_UNSIGNED_8, + RS_TYPE_UNSIGNED_16, + RS_TYPE_UNSIGNED_32, + RS_TYPE_UNSIGNED_64, + RS_TYPE_BOOLEAN + }; - enum DataType + struct Dimension { - eInt, + uint32_t dim_1; + uint32_t dim_2; + uint32_t dim_3; + uint32_t cubeMap; + + Dimension() + { + dim_1 = 0; + dim_2 = 0; + dim_3 = 0; + cubeMap = 0; + } }; - enum Dimension + // Monotonically increasing from 1 + static unsigned int ID; + + // Maps Allocation DataType enum and vector size to printable strings + // using mapping from RenderScript numerical types summary documentation + static const char* RsDataTypeToString[][4]; + + // Maps Allocation DataKind enum to printable strings + static const char* RsDataKindToString[]; + + // Give each allocation an ID as a way + // for commands to reference it. + const unsigned int id; + + empirical_type type; // Type of each data pointer stored by the allocation + empirical_type type_kind; // Defines pixel type if Allocation is created from an image + empirical_type type_vec_size; // Vector size of each data point, e.g '4' for uchar4 + empirical_type dimension; // Dimensions of the Allocation + empirical_type address; // Pointer to address of the RS Allocation + empirical_type data_ptr; // Pointer to the data held by the Allocation + empirical_type type_ptr; // Pointer to the RS Type of the Allocation + empirical_type element_ptr; // Pointer to the RS Element of the Type + empirical_type context; // Pointer to the RS Context of the Allocation + + // Give each allocation an id, so we can reference it in user commands. + AllocationDetails(): id(ID++) { - e1d, - e2d, - e3d, - eCubeMap, - }; + } - empirical_type type; - empirical_type dimension; - empirical_type address; - empirical_type dataPtr; - empirical_type context; +}; + +unsigned int RenderScriptRuntime::AllocationDetails::ID = 1; + +const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = +{ + "User", + "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7 + "Undefined", "Undefined", "Undefined", + "L Pixel", + "A Pixel", + "LA Pixel", + "RGB Pixel", + "RGBA Pixel", + "Pixel Depth", + "YUV Pixel" +}; + +const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = +{ + {"None", "None", "None", "None"}, + {"half", "half2", "half3", "half4"}, + {"float", "float2", "float3", "float4"}, + {"double", "double2", "double3", "double4"}, + {"char", "char2", "char3", "char4"}, + {"short", "short2", "short3", "short4"}, + {"int", "int2", "int3", "int4"}, + {"long", "long2", "long3", "long4"}, + {"uchar", "uchar2", "uchar3", "uchar4"}, + {"ushort", "ushort2", "ushort3", "ushort4"}, + {"uint", "uint2", "uint3", "uint4"}, + {"ulong", "ulong2", "ulong3", "ulong4"}, + {"bool", "bool2", "bool3", "bool4"} }; //------------------------------------------------------------------ @@ -250,7 +340,7 @@ return eModuleKindDriver; } - const ConstString rs_cpureflib("libRSCPURef.so"); + const ConstString rs_cpureflib("libRSCpuRef.so"); if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) { return eModuleKindImpl; @@ -820,6 +910,330 @@ } } +// Uses the Target API to evaluate the expression passed as a parameter to the function +// The result of that expression is returned an unsigned 64 bit int, via the result* paramter. +// Function returns true on success, and false on failure +bool +RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result) +{ + Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + if (log) + log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression); + + ValueObjectSP expr_result; + // Perform the actual expression evaluation + GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result); + + if (!expr_result) + { + if (log) + log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression"); + return false; + } + + // The result of the expression is invalid + if (!expr_result->GetError().Success()) + { + Error err = expr_result->GetError(); + if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success + { + if (log) + log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void"); + + result = nullptr; + return true; + } + + if (log) + log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString()); + return false; + } + + bool success = false; + *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int. + + if (!success) + { + if (log) + log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int"); + return false; + } + + return true; +} + +// Used to index expression format strings +enum ExpressionStrings +{ + eExprGetOffsetPtr = 0, + eExprAllocGetType, + eExprTypeDimX, + eExprTypeDimY, + eExprTypeDimZ, + eExprTypeElemPtr, + eExprElementType, + eExprElementKind, + eExprElementVec +}; + +// Format strings containing the expressions we may need to evaluate. +const char runtimeExpressions[][256] = +{ + // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) + "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", + + // Type* rsaAllocationGetType(Context*, Allocation*) + "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", + + // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) + // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; + // mHal.state.lodCount; mHal.state.faces; mElement; into typeData + // Need to specify 32 or 64 bit for uint_t since this differs between devices + "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim + "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim + "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim + "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr + + // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) + // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData + "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type + "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind + "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]" // Vector Size +}; + +// JITs the RS runtime for the internal data pointer of an allocation. +// Is passed x,y,z coordinates for the pointer to a specific element. +// Then sets the data_ptr member in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, + unsigned int x, unsigned int y, unsigned int z) +{ + Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + + if (!allocation->address.isValid()) + { + if (log) + log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); + return false; + } + + const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; + const int max_expr_size = 512; // Max expression size + char buffer[max_expr_size]; + + int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z); + if (chars_written < 0) + { + if (log) + log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); + return false; + } + else if (chars_written >= max_expr_size) + { + if (log) + log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); + return false; + } + + uint64_t result = 0; + if (!EvalRSExpression(buffer, frame_ptr, &result)) + return false; + + addr_t mem_ptr = static_cast(result); + allocation->data_ptr = mem_ptr; + + return true; +} + +// JITs the RS runtime for the internal pointer to the RS Type of an allocation +// Then sets the type_ptr member in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr) +{ + Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + + if (!allocation->address.isValid() || !allocation->context.isValid()) + { + if (log) + log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); + return false; + } + + const char* expr_cstr = runtimeExpressions[eExprAllocGetType]; + const int max_expr_size = 512; // Max expression size + char buffer[max_expr_size]; + + int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get()); + if (chars_written < 0) + { + if (log) + log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); + return false; + } + else if (chars_written >= max_expr_size) + { + if (log) + log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); + return false; + } + + uint64_t result = 0; + if (!EvalRSExpression(buffer, frame_ptr, &result)) + return false; + + addr_t type_ptr = static_cast(result); + allocation->type_ptr = type_ptr; + + return true; +} + +// JITs the RS runtime for information about the dimensions and type of an allocation +// Then sets dimension and element_ptr members in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr) +{ + Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + + if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) + { + if (log) + log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); + return false; + } + + // Expression is different depending on if device is 32 or 64 bit + uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); + const unsigned int bits = archByteSize == 4 ? 32 : 64; + + // We want 4 elements from packed data + const unsigned int num_exprs = 4; + assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions"); + + const int max_expr_size = 512; // Max expression size + char buffer[num_exprs][max_expr_size]; + uint64_t results[num_exprs]; + + for (unsigned int i = 0; i < num_exprs; ++i) + { + int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits, + *allocation->context.get(), *allocation->type_ptr.get()); + if (chars_written < 0) + { + if (log) + log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); + return false; + } + else if (chars_written >= max_expr_size) + { + if (log) + log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); + return false; + } + + // Perform expression evaluation + if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) + return false; + } + + // Assign results to allocation members + AllocationDetails::Dimension dims; + dims.dim_1 = static_cast(results[0]); + dims.dim_2 = static_cast(results[1]); + dims.dim_3 = static_cast(results[2]); + allocation->dimension = dims; + + addr_t elem_ptr = static_cast(results[3]); + allocation->element_ptr = elem_ptr; + + if (log) + log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, + dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); + + return true; +} + +// JITs the RS runtime for information about the Element of an allocation +// Then sets type, type_vec_size, and type_kind members in Allocation with the result. +// Returns true on success, false otherwise +bool +RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr) +{ + Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); + + if (!allocation->element_ptr.isValid() || !allocation->context.isValid()) + { + if (log) + log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); + return false; + } + + // We want 3 elements from packed data + const unsigned int num_exprs = 3; + assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions"); + + const int max_expr_size = 512; // Max expression size + char buffer[num_exprs][max_expr_size]; + uint64_t results[num_exprs]; + + for (unsigned int i = 0; i < num_exprs; i++) + { + int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get()); + if (chars_written < 0) + { + if (log) + log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); + return false; + } + else if (chars_written >= max_expr_size) + { + if (log) + log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); + return false; + } + + // Perform expression evaluation + if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) + return false; + } + + // Assign results to allocation members + allocation->type = static_cast(results[0]); + allocation->type_kind = static_cast(results[1]); + allocation->type_vec_size = static_cast(results[2]); + + if (log) + log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u", + *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get()); + + return true; +} + +// JIT all the current runtime info regarding an allocation +bool +RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) +{ + // GetOffsetPointer() + if (!JITDataPointer(allocation, frame_ptr)) + return false; + + // rsaAllocationGetType() + if (!JITTypePointer(allocation, frame_ptr)) + return false; + + // rsaTypeGetNativeData() + if (!JITTypePacked(allocation, frame_ptr)) + return false; + + // rsaElementGetNativeData() + if (!JITElementPacked(allocation, frame_ptr)) + return false; + + return true; +} + bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { @@ -1114,6 +1528,89 @@ strm.IndentLess(); } +// Prints infomation regarding all the currently loaded allocations. +// These details are gathered by jitting the runtime, which has as latency. +void +RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) +{ + strm.Printf("RenderScript Allocations:"); + strm.EOL(); + strm.IndentMore(); + + for (auto &alloc : m_allocations) + { + // JIT the allocation info if we haven't done it, or the user forces us to. + bool do_refresh = !alloc->data_ptr.isValid() || recompute; + + // JIT current allocation information + if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) + { + strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); + continue; + } + + strm.Printf("%u:\n",alloc->id); + strm.IndentMore(); + + strm.Indent("Context: "); + if (!alloc->context.isValid()) + strm.Printf("unknown\n"); + else + strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); + + strm.Indent("Address: "); + if (!alloc->address.isValid()) + strm.Printf("unknown\n"); + else + strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); + + strm.Indent("Data pointer: "); + if (!alloc->data_ptr.isValid()) + strm.Printf("unknown\n"); + else + strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); + + strm.Indent("Dimensions: "); + if (!alloc->dimension.isValid()) + strm.Printf("unknown\n"); + else + strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1, + alloc->dimension.get()->dim_2, + alloc->dimension.get()->dim_3); + + strm.Indent("Data Type: "); + if (!alloc->type.isValid() || !alloc->type_vec_size.isValid()) + strm.Printf("unknown\n"); + else + { + const int vector_size = *alloc->type_vec_size.get(); + const AllocationDetails::DataType type = *alloc->type.get(); + + if (vector_size > 4 || vector_size < 1 || + type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN) + strm.Printf("invalid type\n"); + else + strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast(type)][vector_size-1]); + } + + strm.Indent("Data Kind: "); + if (!alloc->type_kind.isValid()) + strm.Printf("unknown\n"); + else + { + const AllocationDetails::DataKind kind = *alloc->type_kind.get(); + if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV) + strm.Printf("invalid kind\n"); + else + strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast(kind)]); + } + + strm.EOL(); + strm.IndentLess(); + } + strm.IndentLess(); +} + // Set breakpoints on every kernel found in RS module void RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp) @@ -1608,6 +2105,108 @@ ~CommandObjectRenderScriptRuntimeContext() {} }; +class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed +{ + public: + CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "renderscript allocation list", + "List renderscript allocations and their information.", "renderscript allocation list", + eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) + { + } + + virtual Options* + GetOptions() + { + return &m_options; + } + + class CommandOptions : public Options + { + public: + CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) + { + } + + virtual + ~CommandOptions() + { + } + + virtual Error + SetOptionValue(uint32_t option_idx, const char *option_arg) + { + Error error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) + { + case 'r': + m_refresh = true; + break; + default: + error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); + break; + } + return error; + } + + void + OptionParsingStarting() + { + m_refresh = false; + } + + const OptionDefinition* + GetDefinitions() + { + return g_option_table; + } + + static OptionDefinition g_option_table[]; + bool m_refresh; + }; + + ~CommandObjectRenderScriptRuntimeAllocationList() {} + + bool + DoExecute(Args &command, CommandReturnObject &result) + { + RenderScriptRuntime *runtime = + static_cast(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); + runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + + private: + CommandOptions m_options; +}; + +OptionDefinition +CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = +{ + { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, + "Recompute allocation details."}, + { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } +}; + + +class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword +{ + private: + public: + CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", + NULL) + { + LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); + } + + ~CommandObjectRenderScriptRuntimeAllocation() {} +}; + + class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed { private: @@ -1643,6 +2242,7 @@ LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter))); LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter))); LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter))); + LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter))); } ~CommandObjectRenderScriptRuntime() {}