OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of js_backend; | 5 part of js_backend; |
6 | 6 |
7 const JAVA_SCRIPT_CONSTANT_SYSTEM = const JavaScriptConstantSystem(); | 7 const JAVA_SCRIPT_CONSTANT_SYSTEM = const JavaScriptConstantSystem(); |
8 | 8 |
9 class JavaScriptBitNotOperation extends BitNotOperation { | 9 class JavaScriptBitNotOperation extends BitNotOperation { |
10 const JavaScriptBitNotOperation(); | 10 const JavaScriptBitNotOperation(); |
11 | 11 |
12 Constant fold(Constant constant) { | 12 ConstantValue fold(ConstantValue constant) { |
13 if (JAVA_SCRIPT_CONSTANT_SYSTEM.isInt(constant)) { | 13 if (JAVA_SCRIPT_CONSTANT_SYSTEM.isInt(constant)) { |
14 // In JavaScript we don't check for -0 and treat it as if it was zero. | 14 // In JavaScript we don't check for -0 and treat it as if it was zero. |
15 if (constant.isMinusZero) constant = DART_CONSTANT_SYSTEM.createInt(0); | 15 if (constant.isMinusZero) constant = DART_CONSTANT_SYSTEM.createInt(0); |
16 IntConstant intConstant = constant; | 16 IntConstantValue intConstant = constant; |
17 // We convert the result of bit-operations to 32 bit unsigned integers. | 17 // We convert the result of bit-operations to 32 bit unsigned integers. |
18 return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(~intConstant.value); | 18 return |
| 19 JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(~intConstant.primitiveValue); |
19 } | 20 } |
20 return null; | 21 return null; |
21 } | 22 } |
22 } | 23 } |
23 | 24 |
24 /** | 25 /** |
25 * In JavaScript we truncate the result to an unsigned 32 bit integer. Also, -0 | 26 * In JavaScript we truncate the result to an unsigned 32 bit integer. Also, -0 |
26 * is treated as if it was the integer 0. | 27 * is treated as if it was the integer 0. |
27 */ | 28 */ |
28 class JavaScriptBinaryBitOperation implements BinaryOperation { | 29 class JavaScriptBinaryBitOperation implements BinaryOperation { |
29 final BinaryBitOperation dartBitOperation; | 30 final BinaryBitOperation dartBitOperation; |
30 | 31 |
31 const JavaScriptBinaryBitOperation(this.dartBitOperation); | 32 const JavaScriptBinaryBitOperation(this.dartBitOperation); |
32 | 33 |
33 String get name => dartBitOperation.name; | 34 String get name => dartBitOperation.name; |
34 | 35 |
35 Constant fold(Constant left, Constant right) { | 36 ConstantValue fold(ConstantValue left, ConstantValue right) { |
36 // In JavaScript we don't check for -0 and treat it as if it was zero. | 37 // In JavaScript we don't check for -0 and treat it as if it was zero. |
37 if (left.isMinusZero) left = DART_CONSTANT_SYSTEM.createInt(0); | 38 if (left.isMinusZero) left = DART_CONSTANT_SYSTEM.createInt(0); |
38 if (right.isMinusZero) right = DART_CONSTANT_SYSTEM.createInt(0); | 39 if (right.isMinusZero) right = DART_CONSTANT_SYSTEM.createInt(0); |
39 IntConstant result = dartBitOperation.fold(left, right); | 40 IntConstantValue result = dartBitOperation.fold(left, right); |
40 if (result != null) { | 41 if (result != null) { |
41 // We convert the result of bit-operations to 32 bit unsigned integers. | 42 // We convert the result of bit-operations to 32 bit unsigned integers. |
42 return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(result.value); | 43 return JAVA_SCRIPT_CONSTANT_SYSTEM.createInt32(result.primitiveValue); |
43 } | 44 } |
44 return result; | 45 return result; |
45 } | 46 } |
46 | 47 |
47 apply(left, right) => dartBitOperation.apply(left, right); | 48 apply(left, right) => dartBitOperation.apply(left, right); |
48 } | 49 } |
49 | 50 |
50 class JavaScriptShiftRightOperation extends JavaScriptBinaryBitOperation { | 51 class JavaScriptShiftRightOperation extends JavaScriptBinaryBitOperation { |
51 const JavaScriptShiftRightOperation() : super(const ShiftRightOperation()); | 52 const JavaScriptShiftRightOperation() : super(const ShiftRightOperation()); |
52 | 53 |
53 Constant fold(Constant left, Constant right) { | 54 ConstantValue fold(ConstantValue left, ConstantValue right) { |
54 // Truncate the input value to 32 bits if necessary. | 55 // Truncate the input value to 32 bits if necessary. |
55 if (left.isInt) { | 56 if (left.isInt) { |
56 IntConstant intConstant = left; | 57 IntConstantValue intConstant = left; |
57 int value = intConstant.value; | 58 int value = intConstant.primitiveValue; |
58 int truncatedValue = value & JAVA_SCRIPT_CONSTANT_SYSTEM.BITS32; | 59 int truncatedValue = value & JAVA_SCRIPT_CONSTANT_SYSTEM.BITS32; |
59 if (value < 0) { | 60 if (value < 0) { |
60 // Sign-extend if the input was negative. The current semantics don't | 61 // Sign-extend if the input was negative. The current semantics don't |
61 // make much sense, since we only look at bit 31. | 62 // make much sense, since we only look at bit 31. |
62 // TODO(floitsch): we should treat the input to right shifts as | 63 // TODO(floitsch): we should treat the input to right shifts as |
63 // unsigned. | 64 // unsigned. |
64 | 65 |
65 // A 32 bit complement-two value x can be computed by: | 66 // A 32 bit complement-two value x can be computed by: |
66 // x_u - 2^32 (where x_u is its unsigned representation). | 67 // x_u - 2^32 (where x_u is its unsigned representation). |
67 // Example: 0xFFFFFFFF - 0x100000000 => -1. | 68 // Example: 0xFFFFFFFF - 0x100000000 => -1. |
(...skipping 10 matching lines...) Expand all Loading... |
78 } | 79 } |
79 } | 80 } |
80 | 81 |
81 class JavaScriptNegateOperation implements UnaryOperation { | 82 class JavaScriptNegateOperation implements UnaryOperation { |
82 final NegateOperation dartNegateOperation = const NegateOperation(); | 83 final NegateOperation dartNegateOperation = const NegateOperation(); |
83 | 84 |
84 const JavaScriptNegateOperation(); | 85 const JavaScriptNegateOperation(); |
85 | 86 |
86 String get name => dartNegateOperation.name; | 87 String get name => dartNegateOperation.name; |
87 | 88 |
88 Constant fold(Constant constant) { | 89 ConstantValue fold(ConstantValue constant) { |
89 if (constant.isInt) { | 90 if (constant.isInt) { |
90 IntConstant intConstant = constant; | 91 IntConstantValue intConstant = constant; |
91 if (intConstant.value == 0) { | 92 if (intConstant.primitiveValue == 0) { |
92 return JAVA_SCRIPT_CONSTANT_SYSTEM.createDouble(-0.0); | 93 return JAVA_SCRIPT_CONSTANT_SYSTEM.createDouble(-0.0); |
93 } | 94 } |
94 } | 95 } |
95 return dartNegateOperation.fold(constant); | 96 return dartNegateOperation.fold(constant); |
96 } | 97 } |
97 } | 98 } |
98 | 99 |
99 class JavaScriptBinaryArithmeticOperation implements BinaryOperation { | 100 class JavaScriptBinaryArithmeticOperation implements BinaryOperation { |
100 final BinaryOperation dartArithmeticOperation; | 101 final BinaryOperation dartArithmeticOperation; |
101 | 102 |
102 const JavaScriptBinaryArithmeticOperation(this.dartArithmeticOperation); | 103 const JavaScriptBinaryArithmeticOperation(this.dartArithmeticOperation); |
103 | 104 |
104 String get name => dartArithmeticOperation.name; | 105 String get name => dartArithmeticOperation.name; |
105 | 106 |
106 Constant fold(Constant left, Constant right) { | 107 ConstantValue fold(ConstantValue left, ConstantValue right) { |
107 Constant result = dartArithmeticOperation.fold(left, right); | 108 ConstantValue result = dartArithmeticOperation.fold(left, right); |
108 if (result == null) return result; | 109 if (result == null) return result; |
109 return JAVA_SCRIPT_CONSTANT_SYSTEM.convertToJavaScriptConstant(result); | 110 return JAVA_SCRIPT_CONSTANT_SYSTEM.convertToJavaScriptConstant(result); |
110 } | 111 } |
111 | 112 |
112 apply(left, right) => dartArithmeticOperation.apply(left, right); | 113 apply(left, right) => dartArithmeticOperation.apply(left, right); |
113 } | 114 } |
114 | 115 |
115 class JavaScriptIdentityOperation implements BinaryOperation { | 116 class JavaScriptIdentityOperation implements BinaryOperation { |
116 final IdentityOperation dartIdentityOperation = const IdentityOperation(); | 117 final IdentityOperation dartIdentityOperation = const IdentityOperation(); |
117 | 118 |
118 const JavaScriptIdentityOperation(); | 119 const JavaScriptIdentityOperation(); |
119 | 120 |
120 String get name => dartIdentityOperation.name; | 121 String get name => dartIdentityOperation.name; |
121 | 122 |
122 BoolConstant fold(Constant left, Constant right) { | 123 BoolConstantValue fold(ConstantValue left, ConstantValue right) { |
123 BoolConstant result = dartIdentityOperation.fold(left, right); | 124 BoolConstantValue result = dartIdentityOperation.fold(left, right); |
124 if (result == null || result.value) return result; | 125 if (result == null || result.primitiveValue) return result; |
125 // In JavaScript -0.0 === 0 and all doubles are equal to their integer | 126 // In JavaScript -0.0 === 0 and all doubles are equal to their integer |
126 // values. Furthermore NaN !== NaN. | 127 // values. Furthermore NaN !== NaN. |
127 if (left.isNum && right.isNum) { | 128 if (left.isNum && right.isNum) { |
128 NumConstant leftNum = left; | 129 NumConstantValue leftNum = left; |
129 NumConstant rightNum = right; | 130 NumConstantValue rightNum = right; |
130 double leftDouble = leftNum.value.toDouble(); | 131 double leftDouble = leftNum.primitiveValue.toDouble(); |
131 double rightDouble = rightNum.value.toDouble(); | 132 double rightDouble = rightNum.primitiveValue.toDouble(); |
132 return new BoolConstant(leftDouble == rightDouble); | 133 return new BoolConstantValue(leftDouble == rightDouble); |
133 } | 134 } |
134 return result; | 135 return result; |
135 } | 136 } |
136 | 137 |
137 apply(left, right) => identical(left, right); | 138 apply(left, right) => identical(left, right); |
138 } | 139 } |
139 | 140 |
140 /** | 141 /** |
141 * Constant system following the semantics for Dart code that has been | 142 * Constant system following the semantics for Dart code that has been |
142 * compiled to JavaScript. | 143 * compiled to JavaScript. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 179 |
179 /** | 180 /** |
180 * Returns true if [value] will turn into NaN or infinity | 181 * Returns true if [value] will turn into NaN or infinity |
181 * at runtime. | 182 * at runtime. |
182 */ | 183 */ |
183 bool integerBecomesNanOrInfinity(int value) { | 184 bool integerBecomesNanOrInfinity(int value) { |
184 double doubleValue = value.toDouble(); | 185 double doubleValue = value.toDouble(); |
185 return doubleValue.isNaN || doubleValue.isInfinite; | 186 return doubleValue.isNaN || doubleValue.isInfinite; |
186 } | 187 } |
187 | 188 |
188 NumConstant convertToJavaScriptConstant(NumConstant constant) { | 189 NumConstantValue convertToJavaScriptConstant(NumConstantValue constant) { |
189 if (constant.isInt) { | 190 if (constant.isInt) { |
190 IntConstant intConstant = constant; | 191 IntConstantValue intConstant = constant; |
191 int intValue = intConstant.value; | 192 int intValue = intConstant.primitiveValue; |
192 if (integerBecomesNanOrInfinity(intValue)) { | 193 if (integerBecomesNanOrInfinity(intValue)) { |
193 return new DoubleConstant(intValue.toDouble()); | 194 return new DoubleConstantValue(intValue.toDouble()); |
194 } | 195 } |
195 // If the integer loses precision with JavaScript numbers, use | 196 // If the integer loses precision with JavaScript numbers, use |
196 // the floored version JavaScript will use. | 197 // the floored version JavaScript will use. |
197 int floorValue = intValue.toDouble().floor().toInt(); | 198 int floorValue = intValue.toDouble().floor().toInt(); |
198 if (floorValue != intValue) { | 199 if (floorValue != intValue) { |
199 return new IntConstant(floorValue); | 200 return new IntConstantValue(floorValue); |
200 } | 201 } |
201 } else if (constant.isDouble) { | 202 } else if (constant.isDouble) { |
202 DoubleConstant doubleResult = constant; | 203 DoubleConstantValue doubleResult = constant; |
203 double doubleValue = doubleResult.value; | 204 double doubleValue = doubleResult.primitiveValue; |
204 if (!doubleValue.isInfinite && !doubleValue.isNaN && | 205 if (!doubleValue.isInfinite && !doubleValue.isNaN && |
205 !constant.isMinusZero) { | 206 !constant.isMinusZero) { |
206 int intValue = doubleValue.truncate(); | 207 int intValue = doubleValue.truncate(); |
207 if (intValue == doubleValue) { | 208 if (intValue == doubleValue) { |
208 return new IntConstant(intValue); | 209 return new IntConstantValue(intValue); |
209 } | 210 } |
210 } | 211 } |
211 } | 212 } |
212 return constant; | 213 return constant; |
213 } | 214 } |
214 | 215 |
215 NumConstant createInt(int i) | 216 NumConstantValue createInt(int i) |
216 => convertToJavaScriptConstant(new IntConstant(i)); | 217 => convertToJavaScriptConstant(new IntConstantValue(i)); |
217 NumConstant createInt32(int i) => new IntConstant(i & BITS32); | 218 NumConstantValue createInt32(int i) => new IntConstantValue(i & BITS32); |
218 NumConstant createDouble(double d) | 219 NumConstantValue createDouble(double d) |
219 => convertToJavaScriptConstant(new DoubleConstant(d)); | 220 => convertToJavaScriptConstant(new DoubleConstantValue(d)); |
220 StringConstant createString(DartString string) => new StringConstant(string); | 221 StringConstantValue createString(DartString string) { |
221 BoolConstant createBool(bool value) => new BoolConstant(value); | 222 return new StringConstantValue(string); |
222 NullConstant createNull() => new NullConstant(); | 223 } |
| 224 BoolConstantValue createBool(bool value) => new BoolConstantValue(value); |
| 225 NullConstantValue createNull() => new NullConstantValue(); |
223 | 226 |
224 // Integer checks don't verify that the number is not -0.0. | 227 // Integer checks don't verify that the number is not -0.0. |
225 bool isInt(Constant constant) => constant.isInt || constant.isMinusZero; | 228 bool isInt(ConstantValue constant) => constant.isInt || constant.isMinusZero; |
226 bool isDouble(Constant constant) | 229 bool isDouble(ConstantValue constant) |
227 => constant.isDouble && !constant.isMinusZero; | 230 => constant.isDouble && !constant.isMinusZero; |
228 bool isString(Constant constant) => constant.isString; | 231 bool isString(ConstantValue constant) => constant.isString; |
229 bool isBool(Constant constant) => constant.isBool; | 232 bool isBool(ConstantValue constant) => constant.isBool; |
230 bool isNull(Constant constant) => constant.isNull; | 233 bool isNull(ConstantValue constant) => constant.isNull; |
231 | 234 |
232 bool isSubtype(Compiler compiler, DartType s, DartType t) { | 235 bool isSubtype(Compiler compiler, DartType s, DartType t) { |
233 // At runtime, an integer is both an integer and a double: the | 236 // At runtime, an integer is both an integer and a double: the |
234 // integer type check is Math.floor, which will return true only | 237 // integer type check is Math.floor, which will return true only |
235 // for real integers, and our double type check is 'typeof number' | 238 // for real integers, and our double type check is 'typeof number' |
236 // which will return true for both integers and doubles. | 239 // which will return true for both integers and doubles. |
237 if (s.element == compiler.intClass && t.element == compiler.doubleClass) { | 240 if (s.element == compiler.intClass && t.element == compiler.doubleClass) { |
238 return true; | 241 return true; |
239 } | 242 } |
240 return compiler.types.isSubtype(s, t); | 243 return compiler.types.isSubtype(s, t); |
241 } | 244 } |
242 | 245 |
243 MapConstant createMap(Compiler compiler, | 246 MapConstantValue createMap(Compiler compiler, |
244 InterfaceType sourceType, | 247 InterfaceType sourceType, |
245 List<Constant> keys, | 248 List<ConstantValue> keys, |
246 List<Constant> values) { | 249 List<ConstantValue> values) { |
247 JavaScriptBackend backend = compiler.backend; | 250 JavaScriptBackend backend = compiler.backend; |
248 | 251 |
249 bool onlyStringKeys = true; | 252 bool onlyStringKeys = true; |
250 Constant protoValue = null; | 253 ConstantValue protoValue = null; |
251 for (int i = 0; i < keys.length ; i++) { | 254 for (int i = 0; i < keys.length ; i++) { |
252 var key = keys[i]; | 255 var key = keys[i]; |
253 if (key.isString) { | 256 if (key.isString) { |
254 if (key.value == JavaScriptMapConstant.PROTO_PROPERTY) { | 257 if (key.primitiveValue == JavaScriptMapConstant.PROTO_PROPERTY) { |
255 protoValue = values[i]; | 258 protoValue = values[i]; |
256 } | 259 } |
257 } else { | 260 } else { |
258 onlyStringKeys = false; | 261 onlyStringKeys = false; |
259 // Don't handle __proto__ values specially in the general map case. | 262 // Don't handle __proto__ values specially in the general map case. |
260 protoValue = null; | 263 protoValue = null; |
261 break; | 264 break; |
262 } | 265 } |
263 } | 266 } |
264 | 267 |
265 bool hasProtoKey = (protoValue != null); | 268 bool hasProtoKey = (protoValue != null); |
266 DartType keysType; | 269 DartType keysType; |
267 if (sourceType.treatAsRaw) { | 270 if (sourceType.treatAsRaw) { |
268 keysType = compiler.listClass.rawType; | 271 keysType = compiler.listClass.rawType; |
269 } else { | 272 } else { |
270 List<DartType> arguments = <DartType>[sourceType.typeArguments.first]; | 273 List<DartType> arguments = <DartType>[sourceType.typeArguments.first]; |
271 keysType = new InterfaceType(compiler.listClass, arguments); | 274 keysType = new InterfaceType(compiler.listClass, arguments); |
272 } | 275 } |
273 ListConstant keysList = new ListConstant(keysType, keys); | 276 ListConstantValue keysList = new ListConstantValue(keysType, keys); |
274 String className = onlyStringKeys | 277 String className = onlyStringKeys |
275 ? (hasProtoKey ? JavaScriptMapConstant.DART_PROTO_CLASS | 278 ? (hasProtoKey ? JavaScriptMapConstant.DART_PROTO_CLASS |
276 : JavaScriptMapConstant.DART_STRING_CLASS) | 279 : JavaScriptMapConstant.DART_STRING_CLASS) |
277 : JavaScriptMapConstant.DART_GENERAL_CLASS; | 280 : JavaScriptMapConstant.DART_GENERAL_CLASS; |
278 ClassElement classElement = backend.jsHelperLibrary.find(className); | 281 ClassElement classElement = backend.jsHelperLibrary.find(className); |
279 classElement.ensureResolved(compiler); | 282 classElement.ensureResolved(compiler); |
280 List<DartType> typeArgument = sourceType.typeArguments; | 283 List<DartType> typeArgument = sourceType.typeArguments; |
281 InterfaceType type; | 284 InterfaceType type; |
282 if (sourceType.treatAsRaw) { | 285 if (sourceType.treatAsRaw) { |
283 type = classElement.rawType; | 286 type = classElement.rawType; |
284 } else { | 287 } else { |
285 type = new InterfaceType(classElement, typeArgument); | 288 type = new InterfaceType(classElement, typeArgument); |
286 } | 289 } |
287 return new JavaScriptMapConstant( | 290 return new JavaScriptMapConstant( |
288 type, keysList, values, protoValue, onlyStringKeys); | 291 type, keysList, values, protoValue, onlyStringKeys); |
289 | 292 |
290 } | 293 } |
291 } | 294 } |
292 | 295 |
293 class JavaScriptMapConstant extends MapConstant { | 296 class JavaScriptMapConstant extends MapConstantValue { |
294 /** | 297 /** |
295 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript | 298 * The [PROTO_PROPERTY] must not be used as normal property in any JavaScript |
296 * object. It would change the prototype chain. | 299 * object. It would change the prototype chain. |
297 */ | 300 */ |
298 static const LiteralDartString PROTO_PROPERTY = | 301 static const LiteralDartString PROTO_PROPERTY = |
299 const LiteralDartString("__proto__"); | 302 const LiteralDartString("__proto__"); |
300 | 303 |
301 /** The dart class implementing constant map literals. */ | 304 /** The dart class implementing constant map literals. */ |
302 static const String DART_CLASS = "ConstantMap"; | 305 static const String DART_CLASS = "ConstantMap"; |
303 static const String DART_STRING_CLASS = "ConstantStringMap"; | 306 static const String DART_STRING_CLASS = "ConstantStringMap"; |
304 static const String DART_PROTO_CLASS = "ConstantProtoMap"; | 307 static const String DART_PROTO_CLASS = "ConstantProtoMap"; |
305 static const String DART_GENERAL_CLASS = "GeneralConstantMap"; | 308 static const String DART_GENERAL_CLASS = "GeneralConstantMap"; |
306 static const String LENGTH_NAME = "length"; | 309 static const String LENGTH_NAME = "length"; |
307 static const String JS_OBJECT_NAME = "_jsObject"; | 310 static const String JS_OBJECT_NAME = "_jsObject"; |
308 static const String KEYS_NAME = "_keys"; | 311 static const String KEYS_NAME = "_keys"; |
309 static const String PROTO_VALUE = "_protoValue"; | 312 static const String PROTO_VALUE = "_protoValue"; |
310 static const String JS_DATA_NAME = "_jsData"; | 313 static const String JS_DATA_NAME = "_jsData"; |
311 | 314 |
312 final ListConstant keyList; | 315 final ListConstantValue keyList; |
313 final Constant protoValue; | 316 final ConstantValue protoValue; |
314 final bool onlyStringKeys; | 317 final bool onlyStringKeys; |
315 | 318 |
316 JavaScriptMapConstant(InterfaceType type, | 319 JavaScriptMapConstant(InterfaceType type, |
317 ListConstant keyList, | 320 ListConstantValue keyList, |
318 List<Constant> values, | 321 List<ConstantValue> values, |
319 this.protoValue, | 322 this.protoValue, |
320 this.onlyStringKeys) | 323 this.onlyStringKeys) |
321 : this.keyList = keyList, | 324 : this.keyList = keyList, |
322 super(type, keyList.entries, values); | 325 super(type, keyList.entries, values); |
323 bool get isMap => true; | 326 bool get isMap => true; |
324 | 327 |
325 TypeMask computeMask(Compiler compiler) { | 328 TypeMask computeMask(Compiler compiler) { |
326 return compiler.typesTask.constMapType; | 329 return compiler.typesTask.constMapType; |
327 } | 330 } |
328 | 331 |
329 List<Constant> getDependencies() { | 332 List<ConstantValue> getDependencies() { |
330 List<Constant> result = <Constant>[]; | 333 List<ConstantValue> result = <ConstantValue>[]; |
331 if (onlyStringKeys) { | 334 if (onlyStringKeys) { |
332 result.add(keyList); | 335 result.add(keyList); |
333 } else { | 336 } else { |
334 // Add the keys individually to avoid generating an unused list constant | 337 // Add the keys individually to avoid generating an unused list constant |
335 // for the keys. | 338 // for the keys. |
336 result.addAll(keys); | 339 result.addAll(keys); |
337 } | 340 } |
338 result.addAll(values); | 341 result.addAll(values); |
339 return result; | 342 return result; |
340 } | 343 } |
341 } | 344 } |
OLD | NEW |