Index: dart/lib/compiler/implementation/lib/interceptors.dart |
diff --git a/dart/lib/compiler/implementation/lib/interceptors.dart b/dart/lib/compiler/implementation/lib/interceptors.dart |
index 680af43e4408e4c86110e683b17e77d774d02123..240b0dd3b39dc8da5b65e1e657663fb21266e929 100644 |
--- a/dart/lib/compiler/implementation/lib/interceptors.dart |
+++ b/dart/lib/compiler/implementation/lib/interceptors.dart |
@@ -364,13 +364,69 @@ every(receiver, f) { |
sort$0(receiver) { |
if (!isJsArray(receiver)) return UNINTERCEPTED(receiver.sort()); |
floitsch
2012/10/18 12:27:22
After this if I would call sort$1(receiver, Compar
Lasse Reichstein Nielsen
2012/10/18 13:04:00
The trick is that this is simpler because we know
floitsch
2012/10/18 13:46:51
Since the shortcut only applies when it is going t
|
checkMutable(receiver, 'sort'); |
- DualPivotQuicksort.sort(receiver, Comparable.compare); |
+ |
+ int length = JS('int', '#.length', receiver); |
+ if (length == 0 || length == 1) return; |
Lasse Reichstein Nielsen
2012/10/18 13:04:00
<= 1 should be fine, a JS Array's length can't be
|
+ for (int i = 0; i < length; i++) { |
+ // JavaScript's Array.prototype.sort has wierd semantics for null. |
+ // It won't call compare and automatically pushes null/undefined |
+ // to the end. |
+ if (JS('var', '#[#]', receiver, i) == null) { |
+ var other = JS('var', '#[#]', receiver, 0); |
+ if (i == 0) { |
+ other = JS('var', '#[#]', receiver, 1); |
+ } |
+ // Provoke a null error by comparing null to another element in |
+ // the array. |
+ Comparable.compare(null, other); |
+ } |
+ } |
+ |
+ JS('void', '#.sort(#)', receiver, DART_CLOSURE_TO_JS(Comparable.compare)); |
} |
sort$1(receiver, compare) { |
if (!isJsArray(receiver)) return UNINTERCEPTED(receiver.sort(compare)); |
checkMutable(receiver, 'sort'); |
- DualPivotQuicksort.sort(receiver, compare); |
+ int length = JS('int', '#.length', receiver); |
floitsch
2012/10/18 12:27:22
Just tell dart2js that receiver is a JavaScript-ar
ahe
2012/11/23 08:43:42
How do I do that?
sra1
2012/11/23 10:57:33
This code is dominated by isJsArray(receiver).
Why
floitsch
2012/11/23 13:00:51
It should be, and now with the new interceptor app
|
+ if (length == 0 || length == 1) return; |
+ bool hasNull = false; |
+ var array = receiver; |
+ for (int i = 0; i < length; i++) { |
floitsch
2012/10/18 12:27:22
Given that you already run through the array, you
sra1
2012/11/23 10:57:33
This assumes compareTo returns num, not int. I'm
|
+ // JavaScript's Array.prototype.sort has wierd semantics for null. |
floitsch
2012/10/18 12:27:22
weird
|
+ // It won't call compare and automatically pushes null/undefined |
+ // to the end. |
+ if (JS('var', '#[#]', array, i) == null) { |
+ if (!hasNull) { |
+ array = JS('var', '#.slice(0)', array); |
floitsch
2012/10/18 12:27:22
Why do we need a copy? To avoid the try/finally?
Lasse Reichstein Nielsen
2012/10/19 07:03:21
Because any NullSentinel in the original array wou
|
+ } |
+ JS('var', '#[#] = #', array, i, const NullSentinel()); |
+ hasNull = true; |
+ } |
+ } |
+ var jsCompare; |
+ if (hasNull) { |
floitsch
2012/10/18 12:27:22
I would special case for the Compare.compare:
if (
|
+ jsCompare = DART_CLOSURE_TO_JS(compareHelperNull); |
+ } else { |
+ jsCompare = DART_CLOSURE_TO_JS(compareHelper); |
+ } |
+ // [DART_CLOSURE_TO_JS] only accepts static or top-level functions. |
+ // So we use [compareHelper] and JavaScript's |
+ // Function.prototype.bind to create a new closure we can safely |
+ // pass to JavaScript. |
+ jsCompare = JS('var', '#.bind(#, #)', jsCompare, null, compare); |
Lasse Reichstein Nielsen
2012/10/18 11:54:50
Is 'bind' fast now? That would be great :)
Try re
|
+ |
+ JS('void', '#.sort(#)', receiver, jsCompare); |
+ |
+ if (hasNull) { |
+ for (int i = 0; i < length; i++) { |
+ var element = JS('var', '#[#]', array, i); |
+ if (const NullSentinel() == element) { |
+ element = null; |
+ } |
+ JS('var', '#[#] = #', receiver, i, element); |
+ } |
+ } |
} |
isNegative(receiver) { |