/*
* Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Business Objects nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* LECCMachineConfiguration.java
* Created: Sep 10, 2003 3:02:02 PM
* By: RCypher
*/
package org.openquark.cal.internal.runtime.lecc;
import org.openquark.cal.runtime.MachineConfiguration;
/**
* This class holds configuration information for code generation,
* as well as some information accessed by the runtime related to how
* the code was generated.
*
* Creation: Sep 10, 2003
* @author RCypher
*/
public final class LECCMachineConfiguration {
/**
* The name of the root package for generated classes.
*/
public static final String ROOT_PACKAGE = "org.openquark";
public static final String GEN_BYTECODE_PROP = "org.openquark.cal.machine.lecc.source";
public static final String STATIC_BYTECODE_RUNTIME_PROP = "org.openquark.cal.machine.lecc.static_runtime";
public static final String GEN_STATISTICS_PROP = "org.openquark.cal.machine.lecc.runtime_statistics";
public static final String GEN_CALLCOUNTS_PROP = "org.openquark.cal.machine.lecc.runtime_call_counts";
public static final String GEN_APPCOUNTS_PROP = "org.openquark.cal.machine.lecc.runtime_gen_app_counts";
public static final String NON_INTERRUPTIBLE_RUNTIME_PROP = "org.openquark.cal.machine.lecc.non_interruptible";
public static final String CONCURRENT_RUNTIME_PROP = "org.openquark.cal.machine.lecc.concurrent_runtime";
public static final String USE_LAZY_FOREIGN_ENTITY_LOADING_PROP = "org.openquark.cal.machine.lecc.strict_foreign_entity_loading";
public static final String CODE_GENERATION_STATS_PROP = "org.openquark.cal.machine.lecc.code_generation_stats";
public static final String DEBUG_INFO_PROP = "org.openquark.cal.machine.lecc.debug_info";
public static final String OUTPUT_DIR_PROP = "org.openquark.cal.machine.lecc.output_directory";
public static final String BYTECODE_SPACE_OPTIMIZATION_PROP = "org.openquark.cal.machine.lecc.bytecode_space_optimization";
public static final String SOURCE_CODE_SPACE_OPTIMIZATION_PROP = "org.openquark.cal.machine.lecc.source_code_space_optimization";
/** Version of code generation schemas.
* Changing this value will force all existing
* generated sources to be re-generated.
*/
public static final int CODEGEN_VERSION = 1612;
/** Whether to directly generate bytecode, or go to source first. */
private static final boolean GEN_BYTECODE = System.getProperty(GEN_BYTECODE_PROP) == null;
/**
* Flag affecting lecc runtime if GEN_BYTECODE is true.
* If true, bytecode will be generated when asked for by the classloader.
* If false, it will be generated statically to disk, and loaded from there by the classloader.
*/
private static final boolean STATIC_BYTECODE_RUNTIME = System.getProperty(STATIC_BYTECODE_RUNTIME_PROP) != null;
/** Turns on generation of reduction, method call, and data instance counting.
* NOTE: Changing this flag's value will result in forcing code regeneration in a static runtime.
*/
private static final boolean GEN_STATISTICS = System.getProperty (GEN_STATISTICS_PROP) != null;
/** Turns on generation of call counting.
* NOTE: Changing this flag's value will result in forcing code regeneration in a static runtime.
*/
private static final boolean GEN_CALLCOUNTS = System.getProperty (GEN_CALLCOUNTS_PROP) != null;
/** Turns on generation of application node counting.
* Counts number of RTApplication nodes and number of RTFullApp nodes.
*/
private static final boolean GEN_APPCOUNTS = System.getProperty (GEN_APPCOUNTS_PROP) != null;
/**
* If this is set to true, the code generated will be capable of function tracing.
* One can then dynamically turn on and off function tracing via calls to Debug.setTracingEnabled.
* Also the code generated will be capable of halting on breakpoints.
*
* Note that when generating debug code, we set GEN_DIRECT_PRIMOP_CALLS to false so that
* calls to primitive operators and foreign functions show up in the traces as well.
* Also we set PASS_EXEC_CONTEXT_TO_DATA_CONSTRUCTORS to true so that data constructors
* can trace/halt.
*/
private static final boolean GEN_DEBUG_CAPABLE = System.getProperty(MachineConfiguration.MACHINE_DEBUG_CAPABLE_PROP) != null;
/**
* If true, the system does not check the quit flag in the execution context to check for external interruptions of execution.
* This is mainly set for benchmarking comparison in situations where we are comparing against another non-interruptible program
* and don't want to occur the extra (small) overhead of checking this flag.
*/
private static final boolean NON_INTERRUPTIBLE_RUNTIME = !GEN_DEBUG_CAPABLE && System.getProperty(NON_INTERRUPTIBLE_RUNTIME_PROP) != null;
/**
* If true, the lecc run-time supports concurrent reduction of CAL programs on a single execution context.
* Note that the lecc runtime is thread-safe even when this flag is false in the sense that concurrent evaluation CAL entry points
* on separate execution contexts that do not share graph is thread-safe (assuming that referenced foreign entities that are
* shared are thread-safe).
* At the moment, this support is limited to being able to concurrently evaluate program graphs that have no shared references
* other than evaluated CAFs.
*/
private static final boolean CONCURRENT_RUNTIME = System.getProperty(CONCURRENT_RUNTIME_PROP) != null;
/**
* If this is true the generated code will pass the execution context to the constructors of the
* data constructor classes.
*/
private static final boolean PASS_EXEC_CONTEXT_TO_DATA_CONSTRUCTORS = GEN_CALLCOUNTS || GEN_STATISTICS || GEN_DEBUG_CAPABLE;
/**
* If true, calls to primitive operators will be made directly whenever possible. Primitive operators
* are those primitive functions defined in the PrimOp class, as well as foreign function calls. Direct
* calls to them are encoded as primitive jvm operations (for example, for int addition), or as direct
* calls to a foreign function.
*
* If false, calls to primitive operators are made via their corresponding fUnboxed method of their
* RTValue derived class.
*
* In general, calling primitive functions directly is good for performance. However, we may want to call
* indirectly so that calls to such functions can be traced, and so that more precise error information
* can be given in the case of an exception occurring while invoking the primitive function.
*/
private static final boolean GEN_DIRECT_PRIMOP_CALLS = !GEN_DEBUG_CAPABLE;
/**
* If true, then foreign entities corresponding to foreign types and foreign functions will be loaded lazily.
* Otherwise, they are resolved and loaded eagerly during compilation/deserialization.
*/
private static final boolean USE_LAZY_FOREIGN_ENTITY_LOADING = System.getProperty(USE_LAZY_FOREIGN_ENTITY_LOADING_PROP) == null;
/**
* If true, the bytecode compiler rewrites its output to insert null assignments, which optimizes for
* runtime memory usage.
* Otherwise, no rewriting is done.
*/
private static final boolean BYTECODE_SPACE_OPTIMIZATION = System.getProperty(BYTECODE_SPACE_OPTIMIZATION_PROP) != null;
/**
* If true, the java generator uses calls to RTValue.lastRef to perform null assignments of local variables
* at the point of last reference, which optimizes for runtime memory usage.
* Otherwise, local variables are not set to null .
*/
private static final boolean SOURCE_CODE_SPACE_OPTIMIZATION = System.getProperty(SOURCE_CODE_SPACE_OPTIMIZATION_PROP) != null;
/**
* The different lazy body functions for the supercombinators (f, fLn) simply refer to the strict body fSn.
*/
public static final boolean CONSOLIDATE_FUNCTION_BODIES = true;
/**
* Generate and call function bodies which directly return an unboxed value.
*/
public static final boolean DIRECT_UNBOXED_RETURNS = true;
/**
* This flag turns on the optimization of fully saturated lazy applications by
* using a strict application node where possible.
*/
public static final boolean OPTIMIZE_LAZY_APP_NODES = true;
/**
* This flag turns on optimized representation of dictionary function applications.
* Currently the dictionary functions optimized are those for the type classes Eq, Ord,
* and Num.
* i.e.: equals, notEquals, lessThan, lessThanEquals, greaterThan, greaterThanEquals,
* fromInteger, toDouble, negate, add, subtract, multiply, divide.
*/
public static final boolean OPTIMIZE_TYPECLASS_DICTS = true;
/**
* This flag indicates that operations specified in the 'optimizedLazyOps' map
* should be compiled strictly even in a lazy context if all the arguments
* are known to be already evaluated.
*/
public static final boolean OPTIMIZE_LAZY_SUPERCOMBINATORS = true;
/**
* This flag allows elimination of switches on data types that only have one
* data constructor.
*/
public static final boolean OPTIMIZE_SINGLE_DC_CASES = true;
/**
* This flag optimizes cases on two DC data types by generating an if-then-else
*/
static final boolean OPTIMIZE_TWO_DC_CASES = false;
/**
* This flag turns off the use of strictness annotations on data constructor and function arguments.
*/
public static final boolean IGNORE_STRICTNESS_ANNOTATIONS = false;
/**
* Turns on optimization of application chains where the LHS cannot be determined at compile time.
*/
public static final boolean OPTIMIZE_GENERAL_APP_CHAINS = true;
/**
* Treat the data constructors in an 'enumeration' data type as ints.
*/
public static final boolean TREAT_ENUMS_AS_INTS = true;
/**
* The number of arguments for which a specialized application node
* exists.
* The runtime will contain specialized application nodes for fully and
* partially saturated application for functions of up to and including
* this arity.
* Also when generating classes we will generate special purpose application
* nodes for handling strict/unboxed values for functions with up to and
* including this arity.
*/
public static final int OPTIMIZED_APP_CHAIN_LENGTH = 15;
/**
* Flag indicating that generated code should contain additional
* functionality to test correctness of let variable code generation.
* This flag is only for internal debugging use and should be used
* with caution. If code executes successfully with this flag
* set to true it is guaranteed that let variables are not being
* executed multiple times for a single reduction of a function.
* However if an error is reported with this flag turned on it
* doesn't necessarily mean that let variable evaluation is
* incorrect. The error should be taken as an indication to double-
* check the corresponding generated code to determine if a problem
* truly exists as turning this flag on can incorrectly report a double
* evaluation of a letvar in situations where reduction of a function
* application will cause reduction of a previously created application
* of the same function.
*/
public static final boolean SANITY_CHECK_LET_VARS = false;
private LECCMachineConfiguration() {}
/**
* @return true if the current configuration directly generates bytecode.
*/
public static boolean generateBytecode () { return GEN_BYTECODE;}
/**
* @return true if generation of statistics is turned on.
*/
public static boolean generateStatistics() {return GEN_STATISTICS;}
/**
* @return true if the generation of call counts is turned on.
*/
public static boolean generateCallCounts() {return GEN_CALLCOUNTS;}
/**
* @return true if the generation of application counts is turned on.
*/
public static boolean generateAppCounts(){return GEN_APPCOUNTS;}
/**
* @return true if debug mode is turned on.
*/
public static boolean generateDebugCode() {return GEN_DEBUG_CAPABLE;}
/**
* @return true if the runtime is in non-interruptible mode.
*/
public static final boolean nonInterruptibleRuntime() {return NON_INTERRUPTIBLE_RUNTIME;}
/**
* @return true if the execution context should be passed to data constructors.
*/
public static final boolean passExecContextToDataConstructors() {return PASS_EXEC_CONTEXT_TO_DATA_CONSTRUCTORS;}
/**
* @return true if direct calls to primitive operators can be in-lined.
*/
public static final boolean generateDirectPrimOpCalls() {return GEN_DIRECT_PRIMOP_CALLS;}
/**
* @return whether config flags specify that a lecc runtime would run in the mode where the runtime is static.
* ie. bytecode is retrieved from disk.
*/
public static final boolean isLeccRuntimeStatic() {
return !GEN_BYTECODE || STATIC_BYTECODE_RUNTIME;
}
/**
* @return whether foreign entities corresponding to foreign types and foreign functions will be loaded lazily.
*/
public static boolean useLazyForeignEntityLoading() {
return USE_LAZY_FOREIGN_ENTITY_LOADING;
}
/**
* @return whether the bytecode compiler should rewrite its output to optimize for runtime memory usage.
*/
public static boolean bytecodeSpaceOptimization() {
return BYTECODE_SPACE_OPTIMIZATION;
}
/**
* @return whether the java generator should use RTValue.lastRef() to null out local variables
* at the point of final reference.
*/
public static boolean sourcecodeSpaceOptimization() {
return SOURCE_CODE_SPACE_OPTIMIZATION;
}
/**
* If true, the lecc run-time supports concurrent reduction of CAL programs on a single execution context.
* Note that the lecc runtime is thread-safe even when this flag is false in the sense that concurrent evaluation CAL entry points
* on separate execution contexts that do not share graph is thread-safe (assuming that referenced foreign entities that are
* shared are thread-safe).
*
* <p>
* When this flag is true, the lecc run-time supports concurrent threads doing CAL evaluation on a single execution context.
* This is accomplished in 3 ways:
* <ol>
* <li> access to CAFs is synchronized (this holds true even without this flag on)
* <li> The rootNode, held by the execution context, is held in thread local storage
* <li> RTValue.evaluate and reduce methods are synchronized in RTResultFunction subclasses.
* </ol>
*/
public static boolean concurrentRuntime() {
return CONCURRENT_RUNTIME;
}
}