FindProperty.java revision 953:221a84ef44c0
1/* 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package jdk.nashorn.internal.runtime; 27 28import static jdk.nashorn.internal.lookup.Lookup.MH; 29import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; 30 31import java.lang.invoke.MethodHandle; 32import jdk.nashorn.internal.codegen.ObjectClassGenerator; 33 34/** 35 * This class represents the result from a find property search. 36 */ 37public final class FindProperty { 38 /** Object where search began. */ 39 private final ScriptObject self; 40 41 /** Object where search finish. */ 42 private final ScriptObject prototype; 43 44 /** Found property. */ 45 private final Property property; 46 47 /** 48 * Constructor 49 * 50 * @param self script object where search began 51 * @param prototype prototype where property was found, may be {@code self} if not inherited 52 * @param property property that was search result 53 */ 54 public FindProperty(final ScriptObject self, final ScriptObject prototype, final Property property) { 55 this.self = self; 56 this.prototype = prototype; 57 this.property = property; 58 } 59 60 /** 61 * Ask for a getter that returns the given type. The type has nothing to do with the 62 * internal representation of the property. It may be an Object (boxing primitives) or 63 * a primitive (primitive fields with -Dnashorn.fields.dual=true) 64 * @see ObjectClassGenerator 65 * 66 * @param type type of getter, e.g. int.class if we want a function with {@code get()I} signature 67 * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic 68 * @return method handle for the getter 69 */ 70 public MethodHandle getGetter(final Class<?> type, final int programPoint) { 71 final MethodHandle getter; 72 if (isValid(programPoint)) { 73 getter = property.getOptimisticGetter(type, programPoint); 74 } else { 75 getter = property.getGetter(type); 76 } 77 return getGetterInner(getter); 78 } 79 80 private MethodHandle getGetterInner(final MethodHandle getter) { 81 if (property instanceof UserAccessorProperty) { 82 final UserAccessorProperty uc = (UserAccessorProperty)property; 83 final ScriptObject owner = getOwner(); 84 final ScriptObject container = (owner != null) ? owner : self; 85 return MH.insertArguments(getter, 0, uc.getAccessors(container)); 86 } 87 return getter; 88 89 } 90 91 /** 92 * Ask for a setter that sets the given type. The type has nothing to do with the 93 * internal representation of the property. It may be an Object (boxing primitives) or 94 * a primitive (primitive fields with -Dnashorn.fields.dual=true) 95 * @see ObjectClassGenerator 96 * 97 * @param type type of setter, e.g. int.class if we want a function with {@code set(I)V} signature 98 * @param strict are we in strict mode 99 * 100 * @return method handle for the getter 101 */ 102 public MethodHandle getSetter(final Class<?> type, final boolean strict) { 103 final MethodHandle setter = property.getSetter(type, getOwner().getMap()); 104 if (property instanceof UserAccessorProperty) { 105 final UserAccessorProperty uc = (UserAccessorProperty)property; 106 final ScriptObject owner = getOwner(); 107 final ScriptObject container = (owner != null) ? owner : self; 108 return MH.insertArguments(setter, 0, uc.getAccessors(container), strict ? property.getKey() : null); 109 } 110 111 return setter; 112 } 113 114 /** 115 * Return the {@code ScriptObject} owning of the property: this means the prototype. 116 * @return owner of property 117 */ 118 public ScriptObject getOwner() { 119 return prototype; 120 } 121 122 /** 123 * Return the appropriate receiver for a getter. 124 * @return appropriate receiver 125 */ 126 public ScriptObject getGetterReceiver() { 127 return property != null && property.hasGetterFunction(prototype) ? self : prototype; 128 } 129 130 /** 131 * Return the appropriate receiver for a setter. 132 * @return appropriate receiver 133 */ 134 public ScriptObject getSetterReceiver() { 135 return property != null && property.hasSetterFunction(prototype) ? self : prototype; 136 } 137 138 /** 139 * Return the property that was found 140 * @return property 141 */ 142 public Property getProperty() { 143 return property; 144 } 145 146 /** 147 * Check if the property found was inherited, i.e. not directly in the self 148 * @return true if inherited property 149 */ 150 public boolean isInherited() { 151 return self != prototype; 152 } 153 154 /** 155 * Check if the property found was NOT inherited, i.e. defined in the script 156 * object, rather than in the prototype 157 * @return true if not inherited 158 */ 159 public boolean isSelf() { 160 return self == prototype; 161 } 162 163 /** 164 * Check if the property is in the scope 165 * @return true if on scope 166 */ 167 public boolean isScope() { 168 return prototype.isScope(); 169 } 170 171 /** 172 * Get the property value from self as object. 173 * @return the property value 174 */ 175 public int getIntValue() { 176 return property.getIntValue(getGetterReceiver(), getOwner()); 177 } 178 /** 179 * Get the property value from self as object. 180 * @return the property value 181 */ 182 public long getLongValue() { 183 return property.getLongValue(getGetterReceiver(), getOwner()); 184 } 185 /** 186 * Get the property value from self as object. 187 * @return the property value 188 */ 189 public double getDoubleValue() { 190 return property.getDoubleValue(getGetterReceiver(), getOwner()); 191 } 192 /** 193 * Get the property value from self as object. 194 * @return the property value 195 */ 196 public Object getObjectValue() { 197 return property.getObjectValue(getGetterReceiver(), getOwner()); 198 } 199 200 /** 201 * Set the property value in self. 202 * 203 * @param value the new value 204 * @param strict strict flag 205 */ 206 public void setValue(final int value, final boolean strict) { 207 property.setValue(getSetterReceiver(), getOwner(), value, strict); 208 } 209 210 /** 211 * Set the property value in self. 212 * 213 * @param value the new value 214 * @param strict strict flag 215 */ 216 public void setValue(final long value, final boolean strict) { 217 property.setValue(getSetterReceiver(), getOwner(), value, strict); 218 } 219 220 /** 221 * Set the property value in self. 222 * 223 * @param value the new value 224 * @param strict strict flag 225 */ 226 public void setValue(final double value, final boolean strict) { 227 property.setValue(getSetterReceiver(), getOwner(), value, strict); 228 } 229 230 /** 231 * Set the property value in self. 232 * 233 * @param value the new value 234 * @param strict strict flag 235 */ 236 public void setValue(final Object value, final boolean strict) { 237 property.setValue(getSetterReceiver(), getOwner(), value, strict); 238 } 239 240 /** 241 * Get the number of objects in the prototype chain between the {@code self} and the 242 * {@code owner} objects. 243 * @return the prototype chain length 244 */ 245 int getProtoChainLength() { 246 assert self != null; 247 int length = 0; 248 for (ScriptObject obj = self; obj != prototype; obj = obj.getProto()) { 249 assert !(obj instanceof WithObject); 250 ++length; 251 } 252 return length; 253 } 254 255 @Override 256 public String toString() { 257 return "[FindProperty: " + property.getKey() + ']'; 258 } 259 260} 261 262