001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.specialization;
014    
015    import org.jikesrvm.classloader.NormalMethod;
016    import org.jikesrvm.compilers.common.CompiledMethod;
017    import org.jikesrvm.compilers.opt.OptOptions;
018    import org.jikesrvm.compilers.opt.driver.CompilationPlan;
019    import org.jikesrvm.compilers.opt.driver.OptimizationPlanElement;
020    import org.jikesrvm.compilers.opt.driver.OptimizationPlanner;
021    import org.jikesrvm.compilers.opt.driver.OptimizingCompiler;
022    
023    /**
024     * This class represents a specialization context meaning
025     * "the invokee is thread local".
026     * We use this context to remove unnecessary synchronizations.
027     */
028    public final class InvokeeThreadLocalContext implements SpecializationContext {
029    
030      public InvokeeThreadLocalContext() {
031      }
032    
033      /**
034       * Find or create a specialized method in this context.
035       * @param source
036       */
037      @Override
038      public SpecializedMethod findOrCreateSpecializedVersion(NormalMethod source) {
039        // first check if the specialization database contains
040        // a specialized version from this context.
041        java.util.Iterator<SpecializedMethod> versions = SpecializationDatabase.getSpecialVersions(source);
042        if (versions != null) {
043          while (versions.hasNext()) {
044            SpecializedMethod spMethod = versions.next();
045            SpecializationContext context = spMethod.getSpecializationContext();
046            if (context == this) {
047              return spMethod;
048            }
049          }
050        }
051        // none found. create one.
052        SpecializedMethod spMethod = createSpecializedMethod(source);
053        // register it in the database.
054        SpecializationDatabase.registerSpecialVersion(spMethod);
055        // return it.
056        return spMethod;
057      }
058    
059      /**
060       * Create specialized method in this context.
061       * @param method
062       */
063      private SpecializedMethod createSpecializedMethod(NormalMethod method) {
064        return (new SpecializedMethod(method, this));
065      }
066    
067      /**
068       * Generate code to specialize a method in this context. Namely, invoke
069       * the opt compiler with the INVOKEE_THREAD_LOCAL option.
070       * @param source
071       */
072      @Override
073      public CompiledMethod specialCompile(NormalMethod source) {
074        CompilationPlan plan = new CompilationPlan(source, optimizationPlan, null, options);
075        return OptimizingCompiler.compile(plan);
076      }
077    
078      /**
079       * The default optimization options, with the INVOKEE_THREAD_LOCAL flag
080       * set true.
081       */
082      private static OptOptions options;
083      /**
084       * The default optimization plan.
085       */
086      private static OptimizationPlanElement[] optimizationPlan;
087    
088      /**
089       * Initialize static members.
090       */
091      public static void init() {
092        options = new OptOptions();
093        optimizationPlan = OptimizationPlanner.createOptimizationPlan(options);
094        // all objects in the specialized method will be thread local
095        options.ESCAPE_INVOKEE_THREAD_LOCAL = true;
096      }
097    }
098