/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.runtime.internal; import static com.github.anba.es6draft.runtime.objects.simd.SIMD.SIMDCreate; import org.mozilla.javascript.ConsString; import com.github.anba.es6draft.runtime.objects.simd.SIMDValue; /** * {@link LinkedMap} implementation with additional changes to {@link #newEntry(Object, Object)} and * {@link #hashKey(Object)} to properly support runtime types. */ public final class LinkedMapImpl<VALUE> extends LinkedMap<Object, VALUE> { @Override protected Entry<Object, VALUE> newEntry(Object key, VALUE value) { if (key instanceof Double) { // Map +/-0 to +0 per Map.prototype.set and Set.prototype.add. double v = (Double) key; return super.newEntry(v == 0 ? +0d : v, value); } return super.newEntry(key, value); } @Override protected Object hashKey(Object key) { if (key instanceof ConsString) { // ConsString -> String return ((ConsString) key).toString(); } if (key instanceof Integer) { // int -> double return (double) (Integer) key; } if (key instanceof Long) { // long -> double return (double) (Long) key; } if (key instanceof Double) { // Map +/-0 to +0 to enforce SameValueZero comparison semantics. double v = (Double) key; return v == 0 ? +0d : v; } if (key instanceof SIMDValue) { // Map +/-0 to +0 to enforce SameValueZero comparison semantics. return hashKeySIMD((SIMDValue) key); } return key; } private SIMDValue hashKeySIMD(SIMDValue value) { if (!value.getType().isFloatingPoint()) { return value; } double[] copy = null, elements = value.asDouble(); for (int i = 0; i < elements.length; ++i) { double v = elements[i]; if (v == 0 && Double.doubleToRawLongBits(v) != 0L) { if (copy == null) { copy = elements.clone(); } copy[i] = +0d; } } if (copy != null) { return SIMDCreate(value.getType(), copy); } return value; } }