Function &OptimizeForRuntime(Function &F) { #ifdef DEBUG static PassManagerBuilder Builder = getDebugBuilder(); #else static PassManagerBuilder Builder = getBuilder(); #endif Module *M = F.getParent(); opt::GenerateOutput = true; polly::opt::PollyParallel = true; FunctionPassManager PM = FunctionPassManager(M); Builder.populateFunctionPassManager(PM); PM.doInitialization(); PM.run(F); PM.doFinalization(); if (opt::havePapi()) { PassManager MPM; Builder.populateModulePassManager(MPM); MPM.add(polli::createTraceMarkerPass()); MPM.run(*M); } if (opt::haveLikwid()) { PassManager MPM; Builder.populateModulePassManager(MPM); MPM.add(polli::createLikwidMarkerPass()); MPM.run(*M); } DEBUG( StoreModule(*M, M->getModuleIdentifier() + ".after.polly.ll") ); opt::GenerateOutput = false; return F; }
void ModuleLoader::StorePreBuiltModule( v8::Isolate* isolate, v8::Local<v8::Object>& exportObject, const std::string& name ) { StoreModule( "", name, name, isolate, exportObject ); }
/** * ### var module = require("module-name"); * * * There is no standard for modules or the 'require' keyword in JavaScript.<br /> * However CommonJS have this: http://wiki.commonjs.org/wiki/Modules/1.1.1 ( used by Node.js). * <br /> <br /> * * The concept behind 'require' keyword is simple, it allows you to include another * JavaScript file, which exports an API / function / constructor / singleton. * * * // example_module.js * exports.hello = function() { return "hello world" } * * <br /> * * // main.js * var example = require( "example_module.js"); * * log( example.hello() ); * * * ### Module writers guide: * * * #### Exporting as a namespace * * Example of using a namespace to export functions / objects. * * // filesystem-helper.js * exports.version = "FileSystem helper 1.0"; * exports.open = function() { } * exports.close = function() { } * exports.read = function() { } * exports.write = function() { ... } * exports.fileSize = function() {...} * * <br /> * * // main.js * var fs = require( "filesystem-helper.js"); * * log( fs.version ); * * var file = fs.open("myfile.txt"); * var data = fs.read( file ); * * * * #### Exporting as a function * * In this example we are using module.exports directly to change it * from an object literal with name-value pairs (exports object) to a function. * * // my_first_module.js * module.exports = function() { log("hello-world"); } * * <br /> * * // main.js * var func = require("my_first_module.js"); * func(); // prints out hello-world * * * #### Exporting as a constructor * * * // ImageActor.js * function ImageActor( position, orientation, image, name ) * { * this = new dali.ImageActor( image ); * this.position = position; * this.orientation = orientation; * this.name = name; * } * module.exports = ImageActor; * * <br /> * * // main.js * * var ImageActor = require(" ImageActor.js"); * * var imageActor = new ImageActor( position, orientation, image, "my first image actor"); * * #### Exporting as a singleton * * By exporting a singleton you have an object which has shared state between * any modules using it. * * example: * * // image-database.js * * function ImageDatabase( ) * { * this.addImage = function() { ... }; * this.removeImage = function() { ... }; * this.getImage = function() { ...}; * this.getImageCount = function() { ... }; * } * * module.exports = new ImageDatabase(); * * * <br /> * * // main.js * * var database = require('image-database.js'); * * database.addImage( myImage ); * * <br /> * * // another-module.js * var database = require('image-database.js'); * * // gets the same database object as main.js * * * The first call to require('image-database.js') will create the image database. * Further calls, will return the same instance, because require caches module.exports. * Otherwise it would have to recompile and run the module every time require is called. * * ## Notes * * #### Automatic wrapping of a module by DALi: * * The module is automatically wrapped in a function by DALi before being executed ( similar technique to Node.js). </br> * This is to prevent any functions / variables declared by the module entering the global namespace. </br> * Currently the module will have access to all DALi global functions, like log, require and the DALi API ( actors / stage etc).</br> * * * // Parameters passed to the internally generated function * // module = reference to current module * // module.exports = defines what the module exports * // exports = reference to module.exports * // __filename = module filename * // __dirname = module directory * * function createModuleXYZ( exports ( === module.exports), module, __filename, __dirname ) * { * // * // Module code automatically inserted here. * // * log(" my first module "); * var version = "1.3"; // this won't pollute global namespace * exports.version = version; * exports.logActorPosition = function( actorName ) * { * var actor = dali.stage.getRootLayer().findChildByName(actorName ); * log( actor.x + "," + actor.y + "," + actor.z ); * } * // * // End module code * // * * return module.exports; * } * * Initially module.exports is an object literal with name-value pairs ( exports object). * However it can be re-assigned to a constructor / function / singleton object as shown * in the examples above. * * * ### Circular dependencies: * * DALi JS supports circular dependencies as required by the CommonJS specification. * * #### a.js * * * export.version = "1.3" * export.loaded = false; * var bModule = require('b.js') * export.loaded = true; * * #### b.js * * var aModule = require('a.js') * log( "aModule version = " + aModule.version + ", aModule loaded = " + aModule.loaded ); * * //prints aModule = 1.3, aModule loaded = false * * #### main.js * * var aModule = require("a.js"); * * * When b.js requires a.js, it is given everything that is exported from a.js, up to the point * b.js is required by a.js. * * ### 'require' background * * There is alternative to module spec in CommonJS called RequireJs ( http://requirejs.org/docs/node.html) <br /> * DALi JS tries to follows the CommonJS specification (used by Node.js) as it * is supposed to be better suited to server side development. <br /><br /> * * @method require * @for ModuleLoader * */ void ModuleLoader::Require(const v8::FunctionCallbackInfo< v8::Value >& args ) { v8::Isolate* isolate = args.GetIsolate(); v8::HandleScope handleScope( isolate ); bool found( false ); std::string fileName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate , args ); if( !found ) { DALI_SCRIPT_EXCEPTION( isolate, "require missing module name"); return; } // strip off any path / .js std::string moduleName; V8Utils::GetModuleName( fileName, moduleName ); // see if the module already exists const Module* existingModule = FindModule( moduleName ); if( existingModule ) { // printf(" using existing module %s \n",moduleName.c_str() ); args.GetReturnValue().Set( existingModule->mExportsObject ); return; } std::string path = mCurrentScriptPath; // path of top level script being executed std::string contents; V8Utils::GetFileContents(path + fileName, contents); // wrap the module in a function to protect global namespace. // the create function itself is global so we make it unique for each module // For reference nodeJs does this as an anonymous function, but we're calling it from native side // so need to pass parameters / get a name for it. std::string functionName ="__createModule" + moduleName; std::string source = "function " + functionName + "( exports, module, __filename, __directory) { "; source+= contents; source+=" \n };"; // close the function CompileAndRun( isolate, source, fileName ); // We need to create module object, so that the module can read / write properties to it v8::Local<v8::Object> moduleObject = v8::Object::New( isolate ); v8::Local<v8::Object> exportsObject = v8::Object::New( isolate ); moduleObject->Set( v8::String::NewFromUtf8( isolate, "exports"), exportsObject ); moduleObject->Set( v8::String::NewFromUtf8( isolate, "id"), v8::String::NewFromUtf8( isolate ,moduleName.c_str() ) ); // store the module exports object now, this is to allow for circular dependencies. // If this-module requires another module, which then requires this module ( creating a circle), it will be given an export object // which contains everything exported so far. Module* module = StoreModule( path, fileName, moduleName, isolate, exportsObject ); v8::Local<v8::Context> currentContext = isolate->GetCurrentContext(); // get the CreateModule function v8::Local<v8::Function> createModule = v8::Local<v8::Function>::Cast(currentContext->Global()->Get(v8::String::NewFromUtf8( isolate, functionName.c_str() ))); // add the arguments std::vector< v8::Local<v8::Value> > arguments; arguments.push_back( exportsObject ); arguments.push_back( moduleObject ); arguments.push_back( v8::String::NewFromUtf8( isolate, fileName.c_str() )); arguments.push_back( v8::String::NewFromUtf8( isolate, path.c_str() )); // call the CreateModule function createModule->Call( createModule, arguments.size(), &arguments[0]); //[0] // get the module.export object, the module writer may have re-assinged module.exports, so the exports object // no longer references it. v8::Local<v8::Value> moduleExportsValue = moduleObject->Get( v8::String::NewFromUtf8( isolate, "exports")); v8::Local<v8::Object> moduleExports = moduleExportsValue->ToObject(); // Re-store the export ( possible nothing happens, because exports hasn't been re-assigned). module->mExportsObject.Reset( isolate, moduleExports); args.GetReturnValue().Set( moduleExports ); }
Handle poly_dispatch_c(TaskData *taskData, Handle args, Handle code) { unsigned c = get_C_unsigned(taskData, DEREFWORDHANDLE(code)); switch (c) { case 1: return exportNative(taskData, args); // Export case 2: raise_syscall(taskData, "C Export has been withdrawn", 0); return 0; case 3: return exportPortable(taskData, args); // Export as portable format case 9: // Return the GIT version if appropriate { return SAVE(C_string_to_Poly(taskData, GitVersion)); } case 10: // Return the RTS version string. { const char *version; switch (machineDependent->MachineArchitecture()) { case MA_Interpreted: version = "Portable-" TextVersion; break; case MA_I386: version = "I386-" TextVersion; break; case MA_X86_64: version = "X86_64-" TextVersion; break; default: version = "Unknown-" TextVersion; break; } return SAVE(C_string_to_Poly(taskData, version)); } case 11: // Return the RTS copyright string return SAVE(C_string_to_Poly(taskData, poly_runtime_system_copyright)); case 12: // Return the architecture { const char *arch; switch (machineDependent->MachineArchitecture()) { case MA_Interpreted: arch = "Interpreted"; break; case MA_I386: arch = "I386"; break; case MA_X86_64: arch = "X86_64"; break; default: arch = "Unknown"; break; } return SAVE(C_string_to_Poly(taskData, arch)); } case 13: // Share common immutable data. { ShareData(taskData, args); return SAVE(TAGGED(0)); } // ObjSize and ShowSize have their own IO vector entries but really they don't // need them. Include them here and add ObjProfile. case 14: return ObjSize(taskData, args); case 15: return ShowSize(taskData, args); case 16: return ObjProfile(taskData, args); /* 17 and 18 are no longer used. */ case 19: // Return the RTS argument help string. return SAVE(C_string_to_Poly(taskData, RTSArgHelp())); case 20: // Write a saved state file. return SaveState(taskData, args); case 21: // Load a saved state file and any ancestors. return LoadState(taskData, false, args); case 22: // Show the hierarchy. return ShowHierarchy(taskData); case 23: // Change the name of the immediate parent stored in a child return RenameParent(taskData, args); case 24: // Return the name of the immediate parent stored in a child return ShowParent(taskData, args); case 25: // Old statistics - now removed case 26: raise_exception_string(taskData, EXC_Fail, "No statistics available"); case 27: // Get number of user statistics available return Make_arbitrary_precision(taskData, N_PS_USER); case 28: // Set an entry in the user stats table. { unsigned index = get_C_unsigned(taskData, DEREFHANDLE(args)->Get(0)); if (index >= N_PS_USER) raise_exception0(taskData, EXC_subscript); POLYSIGNED value = getPolySigned(taskData, DEREFHANDLE(args)->Get(1)); globalStats.setUserCounter(index, value); Make_arbitrary_precision(taskData, 0); } case 29: // Get local statistics. return globalStats.getLocalStatistics(taskData); case 30: // Get remote statistics. The argument is the process ID to get the statistics. return globalStats.getRemoteStatistics(taskData, getPolyUnsigned(taskData, DEREFHANDLE(args))); case 31: // Store a module return StoreModule(taskData, args); case 32: // Load a module return LoadModule(taskData, args); case 33: // Load hierarchy. This provides a complete list of children and parents. return LoadState(taskData, true, args); case 34: // Return the system directory for modules. This is configured differently // in Unix and in Windows. #if (defined(MODULEDIR)) return SAVE(C_string_to_Poly(taskData, Xstr(MODULEDIR))); #elif (defined(_WIN32) && ! defined(__CYGWIN__)) { // This registry key is configured when Poly/ML is installed using the installer. // It gives the path to the Poly/ML installation directory. We return the // Modules subdirectory. HKEY hk; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\PolyML.exe"), 0, KEY_QUERY_VALUE, &hk) == ERROR_SUCCESS) { DWORD valSize; if (RegQueryValueEx(hk, _T("Path"), 0, NULL, NULL, &valSize) == ERROR_SUCCESS) { #define MODULEDIR _T("Modules") TempString buff((TCHAR*)malloc(valSize + (_tcslen(MODULEDIR) + 1)*sizeof(TCHAR))); DWORD dwType; if (RegQueryValueEx(hk, _T("Path"), 0, &dwType, (LPBYTE)(LPTSTR)buff, &valSize) == ERROR_SUCCESS) { RegCloseKey(hk); // The registry entry should end with a backslash. _tcscat(buff, MODULEDIR); return SAVE(C_string_to_Poly(taskData, buff)); } } RegCloseKey(hk); } return SAVE(C_string_to_Poly(taskData, "")); } #else return SAVE(C_string_to_Poly(taskData, "")); #endif case 50: // GCD return gcd_arbitrary(taskData, SAVE(DEREFHANDLE(args)->Get(0)), SAVE(DEREFHANDLE(args)->Get(1))); case 51: // LCM return lcm_arbitrary(taskData, SAVE(DEREFHANDLE(args)->Get(0)), SAVE(DEREFHANDLE(args)->Get(1))); // These next ones were originally in process_env and have now been moved here, case 100: /* Return the maximum word segment size. */ return taskData->saveVec.push(TAGGED(MAX_OBJECT_SIZE)); case 101: /* Return the maximum string size (in bytes). It is the maximum number of bytes in a segment less one word for the length field. */ return taskData->saveVec.push(TAGGED((MAX_OBJECT_SIZE)*sizeof(PolyWord) - sizeof(PolyWord))); case 102: /* Test whether the supplied address is in the io area. This was previously done by having get_flags return 256 but this was changed so that get_flags simply returns the top byte of the length word. */ { PolyWord *pt = (PolyWord*)DEREFWORDHANDLE(args); if (gMem.IsIOPointer(pt)) return Make_arbitrary_precision(taskData, 1); else return Make_arbitrary_precision(taskData, 0); } case 103: /* Return the register mask for the given function. This is used by the code-generator to find out which registers are modified by the function and so need to be saved if they are used by the caller. */ { PolyObject *pt = DEREFWORDHANDLE(args); if (gMem.IsIOPointer(pt)) { /* IO area. We need to get this from the vector. */ int i; for (i=0; i < POLY_SYS_vecsize; i++) { if (pt == (PolyObject*)IoEntry(i)) { int regMask = taskData->GetIOFunctionRegisterMask(i); POLYUNSIGNED props = rtsProperties(taskData, i); return taskData->saveVec.push(TAGGED(regMask | props)); } } raise_exception_string(taskData, EXC_Fail, "Io pointer not found"); } else { /* We may have a pointer to the code or a pointer to a closure. If it's a closure we have to find the code. */ if (! pt->IsCodeObject() && ! pt->IsByteObject()) pt = pt->Get(0).AsObjPtr(); /* Should now be a code object. */ if (pt->IsCodeObject()) { /* Compiled code. This is the second constant in the constant area. */ PolyWord *codePt = pt->ConstPtrForCode(); PolyWord mask = codePt[1]; // A real mask will be an integer. if (IS_INT(mask)) return SAVE(mask); else raise_exception_string(taskData, EXC_Fail, "Invalid mask"); } else raise_exception_string(taskData, EXC_Fail, "Not a code pointer"); } } case 104: return Make_arbitrary_precision(taskData, POLY_version_number); case 105: /* Get the name of the function. */ { PolyObject *pt = DEREFWORDHANDLE(args); if (gMem.IsIOPointer(pt)) { /* IO area. */ int i; for (i=0; i < POLY_SYS_vecsize; i++) { if (pt == (PolyObject*)IoEntry(i)) { char buff[8]; sprintf(buff, "RTS%d", i); return SAVE(C_string_to_Poly(taskData, buff)); } } raise_syscall(taskData, "Io pointer not found", 0); } else if (pt->IsCodeObject()) /* Should now be a code object. */ { /* Compiled code. This is the first constant in the constant area. */ PolyWord *codePt = pt->ConstPtrForCode(); PolyWord name = codePt[0]; /* May be zero indicating an anonymous segment - return null string. */ if (name == PolyWord::FromUnsigned(0)) return SAVE(C_string_to_Poly(taskData, "")); else return SAVE(name); } else raise_syscall(taskData, "Not a code pointer", 0); } default: { char msg[100]; sprintf(msg, "Unknown poly-specific function: %d", c); raise_exception_string(taskData, EXC_Fail, msg); return 0; } } }