You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by va...@apache.org on 2007/01/26 10:05:35 UTC

svn commit: r500190 - in /harmony/enhanced/drlvm/trunk: src/test/microbenchmark/harmony-2815/ vm/vmcore/include/ vm/vmcore/src/class_support/ vm/vmcore/src/kernel_classes/javasrc/java/security/ vm/vmcore/src/kernel_classes/native/

Author: varlax
Date: Fri Jan 26 01:05:34 2007
New Revision: 500190

URL: http://svn.apache.org/viewvc?view=rev&rev=500190
Log:
Fixed HARMONY-2815 [drlvm][performance] very slow security checks with quadratical dependence on number of stack frames
Tested on Win32, SUSE9@ia32 SUSE9@x64

Added:
    harmony/enhanced/drlvm/trunk/src/test/microbenchmark/harmony-2815/
    harmony/enhanced/drlvm/trunk/src/test/microbenchmark/harmony-2815/SecurityPerfTest.java
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_security_AccessController.h   (with props)
Modified:
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/security/AccessController.java
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp

Added: harmony/enhanced/drlvm/trunk/src/test/microbenchmark/harmony-2815/SecurityPerfTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/src/test/microbenchmark/harmony-2815/SecurityPerfTest.java?view=auto&rev=500190
==============================================================================
--- harmony/enhanced/drlvm/trunk/src/test/microbenchmark/harmony-2815/SecurityPerfTest.java (added)
+++ harmony/enhanced/drlvm/trunk/src/test/microbenchmark/harmony-2815/SecurityPerfTest.java Fri Jan 26 01:05:34 2007
@@ -0,0 +1,41 @@
+import java.security.Security;
+
+/**
+recursive call of run() checks for security permissions
+
+to run it, issue the recursion depth list via command-line parameters like this:
+java SecurityPerfTest 50 100 150 300 350 400 450 500 
+
+on Jrockit/ia32 the time spent for each step depends linearly on the number of
+iterations:
+50 107 // this line should be ignored
+100 1
+150 1
+300 3
+350 5
+400 6
+450 7
+500 9
+*/
+public class SecurityPerfTest {
+    public static void main(String[] args) {
+        System.setSecurityManager(new SecurityManager());
+        for (int i = 0; i < args.length; i++ ) {
+            long start_time = System.currentTimeMillis();
+            int amount = Integer.parseInt(args[i]);
+            run(amount);
+            long total_time = System.currentTimeMillis() - start_time;
+            System.out.println(amount + " " + total_time);
+        }
+   }
+
+public static void run(int count) {
+       if ( count < 0 ) {
+           return;
+       }
+
+//System.out.println("Runner: " + count);
+       System.getProperty("os.name");
+       run(count - 1);
+   }
+}

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?view=diff&rev=500190&r1=500189&r2=500190
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Fri Jan 26 01:05:34 2007
@@ -196,6 +196,9 @@
     Class* java_lang_OutOfMemoryError_Class;
     Class* java_lang_ThreadDeath_Class;
 
+    Class* java_security_ProtectionDomain_Class;
+    unsigned Class_domain_field_offset;
+
     ObjectHandle java_lang_Object;
     ObjectHandle java_lang_OutOfMemoryError;
     ObjectHandle java_lang_ThreadDeath;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp?view=diff&rev=500190&r1=500189&r2=500190
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Environment.cpp Fri Jan 26 01:05:34 2007
@@ -194,6 +194,9 @@
 
     JavaLangString_VTable = NULL;
 
+    java_security_ProtectionDomain_Class = NULL;
+    Class_domain_field_offset = 0;
+
     vm_class_offset = 0;
     vm_state = VM_INITIALIZING;
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/security/AccessController.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/security/AccessController.java?view=diff&rev=500190&r1=500189&r2=500190
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/security/AccessController.java (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/javasrc/java/security/AccessController.java Fri Jan 26 01:05:34 2007
@@ -14,10 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
-* @author Alexander V. Astapchuk
-* @version $Revision: 1.1.2.2.4.3 $
-*/
 
 package java.security;
 
@@ -26,8 +22,6 @@
 
 import org.apache.harmony.fortress.security.SecurityUtils;
 
-import org.apache.harmony.vm.VMStack;
-
 /**
  * @com.intel.drl.spec_ref
  */
@@ -197,50 +191,27 @@
             throw new NullPointerException("permission can not be null");
         }
 
-        Class[] trace = VMStack.getClasses(-1, true);
-
-        // do a quick check: always trust to doSecure_XXX calls from AC
-        for (int i = 0; i < trace.length; i++) {
-            if (DoSecure.class == trace[i]) {
-                return;
-            }
-        }
-        buildContext(trace).checkPermission(perm);
+        getContext().checkPermission(perm);
     }
 
     /**
-     * @com.intel.drl.spec_ref 
+     * Returns array of ProtectionDomains of classes residing 
+     * on the stack of the current thread, up to the caller of nearest
+     * privileged frame; reflection frames are skipped. 
+     * The returned array is never null and never contains null elements, 
+     * meaning that bootstrap classes are effectively ignored.
+     * @see org.apache.harmony.vm.VMStack.getClasses()
      */
-    public static AccessControlContext getContext() {
-        Class[] trace = VMStack.getClasses(-1, true);
-        return buildContext(trace);
-    };
-
+    private static native ProtectionDomain[] getStackDomains();
+    
     /**
-     * Builds AccessControllerContext from the passed stack trace, loading
-     * inherited context if neccessary. It's taken out as a separate method as
-     * both the getContext() and checkPermission() query the stack trace and I
-     * want to avoid additional unnecessary trip to VM.
-     * 
-     * @param trace
-     *            stack trace
-     * @return current AccessControllerContext basing on the <code>trace</code>
-     *         passed
+     * @com.intel.drl.spec_ref 
      */
-    private static AccessControlContext buildContext(Class[] trace) {
-
-        ArrayList<ProtectionDomain> a = new ArrayList<ProtectionDomain>();
-        for (int i = 0; i < trace.length; i++) {
-            ProtectionDomain pd = DoSecure.doSecure_getProtectionDomain(trace[i]);
-            
-            if (!a.contains(pd)) { // remove dups
-                a.add(pd);
-            }
-        }
-
-        ProtectionDomain[] stack = new ProtectionDomain[a.size()];
-        a.toArray(stack);
+    public static AccessControlContext getContext() {
 
+        // duplicates (if any) will be removed in ACC constructor
+        ProtectionDomain[] stack = getStackDomains();
+        
         Thread currThread = Thread.currentThread();
         if (currThread == null || contexts == null) {
             // Big boo time. No need to check anything ? 
@@ -265,41 +236,18 @@
 
         if (that != null && that.combiner != null) {
             ProtectionDomain[] assigned = null;
-            if (that.context != null) {
-                if (that.context.length == 0) {
-                    assigned = new ProtectionDomain[0];
-                } else {
+            if (that.context != null && that.context.length != 0) {
                     assigned = new ProtectionDomain[that.context.length];
                     System.arraycopy(that.context, 0, assigned, 0,
                             assigned.length);
-                }
             }
             ProtectionDomain[] allpds = that.combiner.combine(stack, assigned);
+            if (allpds == null) {
+                allpds = new ProtectionDomain[0];
+            }
             return new AccessControlContext(allpds, that.combiner);
         }
 
         return new AccessControlContext(stack, that);
-    }
-
-    private static final class DoSecure {
-        /**
-         * The doSecure_XXX method acts like a doPrivileged() does.<br>
-         * The exception is a special processing in the checkPermission() method. 
-         * doPrivileged() calls always go through the full check with the stack inspection.<br>
-         * doSecure_XXX() calls are always trusted as they always get called from AccessController 
-         * only, and this is quick-checked in the checkPermission() without inspecting the
-         * full call chain.<br>
-         * There are currently only one doSecure_XXX method - doSecure_getProtectionDomain(Class klass)<br>
-         * The reasons why this is done via this specific and not general (like 'doSecure(PrivilegedAction)')
-         * method are:<br>
-         * 1. I only need this 1 action and I don't need anything more general<br>
-         * 2. I do not want to create additional Class-es/Object-s on each checkPermssion/getContext call.
-         * 
-         * @param klass
-         * @return klass.getProtectionDomain()
-         */
-        private static ProtectionDomain doSecure_getProtectionDomain(Class<?> klass) {
-            return klass.getProtectionDomain();
-        }
     }
 }

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_security_AccessController.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_security_AccessController.h?view=auto&rev=500190
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_security_AccessController.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_security_AccessController.h Fri Jan 26 01:05:34 2007
@@ -0,0 +1,48 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/*
+ * THE FILE HAS BEEN AUTOGENERATED BY INTEL IJH TOOL.
+ * Please be aware that all changes made to this file manually
+ * will be overwritten by the tool if it runs again.
+ */
+
+#include <jni.h>
+
+
+/* Header for class java.security.AccessController */
+
+#ifndef _JAVA_SECURITY_ACCESSCONTROLLER_H
+#define _JAVA_SECURITY_ACCESSCONTROLLER_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * Method: java.security.AccessController.getStackDomains()[Ljava/security/ProtectionDomain;
+ */
+JNIEXPORT jobjectArray JNICALL
+Java_java_security_AccessController_getStackDomains(JNIEnv *, jclass); 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _JAVA_SECURITY_ACCESSCONTROLLER_H */
+

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/java_security_AccessController.h
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp?view=diff&rev=500190&r1=500189&r2=500190
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/kernel_classes/native/org_apache_harmony_vm_VMStack.cpp Fri Jan 26 01:05:34 2007
@@ -14,10 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/** 
- * @author Euguene Ostrovsky
- * @version $Revision: 1.1.6.6 $
- */  
 
 /**
  * @file org_apache_harmony_vm_VMStack.cpp
@@ -30,6 +26,8 @@
 #define LOG_DOMAIN "kernel.stack"
 #include "cxxlog.h"
 
+#include <vector>
+
 #include "open/jthread.h"
 #include "stack_trace.h"
 #include "jni_direct.h"
@@ -42,6 +40,7 @@
 #include "java_lang_VMClassRegistry.h"
 
 #include "org_apache_harmony_vm_VMStack.h"
+#include "java_security_AccessController.h"
 
 /*
  * Class:     org_apache_harmony_vm_VMStack
@@ -173,6 +172,75 @@
     assert(hythread_is_suspend_enabled());
     return arr;
 }
+
+/*
+* Method: java.security.AccessController.getStackDomains()[Ljava/security/ProtectionDomain;
+*/
+JNIEXPORT jobjectArray JNICALL
+Java_java_security_AccessController_getStackDomains(JNIEnv *jenv, jclass UNREF)
+{
+    assert(hythread_is_suspend_enabled());
+    unsigned size;
+    StackTraceFrame* frames;
+    st_get_trace(get_thread_ptr(), &size, &frames);
+
+    std::vector<jobject> domains = std::vector<jobject>();
+    Global_Env* genv = jni_get_vm_env(jenv);
+
+    unsigned domain_field_offset = genv->Class_domain_field_offset;
+
+    if (domain_field_offset == 0) {
+        // initialize preloaded values
+        genv->java_security_ProtectionDomain_Class = genv->LoadCoreClass("java/security/ProtectionDomain");
+        String* name = genv->string_pool.lookup("domain");
+        String* desc = genv->string_pool.lookup("Ljava/security/ProtectionDomain;");
+        Field* f = genv->JavaLangClass_Class->lookup_field(name, desc);
+        assert(f);
+        domain_field_offset = genv->Class_domain_field_offset = f->get_offset();
+    }
+
+    // The caller of the caller of this method is stored as a first element of the array.
+    // For details look at the org/apache/harmony/vm/VMStack.java file. Thus skipping 2 frames.
+    unsigned s = 2;
+    for (; s < size; s++) {
+        Method_Handle method = frames[s].method;
+
+        if (isReflectionFrame(method, genv))
+            continue;
+
+        if (isPrivilegedFrame(method, genv)) {
+            // find nearest non-reflection frame and finish looping
+            while (++s < size && isReflectionFrame(frames[s].method, genv));
+            TRACE("Privileged frame at " << s << " of " << size);
+            size = s;
+            method = frames[s].method;
+        }
+
+        jobject pd = GetObjectFieldOffset(jenv, 
+            struct_Class_to_java_lang_Class_Handle(method->get_class()), domain_field_offset);
+        if (pd) {
+            domains.push_back(pd);
+        }
+    }
+
+    jclass pdc = struct_Class_to_java_lang_Class_Handle(genv->java_security_ProtectionDomain_Class);
+    assert(pdc);
+    size = domains.size();
+    TRACE("Domains on stack: " << size);
+    // create & fill  java array
+    jarray arr = jenv->NewObjectArray(size, pdc, NULL);
+    if (arr != NULL) {
+        for (s = 0; s < size; s++) {
+            jenv->SetObjectArrayElement(arr, s, domains[s]);
+        }
+    } else {
+        // OutOfMemoryError
+        assert(exn_raised());
+    }
+    core_free(frames);
+    return arr;
+}
+
 
 /*
  * Class:     org_apache_harmony_vm_VMStack