Bug 812446 - Optimize str[double], str.char[Code]At(double). r=nbp
authorTom Schuster <evilpies@gmail.com>
Wed, 12 Dec 2012 13:21:41 +0100
changeset 121353 f99c04a0afc54356509f222902988c3c8d53ab8f
parent 121352 421ea4f8b050efb92228d94d0ecd093aa3a9c1c6
child 121354 2ce14c9551fa3e280fbf2a2a036ba7bf64900d31
push idunknown
push userunknown
push dateunknown
reviewersnbp
bugs812446
milestone20.0a1
Bug 812446 - Optimize str[double], str.char[Code]At(double). r=nbp
js/src/ion/MCallOptimize.cpp
js/src/ion/TypeOracle.cpp
js/src/jsinterpinlines.h
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -708,17 +708,18 @@ IonBuilder::inlineStrCharCodeAt(uint32_t
 {
     if (argc != 1 || constructing)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType_Int32)
         return InliningStatus_NotInlined;
     if (getInlineArgType(argc, 0) != MIRType_String)
         return InliningStatus_NotInlined;
-    if (getInlineArgType(argc, 1) != MIRType_Int32)
+    MIRType argType = getInlineArgType(argc, 1);
+    if (argType != MIRType_Int32 && argType != MIRType_Double)
         return InliningStatus_NotInlined;
 
     MDefinitionVector argv;
     if (!discardCall(argc, argv, current))
         return InliningStatus_Error;
 
     MInstruction *index = MToInt32::New(argv[1]);
     current->add(index);
@@ -763,17 +764,18 @@ IonBuilder::inlineStrCharAt(uint32_t arg
 {
     if (argc != 1 || constructing)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType_String)
         return InliningStatus_NotInlined;
     if (getInlineArgType(argc, 0) != MIRType_String)
         return InliningStatus_NotInlined;
-    if (getInlineArgType(argc, 1) != MIRType_Int32)
+    MIRType argType = getInlineArgType(argc, 1);
+    if (argType != MIRType_Int32 && argType != MIRType_Double)
         return InliningStatus_NotInlined;
 
     MDefinitionVector argv;
     if (!discardCall(argc, argv, current))
         return InliningStatus_Error;
 
     MInstruction *index = MToInt32::New(argv[1]);
     current->add(index);
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -343,24 +343,25 @@ TypeInferenceOracle::elementReadIsTypedA
     }
 
     return true;
 }
 
 bool
 TypeInferenceOracle::elementReadIsString(JSScript *script, jsbytecode *pc)
 {
-    // Check for string[int32].
+    // Check for string[index].
     StackTypeSet *value = script->analysis()->poppedTypes(pc, 1);
     StackTypeSet *id = script->analysis()->poppedTypes(pc, 0);
 
     if (value->getKnownTypeTag() != JSVAL_TYPE_STRING)
         return false;
 
-    if (id->getKnownTypeTag() != JSVAL_TYPE_INT32)
+    JSValueType idType = id->getKnownTypeTag();
+    if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
         return false;
 
     // This function is used for jsop_getelem_string which should return
     // undefined if this is out-side the string bounds. Currently we just
     // fallback to a CallGetElement.
     StackTypeSet *pushed = script->analysis()->pushedTypes(pc, 0);
     if (pushed->getKnownTypeTag() != JSVAL_TYPE_STRING)
         return false;
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -785,21 +785,21 @@ GetObjectElementOperation(JSContext *cx,
 
 static JS_ALWAYS_INLINE bool
 GetElementOperation(JSContext *cx, JSOp op, HandleValue lref, HandleValue rref,
                     MutableHandleValue res)
 {
     AssertCanGC();
     JS_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
 
-    if (lref.isString() && rref.isInt32()) {
+    uint32_t index;
+    if (lref.isString() && IsDefinitelyIndex(rref, &index)) {
         JSString *str = lref.toString();
-        int32_t i = rref.toInt32();
-        if (size_t(i) < str->length()) {
-            str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
+        if (index < str->length()) {
+            str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, index);
             if (!str)
                 return false;
             res.setString(str);
             return true;
         }
     }
 
     StackFrame *fp = cx->fp();