The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / runtime.cc @ f230a1cf

History | View | Annotate | Download (506 KB)

1
// Copyright 2012 the V8 project authors. All rights reserved.
2
// Redistribution and use in source and binary forms, with or without
3
// modification, are permitted provided that the following conditions are
4
// met:
5
//
6
//     * Redistributions of source code must retain the above copyright
7
//       notice, this list of conditions and the following disclaimer.
8
//     * Redistributions in binary form must reproduce the above
9
//       copyright notice, this list of conditions and the following
10
//       disclaimer in the documentation and/or other materials provided
11
//       with the distribution.
12
//     * Neither the name of Google Inc. nor the names of its
13
//       contributors may be used to endorse or promote products derived
14
//       from this software without specific prior written permission.
15
//
16
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27

    
28
#include <stdlib.h>
29
#include <limits>
30

    
31
#include "v8.h"
32

    
33
#include "accessors.h"
34
#include "allocation-site-scopes.h"
35
#include "api.h"
36
#include "arguments.h"
37
#include "bootstrapper.h"
38
#include "codegen.h"
39
#include "compilation-cache.h"
40
#include "compiler.h"
41
#include "cpu.h"
42
#include "cpu-profiler.h"
43
#include "dateparser-inl.h"
44
#include "debug.h"
45
#include "deoptimizer.h"
46
#include "date.h"
47
#include "execution.h"
48
#include "full-codegen.h"
49
#include "global-handles.h"
50
#include "isolate-inl.h"
51
#include "jsregexp.h"
52
#include "jsregexp-inl.h"
53
#include "json-parser.h"
54
#include "json-stringifier.h"
55
#include "liveedit.h"
56
#include "misc-intrinsics.h"
57
#include "parser.h"
58
#include "platform.h"
59
#include "runtime-profiler.h"
60
#include "runtime.h"
61
#include "scopeinfo.h"
62
#include "smart-pointers.h"
63
#include "string-search.h"
64
#include "stub-cache.h"
65
#include "uri.h"
66
#include "v8conversions.h"
67
#include "v8threads.h"
68
#include "vm-state-inl.h"
69

    
70
#ifdef V8_I18N_SUPPORT
71
#include "i18n.h"
72
#include "unicode/brkiter.h"
73
#include "unicode/calendar.h"
74
#include "unicode/coll.h"
75
#include "unicode/curramt.h"
76
#include "unicode/datefmt.h"
77
#include "unicode/dcfmtsym.h"
78
#include "unicode/decimfmt.h"
79
#include "unicode/dtfmtsym.h"
80
#include "unicode/dtptngen.h"
81
#include "unicode/locid.h"
82
#include "unicode/numfmt.h"
83
#include "unicode/numsys.h"
84
#include "unicode/rbbi.h"
85
#include "unicode/smpdtfmt.h"
86
#include "unicode/timezone.h"
87
#include "unicode/uchar.h"
88
#include "unicode/ucol.h"
89
#include "unicode/ucurr.h"
90
#include "unicode/uloc.h"
91
#include "unicode/unum.h"
92
#include "unicode/uversion.h"
93
#endif
94

    
95
#ifndef _STLP_VENDOR_CSTD
96
// STLPort doesn't import fpclassify and isless into the std namespace.
97
using std::fpclassify;
98
using std::isless;
99
#endif
100

    
101
namespace v8 {
102
namespace internal {
103

    
104

    
105
#define RUNTIME_ASSERT(value) \
106
  if (!(value)) return isolate->ThrowIllegalOperation();
107

    
108
// Cast the given object to a value of the specified type and store
109
// it in a variable with the given name.  If the object is not of the
110
// expected type call IllegalOperation and return.
111
#define CONVERT_ARG_CHECKED(Type, name, index)                       \
112
  RUNTIME_ASSERT(args[index]->Is##Type());                           \
113
  Type* name = Type::cast(args[index]);
114

    
115
#define CONVERT_ARG_HANDLE_CHECKED(Type, name, index)                \
116
  RUNTIME_ASSERT(args[index]->Is##Type());                           \
117
  Handle<Type> name = args.at<Type>(index);
118

    
119
// Cast the given object to a boolean and store it in a variable with
120
// the given name.  If the object is not a boolean call IllegalOperation
121
// and return.
122
#define CONVERT_BOOLEAN_ARG_CHECKED(name, index)                     \
123
  RUNTIME_ASSERT(args[index]->IsBoolean());                          \
124
  bool name = args[index]->IsTrue();
125

    
126
// Cast the given argument to a Smi and store its value in an int variable
127
// with the given name.  If the argument is not a Smi call IllegalOperation
128
// and return.
129
#define CONVERT_SMI_ARG_CHECKED(name, index)                         \
130
  RUNTIME_ASSERT(args[index]->IsSmi());                              \
131
  int name = args.smi_at(index);
132

    
133
// Cast the given argument to a double and store it in a variable with
134
// the given name.  If the argument is not a number (as opposed to
135
// the number not-a-number) call IllegalOperation and return.
136
#define CONVERT_DOUBLE_ARG_CHECKED(name, index)                      \
137
  RUNTIME_ASSERT(args[index]->IsNumber());                           \
138
  double name = args.number_at(index);
139

    
140
// Call the specified converter on the object *comand store the result in
141
// a variable of the specified type with the given name.  If the
142
// object is not a Number call IllegalOperation and return.
143
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
144
  RUNTIME_ASSERT(obj->IsNumber());                                   \
145
  type name = NumberTo##Type(obj);
146

    
147

    
148
// Cast the given argument to PropertyDetails and store its value in a
149
// variable with the given name.  If the argument is not a Smi call
150
// IllegalOperation and return.
151
#define CONVERT_PROPERTY_DETAILS_CHECKED(name, index)                \
152
  RUNTIME_ASSERT(args[index]->IsSmi());                              \
153
  PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
154

    
155

    
156
// Assert that the given argument has a valid value for a StrictModeFlag
157
// and store it in a StrictModeFlag variable with the given name.
158
#define CONVERT_STRICT_MODE_ARG_CHECKED(name, index)                 \
159
  RUNTIME_ASSERT(args[index]->IsSmi());                              \
160
  RUNTIME_ASSERT(args.smi_at(index) == kStrictMode ||                \
161
                 args.smi_at(index) == kNonStrictMode);              \
162
  StrictModeFlag name =                                              \
163
      static_cast<StrictModeFlag>(args.smi_at(index));
164

    
165

    
166
// Assert that the given argument has a valid value for a LanguageMode
167
// and store it in a LanguageMode variable with the given name.
168
#define CONVERT_LANGUAGE_MODE_ARG(name, index)                       \
169
  ASSERT(args[index]->IsSmi());                                      \
170
  ASSERT(args.smi_at(index) == CLASSIC_MODE ||                       \
171
         args.smi_at(index) == STRICT_MODE ||                        \
172
         args.smi_at(index) == EXTENDED_MODE);                       \
173
  LanguageMode name =                                                \
174
      static_cast<LanguageMode>(args.smi_at(index));
175

    
176

    
177
static Handle<Map> ComputeObjectLiteralMap(
178
    Handle<Context> context,
179
    Handle<FixedArray> constant_properties,
180
    bool* is_result_from_cache) {
181
  Isolate* isolate = context->GetIsolate();
182
  int properties_length = constant_properties->length();
183
  int number_of_properties = properties_length / 2;
184
  // Check that there are only internal strings and array indices among keys.
185
  int number_of_string_keys = 0;
186
  for (int p = 0; p != properties_length; p += 2) {
187
    Object* key = constant_properties->get(p);
188
    uint32_t element_index = 0;
189
    if (key->IsInternalizedString()) {
190
      number_of_string_keys++;
191
    } else if (key->ToArrayIndex(&element_index)) {
192
      // An index key does not require space in the property backing store.
193
      number_of_properties--;
194
    } else {
195
      // Bail out as a non-internalized-string non-index key makes caching
196
      // impossible.
197
      // ASSERT to make sure that the if condition after the loop is false.
198
      ASSERT(number_of_string_keys != number_of_properties);
199
      break;
200
    }
201
  }
202
  // If we only have internalized strings and array indices among keys then we
203
  // can use the map cache in the native context.
204
  const int kMaxKeys = 10;
205
  if ((number_of_string_keys == number_of_properties) &&
206
      (number_of_string_keys < kMaxKeys)) {
207
    // Create the fixed array with the key.
208
    Handle<FixedArray> keys =
209
        isolate->factory()->NewFixedArray(number_of_string_keys);
210
    if (number_of_string_keys > 0) {
211
      int index = 0;
212
      for (int p = 0; p < properties_length; p += 2) {
213
        Object* key = constant_properties->get(p);
214
        if (key->IsInternalizedString()) {
215
          keys->set(index++, key);
216
        }
217
      }
218
      ASSERT(index == number_of_string_keys);
219
    }
220
    *is_result_from_cache = true;
221
    return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
222
  }
223
  *is_result_from_cache = false;
224
  return isolate->factory()->CopyMap(
225
      Handle<Map>(context->object_function()->initial_map()),
226
      number_of_properties);
227
}
228

    
229

    
230
static Handle<Object> CreateLiteralBoilerplate(
231
    Isolate* isolate,
232
    Handle<FixedArray> literals,
233
    Handle<FixedArray> constant_properties);
234

    
235

    
236
static Handle<Object> CreateObjectLiteralBoilerplate(
237
    Isolate* isolate,
238
    Handle<FixedArray> literals,
239
    Handle<FixedArray> constant_properties,
240
    bool should_have_fast_elements,
241
    bool has_function_literal) {
242
  // Get the native context from the literals array.  This is the
243
  // context in which the function was created and we use the object
244
  // function from this context to create the object literal.  We do
245
  // not use the object function from the current native context
246
  // because this might be the object function from another context
247
  // which we should not have access to.
248
  Handle<Context> context =
249
      Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
250

    
251
  // In case we have function literals, we want the object to be in
252
  // slow properties mode for now. We don't go in the map cache because
253
  // maps with constant functions can't be shared if the functions are
254
  // not the same (which is the common case).
255
  bool is_result_from_cache = false;
256
  Handle<Map> map = has_function_literal
257
      ? Handle<Map>(context->object_function()->initial_map())
258
      : ComputeObjectLiteralMap(context,
259
                                constant_properties,
260
                                &is_result_from_cache);
261

    
262
  Handle<JSObject> boilerplate =
263
      isolate->factory()->NewJSObjectFromMap(
264
          map, isolate->heap()->GetPretenureMode());
265

    
266
  // Normalize the elements of the boilerplate to save space if needed.
267
  if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
268

    
269
  // Add the constant properties to the boilerplate.
270
  int length = constant_properties->length();
271
  bool should_transform =
272
      !is_result_from_cache && boilerplate->HasFastProperties();
273
  if (should_transform || has_function_literal) {
274
    // Normalize the properties of object to avoid n^2 behavior
275
    // when extending the object multiple properties. Indicate the number of
276
    // properties to be added.
277
    JSObject::NormalizeProperties(
278
        boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
279
  }
280

    
281
  // TODO(verwaest): Support tracking representations in the boilerplate.
282
  for (int index = 0; index < length; index +=2) {
283
    Handle<Object> key(constant_properties->get(index+0), isolate);
284
    Handle<Object> value(constant_properties->get(index+1), isolate);
285
    if (value->IsFixedArray()) {
286
      // The value contains the constant_properties of a
287
      // simple object or array literal.
288
      Handle<FixedArray> array = Handle<FixedArray>::cast(value);
289
      value = CreateLiteralBoilerplate(isolate, literals, array);
290
      if (value.is_null()) return value;
291
    }
292
    Handle<Object> result;
293
    uint32_t element_index = 0;
294
    StoreMode mode = value->IsJSObject() ? FORCE_FIELD : ALLOW_AS_CONSTANT;
295
    if (key->IsInternalizedString()) {
296
      if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
297
        // Array index as string (uint32).
298
        result = JSObject::SetOwnElement(
299
            boilerplate, element_index, value, kNonStrictMode);
300
      } else {
301
        Handle<String> name(String::cast(*key));
302
        ASSERT(!name->AsArrayIndex(&element_index));
303
        result = JSObject::SetLocalPropertyIgnoreAttributes(
304
            boilerplate, name, value, NONE,
305
            Object::OPTIMAL_REPRESENTATION, mode);
306
      }
307
    } else if (key->ToArrayIndex(&element_index)) {
308
      // Array index (uint32).
309
      result = JSObject::SetOwnElement(
310
          boilerplate, element_index, value, kNonStrictMode);
311
    } else {
312
      // Non-uint32 number.
313
      ASSERT(key->IsNumber());
314
      double num = key->Number();
315
      char arr[100];
316
      Vector<char> buffer(arr, ARRAY_SIZE(arr));
317
      const char* str = DoubleToCString(num, buffer);
318
      Handle<String> name =
319
          isolate->factory()->NewStringFromAscii(CStrVector(str));
320
      result = JSObject::SetLocalPropertyIgnoreAttributes(
321
          boilerplate, name, value, NONE,
322
          Object::OPTIMAL_REPRESENTATION, mode);
323
    }
324
    // If setting the property on the boilerplate throws an
325
    // exception, the exception is converted to an empty handle in
326
    // the handle based operations.  In that case, we need to
327
    // convert back to an exception.
328
    if (result.is_null()) return result;
329
  }
330

    
331
  // Transform to fast properties if necessary. For object literals with
332
  // containing function literals we defer this operation until after all
333
  // computed properties have been assigned so that we can generate
334
  // constant function properties.
335
  if (should_transform && !has_function_literal) {
336
    JSObject::TransformToFastProperties(
337
        boilerplate, boilerplate->map()->unused_property_fields());
338
  }
339

    
340
  return boilerplate;
341
}
342

    
343

    
344
MaybeObject* TransitionElements(Handle<Object> object,
345
                                ElementsKind to_kind,
346
                                Isolate* isolate) {
347
  HandleScope scope(isolate);
348
  if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
349
  ElementsKind from_kind =
350
      Handle<JSObject>::cast(object)->map()->elements_kind();
351
  if (Map::IsValidElementsTransition(from_kind, to_kind)) {
352
    JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), to_kind);
353
    return *object;
354
  }
355
  return isolate->ThrowIllegalOperation();
356
}
357

    
358

    
359
static const int kSmiLiteralMinimumLength = 1024;
360

    
361

    
362
Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
363
    Isolate* isolate,
364
    Handle<FixedArray> literals,
365
    Handle<FixedArray> elements) {
366
  // Create the JSArray.
367
  Handle<JSFunction> constructor(
368
      JSFunction::NativeContextFromLiterals(*literals)->array_function());
369

    
370
  Handle<JSArray> object = Handle<JSArray>::cast(
371
      isolate->factory()->NewJSObject(
372
          constructor, isolate->heap()->GetPretenureMode()));
373

    
374
  ElementsKind constant_elements_kind =
375
      static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
376
  Handle<FixedArrayBase> constant_elements_values(
377
      FixedArrayBase::cast(elements->get(1)));
378

    
379
  ASSERT(IsFastElementsKind(constant_elements_kind));
380
  Context* native_context = isolate->context()->native_context();
381
  Object* maybe_maps_array = native_context->js_array_maps();
382
  ASSERT(!maybe_maps_array->IsUndefined());
383
  Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
384
      constant_elements_kind);
385
  ASSERT(maybe_map->IsMap());
386
  object->set_map(Map::cast(maybe_map));
387

    
388
  Handle<FixedArrayBase> copied_elements_values;
389
  if (IsFastDoubleElementsKind(constant_elements_kind)) {
390
    ASSERT(FLAG_smi_only_arrays);
391
    copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
392
        Handle<FixedDoubleArray>::cast(constant_elements_values));
393
  } else {
394
    ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
395
    const bool is_cow =
396
        (constant_elements_values->map() ==
397
         isolate->heap()->fixed_cow_array_map());
398
    if (is_cow) {
399
      copied_elements_values = constant_elements_values;
400
#if DEBUG
401
      Handle<FixedArray> fixed_array_values =
402
          Handle<FixedArray>::cast(copied_elements_values);
403
      for (int i = 0; i < fixed_array_values->length(); i++) {
404
        ASSERT(!fixed_array_values->get(i)->IsFixedArray());
405
      }
406
#endif
407
    } else {
408
      Handle<FixedArray> fixed_array_values =
409
          Handle<FixedArray>::cast(constant_elements_values);
410
      Handle<FixedArray> fixed_array_values_copy =
411
          isolate->factory()->CopyFixedArray(fixed_array_values);
412
      copied_elements_values = fixed_array_values_copy;
413
      for (int i = 0; i < fixed_array_values->length(); i++) {
414
        Object* current = fixed_array_values->get(i);
415
        if (current->IsFixedArray()) {
416
          // The value contains the constant_properties of a
417
          // simple object or array literal.
418
          Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
419
          Handle<Object> result =
420
              CreateLiteralBoilerplate(isolate, literals, fa);
421
          if (result.is_null()) return result;
422
          fixed_array_values_copy->set(i, *result);
423
        }
424
      }
425
    }
426
  }
427
  object->set_elements(*copied_elements_values);
428
  object->set_length(Smi::FromInt(copied_elements_values->length()));
429

    
430
  //  Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
431
  //  on or the object is larger than the threshold.
432
  if (!FLAG_smi_only_arrays &&
433
      constant_elements_values->length() < kSmiLiteralMinimumLength) {
434
    ElementsKind elements_kind = object->GetElementsKind();
435
    if (!IsFastObjectElementsKind(elements_kind)) {
436
      if (IsFastHoleyElementsKind(elements_kind)) {
437
        CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
438
                                  isolate)->IsFailure());
439
      } else {
440
        CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
441
      }
442
    }
443
  }
444

    
445
  object->ValidateElements();
446
  return object;
447
}
448

    
449

    
450
static Handle<Object> CreateLiteralBoilerplate(
451
    Isolate* isolate,
452
    Handle<FixedArray> literals,
453
    Handle<FixedArray> array) {
454
  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
455
  const bool kHasNoFunctionLiteral = false;
456
  switch (CompileTimeValue::GetLiteralType(array)) {
457
    case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
458
      return CreateObjectLiteralBoilerplate(isolate,
459
                                            literals,
460
                                            elements,
461
                                            true,
462
                                            kHasNoFunctionLiteral);
463
    case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
464
      return CreateObjectLiteralBoilerplate(isolate,
465
                                            literals,
466
                                            elements,
467
                                            false,
468
                                            kHasNoFunctionLiteral);
469
    case CompileTimeValue::ARRAY_LITERAL:
470
      return Runtime::CreateArrayLiteralBoilerplate(
471
          isolate, literals, elements);
472
    default:
473
      UNREACHABLE();
474
      return Handle<Object>::null();
475
  }
476
}
477

    
478

    
479
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
480
  HandleScope scope(isolate);
481
  ASSERT(args.length() == 4);
482
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
483
  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
484
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
485
  CONVERT_SMI_ARG_CHECKED(flags, 3);
486
  bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
487
  bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
488

    
489
  // Check if boilerplate exists. If not, create it first.
490
  Handle<Object> literal_site(literals->get(literals_index), isolate);
491
  Handle<AllocationSite> site;
492
  Handle<JSObject> boilerplate;
493
  if (*literal_site == isolate->heap()->undefined_value()) {
494
    Handle<Object> raw_boilerplate = CreateObjectLiteralBoilerplate(
495
        isolate,
496
        literals,
497
        constant_properties,
498
        should_have_fast_elements,
499
        has_function_literal);
500
    RETURN_IF_EMPTY_HANDLE(isolate, raw_boilerplate);
501
    boilerplate = Handle<JSObject>::cast(raw_boilerplate);
502

    
503
    AllocationSiteCreationContext creation_context(isolate);
504
    site = creation_context.EnterNewScope();
505
    RETURN_IF_EMPTY_HANDLE(isolate,
506
                           JSObject::DeepWalk(boilerplate, &creation_context));
507
    creation_context.ExitScope(site, boilerplate);
508

    
509
    // Update the functions literal and return the boilerplate.
510
    literals->set(literals_index, *site);
511
  } else {
512
    site = Handle<AllocationSite>::cast(literal_site);
513
    boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
514
                                   isolate);
515
  }
516

    
517
  AllocationSiteUsageContext usage_context(isolate, site, true);
518
  usage_context.EnterNewScope();
519
  Handle<Object> copy = JSObject::DeepCopy(boilerplate, &usage_context);
520
  usage_context.ExitScope(site, boilerplate);
521
  RETURN_IF_EMPTY_HANDLE(isolate, copy);
522
  return *copy;
523
}
524

    
525

    
526
static Handle<AllocationSite> GetLiteralAllocationSite(
527
    Isolate* isolate,
528
    Handle<FixedArray> literals,
529
    int literals_index,
530
    Handle<FixedArray> elements) {
531
  // Check if boilerplate exists. If not, create it first.
532
  Handle<Object> literal_site(literals->get(literals_index), isolate);
533
  Handle<AllocationSite> site;
534
  if (*literal_site == isolate->heap()->undefined_value()) {
535
    ASSERT(*elements != isolate->heap()->empty_fixed_array());
536
    Handle<Object> boilerplate =
537
        Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
538
    if (boilerplate.is_null()) return Handle<AllocationSite>::null();
539

    
540
    AllocationSiteCreationContext creation_context(isolate);
541
    site = creation_context.EnterNewScope();
542
    if (JSObject::DeepWalk(Handle<JSObject>::cast(boilerplate),
543
                           &creation_context).is_null()) {
544
      return Handle<AllocationSite>::null();
545
    }
546
    creation_context.ExitScope(site, Handle<JSObject>::cast(boilerplate));
547

    
548
    literals->set(literals_index, *site);
549
  } else {
550
    site = Handle<AllocationSite>::cast(literal_site);
551
  }
552

    
553
  return site;
554
}
555

    
556

    
557
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
558
  HandleScope scope(isolate);
559
  ASSERT(args.length() == 3);
560
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
561
  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
562
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
563

    
564
  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
565
      literals_index, elements);
566
  RETURN_IF_EMPTY_HANDLE(isolate, site);
567

    
568
  Handle<JSObject> boilerplate(JSObject::cast(site->transition_info()));
569
  AllocationSiteUsageContext usage_context(isolate, site, true);
570
  usage_context.EnterNewScope();
571
  Handle<JSObject> copy = JSObject::DeepCopy(boilerplate, &usage_context);
572
  usage_context.ExitScope(site, boilerplate);
573
  RETURN_IF_EMPTY_HANDLE(isolate, copy);
574
  return *copy;
575
}
576

    
577

    
578
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
579
  HandleScope scope(isolate);
580
  ASSERT(args.length() == 3);
581
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
582
  CONVERT_SMI_ARG_CHECKED(literals_index, 1);
583
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
584

    
585
  Handle<AllocationSite> site = GetLiteralAllocationSite(isolate, literals,
586
      literals_index, elements);
587
  RETURN_IF_EMPTY_HANDLE(isolate, site);
588

    
589
  JSObject* boilerplate = JSObject::cast(site->transition_info());
590
  if (boilerplate->elements()->map() ==
591
      isolate->heap()->fixed_cow_array_map()) {
592
    isolate->counters()->cow_arrays_created_runtime()->Increment();
593
  }
594

    
595
  if (AllocationSite::GetMode(boilerplate->GetElementsKind()) ==
596
      TRACK_ALLOCATION_SITE) {
597
    return isolate->heap()->CopyJSObject(boilerplate, *site);
598
  }
599

    
600
  return isolate->heap()->CopyJSObject(boilerplate);
601
}
602

    
603

    
604
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateSymbol) {
605
  HandleScope scope(isolate);
606
  ASSERT(args.length() == 1);
607
  Handle<Object> name(args[0], isolate);
608
  RUNTIME_ASSERT(name->IsString() || name->IsUndefined());
609
  Symbol* symbol;
610
  MaybeObject* maybe = isolate->heap()->AllocateSymbol();
611
  if (!maybe->To(&symbol)) return maybe;
612
  if (name->IsString()) symbol->set_name(*name);
613
  return symbol;
614
}
615

    
616

    
617
RUNTIME_FUNCTION(MaybeObject*, Runtime_SymbolName) {
618
  SealHandleScope shs(isolate);
619
  ASSERT(args.length() == 1);
620
  CONVERT_ARG_CHECKED(Symbol, symbol, 0);
621
  return symbol->name();
622
}
623

    
624

    
625
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
626
  SealHandleScope shs(isolate);
627
  ASSERT(args.length() == 2);
628
  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
629
  Object* prototype = args[1];
630
  Object* used_prototype =
631
      prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
632
  return isolate->heap()->AllocateJSProxy(handler, used_prototype);
633
}
634

    
635

    
636
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
637
  SealHandleScope shs(isolate);
638
  ASSERT(args.length() == 4);
639
  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
640
  Object* call_trap = args[1];
641
  RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
642
  CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
643
  Object* prototype = args[3];
644
  Object* used_prototype =
645
      prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
646
  return isolate->heap()->AllocateJSFunctionProxy(
647
      handler, call_trap, construct_trap, used_prototype);
648
}
649

    
650

    
651
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
652
  SealHandleScope shs(isolate);
653
  ASSERT(args.length() == 1);
654
  Object* obj = args[0];
655
  return isolate->heap()->ToBoolean(obj->IsJSProxy());
656
}
657

    
658

    
659
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
660
  SealHandleScope shs(isolate);
661
  ASSERT(args.length() == 1);
662
  Object* obj = args[0];
663
  return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
664
}
665

    
666

    
667
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
668
  SealHandleScope shs(isolate);
669
  ASSERT(args.length() == 1);
670
  CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
671
  return proxy->handler();
672
}
673

    
674

    
675
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
676
  SealHandleScope shs(isolate);
677
  ASSERT(args.length() == 1);
678
  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
679
  return proxy->call_trap();
680
}
681

    
682

    
683
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
684
  SealHandleScope shs(isolate);
685
  ASSERT(args.length() == 1);
686
  CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
687
  return proxy->construct_trap();
688
}
689

    
690

    
691
RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
692
  HandleScope scope(isolate);
693
  ASSERT(args.length() == 1);
694
  CONVERT_ARG_HANDLE_CHECKED(JSProxy, proxy, 0);
695
  JSProxy::Fix(proxy);
696
  return isolate->heap()->undefined_value();
697
}
698

    
699

    
700
void Runtime::FreeArrayBuffer(Isolate* isolate,
701
                              JSArrayBuffer* phantom_array_buffer) {
702
  if (phantom_array_buffer->is_external()) return;
703

    
704
  size_t allocated_length = NumberToSize(
705
      isolate, phantom_array_buffer->byte_length());
706

    
707
  isolate->heap()->AdjustAmountOfExternalAllocatedMemory(
708
      -static_cast<intptr_t>(allocated_length));
709
  CHECK(V8::ArrayBufferAllocator() != NULL);
710
  V8::ArrayBufferAllocator()->Free(
711
      phantom_array_buffer->backing_store(),
712
      allocated_length);
713
}
714

    
715

    
716
void Runtime::SetupArrayBuffer(Isolate* isolate,
717
                               Handle<JSArrayBuffer> array_buffer,
718
                               bool is_external,
719
                               void* data,
720
                               size_t allocated_length) {
721
  ASSERT(array_buffer->GetInternalFieldCount() ==
722
      v8::ArrayBuffer::kInternalFieldCount);
723
  for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
724
    array_buffer->SetInternalField(i, Smi::FromInt(0));
725
  }
726
  array_buffer->set_backing_store(data);
727
  array_buffer->set_flag(Smi::FromInt(0));
728
  array_buffer->set_is_external(is_external);
729

    
730
  Handle<Object> byte_length =
731
      isolate->factory()->NewNumberFromSize(allocated_length);
732
  CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
733
  array_buffer->set_byte_length(*byte_length);
734

    
735
  array_buffer->set_weak_next(isolate->heap()->array_buffers_list());
736
  isolate->heap()->set_array_buffers_list(*array_buffer);
737
  array_buffer->set_weak_first_view(isolate->heap()->undefined_value());
738
}
739

    
740

    
741
bool Runtime::SetupArrayBufferAllocatingData(
742
    Isolate* isolate,
743
    Handle<JSArrayBuffer> array_buffer,
744
    size_t allocated_length,
745
    bool initialize) {
746
  void* data;
747
  CHECK(V8::ArrayBufferAllocator() != NULL);
748
  if (allocated_length != 0) {
749
    if (initialize) {
750
      data = V8::ArrayBufferAllocator()->Allocate(allocated_length);
751
    } else {
752
      data =
753
        V8::ArrayBufferAllocator()->AllocateUninitialized(allocated_length);
754
    }
755
    if (data == NULL) return false;
756
  } else {
757
    data = NULL;
758
  }
759

    
760
  SetupArrayBuffer(isolate, array_buffer, false, data, allocated_length);
761

    
762
  isolate->heap()->AdjustAmountOfExternalAllocatedMemory(allocated_length);
763

    
764
  return true;
765
}
766

    
767

    
768
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
769
  HandleScope scope(isolate);
770
  ASSERT(args.length() == 2);
771
  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, holder, 0);
772
  CONVERT_ARG_HANDLE_CHECKED(Object, byteLength, 1);
773
  size_t allocated_length;
774
  if (byteLength->IsSmi()) {
775
    allocated_length = Smi::cast(*byteLength)->value();
776
  } else {
777
    ASSERT(byteLength->IsHeapNumber());
778
    double value = HeapNumber::cast(*byteLength)->value();
779

    
780
    ASSERT(value >= 0);
781

    
782
    if (value > std::numeric_limits<size_t>::max()) {
783
      return isolate->Throw(
784
          *isolate->factory()->NewRangeError("invalid_array_buffer_length",
785
            HandleVector<Object>(NULL, 0)));
786
    }
787

    
788
    allocated_length = static_cast<size_t>(value);
789
  }
790

    
791
  if (!Runtime::SetupArrayBufferAllocatingData(isolate,
792
                                               holder, allocated_length)) {
793
      return isolate->Throw(*isolate->factory()->
794
          NewRangeError("invalid_array_buffer_length",
795
            HandleVector<Object>(NULL, 0)));
796
  }
797

    
798
  return *holder;
799
}
800

    
801

    
802
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferGetByteLength) {
803
  SealHandleScope shs(isolate);
804
  ASSERT(args.length() == 1);
805
  CONVERT_ARG_CHECKED(JSArrayBuffer, holder, 0);
806
  return holder->byte_length();
807
}
808

    
809

    
810
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferSliceImpl) {
811
  HandleScope scope(isolate);
812
  ASSERT(args.length() == 3);
813
  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, source, 0);
814
  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, target, 1);
815
  CONVERT_DOUBLE_ARG_CHECKED(first, 2);
816
  size_t start = static_cast<size_t>(first);
817
  size_t target_length = NumberToSize(isolate, target->byte_length());
818

    
819
  if (target_length == 0) return isolate->heap()->undefined_value();
820

    
821
  ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
822
  uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store());
823
  uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
824
  CopyBytes(target_data, source_data + start, target_length);
825
  return isolate->heap()->undefined_value();
826
}
827

    
828

    
829
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferIsView) {
830
  HandleScope scope(isolate);
831
  ASSERT(args.length() == 1);
832
  CONVERT_ARG_CHECKED(Object, object, 0);
833
  return object->IsJSArrayBufferView()
834
    ? isolate->heap()->true_value()
835
    : isolate->heap()->false_value();
836
}
837

    
838

    
839
enum TypedArrayId {
840
  // arrayIds below should be synchromized with typedarray.js natives.
841
  ARRAY_ID_UINT8 = 1,
842
  ARRAY_ID_INT8 = 2,
843
  ARRAY_ID_UINT16 = 3,
844
  ARRAY_ID_INT16 = 4,
845
  ARRAY_ID_UINT32 = 5,
846
  ARRAY_ID_INT32 = 6,
847
  ARRAY_ID_FLOAT32 = 7,
848
  ARRAY_ID_FLOAT64 = 8,
849
  ARRAY_ID_UINT8C = 9
850
};
851

    
852
static void ArrayIdToTypeAndSize(
853
    int arrayId, ExternalArrayType* array_type, size_t* element_size) {
854
  switch (arrayId) {
855
    case ARRAY_ID_UINT8:
856
      *array_type = kExternalUnsignedByteArray;
857
      *element_size = 1;
858
      break;
859
    case ARRAY_ID_INT8:
860
      *array_type = kExternalByteArray;
861
      *element_size = 1;
862
      break;
863
    case ARRAY_ID_UINT16:
864
      *array_type = kExternalUnsignedShortArray;
865
      *element_size = 2;
866
      break;
867
    case ARRAY_ID_INT16:
868
      *array_type = kExternalShortArray;
869
      *element_size = 2;
870
      break;
871
    case ARRAY_ID_UINT32:
872
      *array_type = kExternalUnsignedIntArray;
873
      *element_size = 4;
874
      break;
875
    case ARRAY_ID_INT32:
876
      *array_type = kExternalIntArray;
877
      *element_size = 4;
878
      break;
879
    case ARRAY_ID_FLOAT32:
880
      *array_type = kExternalFloatArray;
881
      *element_size = 4;
882
      break;
883
    case ARRAY_ID_FLOAT64:
884
      *array_type = kExternalDoubleArray;
885
      *element_size = 8;
886
      break;
887
    case ARRAY_ID_UINT8C:
888
      *array_type = kExternalPixelArray;
889
      *element_size = 1;
890
      break;
891
    default:
892
      UNREACHABLE();
893
  }
894
}
895

    
896

    
897
RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitialize) {
898
  HandleScope scope(isolate);
899
  ASSERT(args.length() == 5);
900
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
901
  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
902
  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 2);
903
  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset_object, 3);
904
  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length_object, 4);
905

    
906
  ASSERT(holder->GetInternalFieldCount() ==
907
      v8::ArrayBufferView::kInternalFieldCount);
908
  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
909
    holder->SetInternalField(i, Smi::FromInt(0));
910
  }
911

    
912
  ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
913
  size_t element_size = 1;  // Bogus initialization.
914
  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
915

    
916
  holder->set_buffer(*buffer);
917
  holder->set_byte_offset(*byte_offset_object);
918
  holder->set_byte_length(*byte_length_object);
919

    
920
  size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
921
  size_t byte_length = NumberToSize(isolate, *byte_length_object);
922
  ASSERT(byte_length % element_size == 0);
923
  size_t length = byte_length / element_size;
924

    
925
  Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(length);
926
  holder->set_length(*length_obj);
927
  holder->set_weak_next(buffer->weak_first_view());
928
  buffer->set_weak_first_view(*holder);
929

    
930
  Handle<ExternalArray> elements =
931
      isolate->factory()->NewExternalArray(
932
          static_cast<int>(length), array_type,
933
          static_cast<uint8_t*>(buffer->backing_store()) + byte_offset);
934
  holder->set_elements(*elements);
935
  return isolate->heap()->undefined_value();
936
}
937

    
938

    
939
// Initializes a typed array from an array-like object.
940
// If an array-like object happens to be a typed array of the same type,
941
// initializes backing store using memove.
942
//
943
// Returns true if backing store was initialized or false otherwise.
944
RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayInitializeFromArrayLike) {
945
  HandleScope scope(isolate);
946
  ASSERT(args.length() == 4);
947
  CONVERT_ARG_HANDLE_CHECKED(JSTypedArray, holder, 0);
948
  CONVERT_SMI_ARG_CHECKED(arrayId, 1);
949
  CONVERT_ARG_HANDLE_CHECKED(Object, source, 2);
950
  CONVERT_ARG_HANDLE_CHECKED(Object, length_obj, 3);
951

    
952
  ASSERT(holder->GetInternalFieldCount() ==
953
      v8::ArrayBufferView::kInternalFieldCount);
954
  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
955
    holder->SetInternalField(i, Smi::FromInt(0));
956
  }
957

    
958
  ExternalArrayType array_type = kExternalByteArray;  // Bogus initialization.
959
  size_t element_size = 1;  // Bogus initialization.
960
  ArrayIdToTypeAndSize(arrayId, &array_type, &element_size);
961

    
962
  Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
963
  size_t length = NumberToSize(isolate, *length_obj);
964
  size_t byte_length = length * element_size;
965
  if (byte_length < length) {  // Overflow
966
    return isolate->Throw(*isolate->factory()->
967
          NewRangeError("invalid_array_buffer_length",
968
            HandleVector<Object>(NULL, 0)));
969
  }
970

    
971
  // NOTE: not initializing backing store.
972
  // We assume that the caller of this function will initialize holder
973
  // with the loop
974
  //      for(i = 0; i < length; i++) { holder[i] = source[i]; }
975
  // We assume that the caller of this function is always a typed array
976
  // constructor.
977
  // If source is a typed array, this loop will always run to completion,
978
  // so we are sure that the backing store will be initialized.
979
  // Otherwise, the indexing operation might throw, so the loop will not
980
  // run to completion and the typed array might remain partly initialized.
981
  // However we further assume that the caller of this function is a typed array
982
  // constructor, and the exception will propagate out of the constructor,
983
  // therefore uninitialized memory will not be accessible by a user program.
984
  //
985
  // TODO(dslomov): revise this once we support subclassing.
986

    
987
  if (!Runtime::SetupArrayBufferAllocatingData(
988
        isolate, buffer, byte_length, false)) {
989
    return isolate->Throw(*isolate->factory()->
990
          NewRangeError("invalid_array_buffer_length",
991
            HandleVector<Object>(NULL, 0)));
992
  }
993

    
994
  holder->set_buffer(*buffer);
995
  holder->set_byte_offset(Smi::FromInt(0));
996
  Handle<Object> byte_length_obj(
997
      isolate->factory()->NewNumberFromSize(byte_length));
998
  holder->set_byte_length(*byte_length_obj);
999
  holder->set_length(*length_obj);
1000
  holder->set_weak_next(buffer->weak_first_view());
1001
  buffer->set_weak_first_view(*holder);
1002

    
1003
  Handle<ExternalArray> elements =
1004
      isolate->factory()->NewExternalArray(
1005
          static_cast<int>(length), array_type,
1006
          static_cast<uint8_t*>(buffer->backing_store()));
1007
  holder->set_elements(*elements);
1008

    
1009
  if (source->IsJSTypedArray()) {
1010
    Handle<JSTypedArray> typed_array(JSTypedArray::cast(*source));
1011

    
1012
    if (typed_array->type() == holder->type()) {
1013
      uint8_t* backing_store =
1014
        static_cast<uint8_t*>(
1015
          JSArrayBuffer::cast(typed_array->buffer())->backing_store());
1016
      size_t source_byte_offset =
1017
          NumberToSize(isolate, typed_array->byte_offset());
1018
      memcpy(
1019
          buffer->backing_store(),
1020
          backing_store + source_byte_offset,
1021
          byte_length);
1022
      return *isolate->factory()->true_value();
1023
    } else {
1024
      return *isolate->factory()->false_value();
1025
    }
1026
  }
1027

    
1028
  return *isolate->factory()->false_value();
1029
}
1030

    
1031

    
1032
#define TYPED_ARRAY_GETTER(getter, accessor) \
1033
  RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArrayGet##getter) {             \
1034
    HandleScope scope(isolate);                                               \
1035
    ASSERT(args.length() == 1);                                               \
1036
    CONVERT_ARG_HANDLE_CHECKED(Object, holder, 0);                            \
1037
    if (!holder->IsJSTypedArray())                                            \
1038
      return isolate->Throw(*isolate->factory()->NewTypeError(                \
1039
          "not_typed_array", HandleVector<Object>(NULL, 0)));                 \
1040
    Handle<JSTypedArray> typed_array(JSTypedArray::cast(*holder));            \
1041
    return typed_array->accessor();                                           \
1042
  }
1043

    
1044
TYPED_ARRAY_GETTER(Buffer, buffer)
1045
TYPED_ARRAY_GETTER(ByteLength, byte_length)
1046
TYPED_ARRAY_GETTER(ByteOffset, byte_offset)
1047
TYPED_ARRAY_GETTER(Length, length)
1048

    
1049
#undef TYPED_ARRAY_GETTER
1050

    
1051
// Return codes for Runtime_TypedArraySetFastCases.
1052
// Should be synchronized with typedarray.js natives.
1053
enum TypedArraySetResultCodes {
1054
  // Set from typed array of the same type.
1055
  // This is processed by TypedArraySetFastCases
1056
  TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE = 0,
1057
  // Set from typed array of the different type, overlapping in memory.
1058
  TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING = 1,
1059
  // Set from typed array of the different type, non-overlapping.
1060
  TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING = 2,
1061
  // Set from non-typed array.
1062
  TYPED_ARRAY_SET_NON_TYPED_ARRAY = 3
1063
};
1064

    
1065

    
1066
RUNTIME_FUNCTION(MaybeObject*, Runtime_TypedArraySetFastCases) {
1067
  HandleScope scope(isolate);
1068
  CONVERT_ARG_HANDLE_CHECKED(Object, target_obj, 0);
1069
  CONVERT_ARG_HANDLE_CHECKED(Object, source_obj, 1);
1070
  CONVERT_ARG_HANDLE_CHECKED(Object, offset_obj, 2);
1071

    
1072
  if (!target_obj->IsJSTypedArray())
1073
    return isolate->Throw(*isolate->factory()->NewTypeError(
1074
        "not_typed_array", HandleVector<Object>(NULL, 0)));
1075

    
1076
  if (!source_obj->IsJSTypedArray())
1077
    return Smi::FromInt(TYPED_ARRAY_SET_NON_TYPED_ARRAY);
1078

    
1079
  Handle<JSTypedArray> target(JSTypedArray::cast(*target_obj));
1080
  Handle<JSTypedArray> source(JSTypedArray::cast(*source_obj));
1081
  size_t offset = NumberToSize(isolate, *offset_obj);
1082
  size_t target_length = NumberToSize(isolate, target->length());
1083
  size_t source_length = NumberToSize(isolate, source->length());
1084
  size_t target_byte_length = NumberToSize(isolate, target->byte_length());
1085
  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
1086
  if (offset > target_length ||
1087
      offset + source_length > target_length ||
1088
      offset + source_length < offset)  // overflow
1089
    return isolate->Throw(*isolate->factory()->NewRangeError(
1090
          "typed_array_set_source_too_large", HandleVector<Object>(NULL, 0)));
1091

    
1092
  size_t target_offset = NumberToSize(isolate, target->byte_offset());
1093
  size_t source_offset = NumberToSize(isolate, source->byte_offset());
1094
  uint8_t* target_base =
1095
      static_cast<uint8_t*>(
1096
        JSArrayBuffer::cast(target->buffer())->backing_store()) + target_offset;
1097
  uint8_t* source_base =
1098
      static_cast<uint8_t*>(
1099
        JSArrayBuffer::cast(source->buffer())->backing_store()) + source_offset;
1100

    
1101
  // Typed arrays of the same type: use memmove.
1102
  if (target->type() == source->type()) {
1103
    memmove(target_base + offset * target->element_size(),
1104
        source_base, source_byte_length);
1105
    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_SAME_TYPE);
1106
  }
1107

    
1108
  // Typed arrays of different types over the same backing store
1109
  if ((source_base <= target_base &&
1110
        source_base + source_byte_length > target_base) ||
1111
      (target_base <= source_base &&
1112
        target_base + target_byte_length > source_base)) {
1113
    // We do not support overlapping ArrayBuffers
1114
    ASSERT(
1115
      JSArrayBuffer::cast(target->buffer())->backing_store() ==
1116
      JSArrayBuffer::cast(source->buffer())->backing_store());
1117
    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_OVERLAPPING);
1118
  } else {  // Non-overlapping typed arrays
1119
    return Smi::FromInt(TYPED_ARRAY_SET_TYPED_ARRAY_NONOVERLAPPING);
1120
  }
1121
}
1122

    
1123

    
1124
RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewInitialize) {
1125
  HandleScope scope(isolate);
1126
  ASSERT(args.length() == 4);
1127
  CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);
1128
  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, buffer, 1);
1129
  CONVERT_ARG_HANDLE_CHECKED(Object, byte_offset, 2);
1130
  CONVERT_ARG_HANDLE_CHECKED(Object, byte_length, 3);
1131

    
1132
  ASSERT(holder->GetInternalFieldCount() ==
1133
      v8::ArrayBufferView::kInternalFieldCount);
1134
  for (int i = 0; i < v8::ArrayBufferView::kInternalFieldCount; i++) {
1135
    holder->SetInternalField(i, Smi::FromInt(0));
1136
  }
1137

    
1138
  holder->set_buffer(*buffer);
1139
  ASSERT(byte_offset->IsNumber());
1140
  ASSERT(
1141
      NumberToSize(isolate, buffer->byte_length()) >=
1142
        NumberToSize(isolate, *byte_offset)
1143
        + NumberToSize(isolate, *byte_length));
1144
  holder->set_byte_offset(*byte_offset);
1145
  ASSERT(byte_length->IsNumber());
1146
  holder->set_byte_length(*byte_length);
1147

    
1148
  holder->set_weak_next(buffer->weak_first_view());
1149
  buffer->set_weak_first_view(*holder);
1150

    
1151
  return isolate->heap()->undefined_value();
1152
}
1153

    
1154

    
1155
RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetBuffer) {
1156
  HandleScope scope(isolate);
1157
  ASSERT(args.length() == 1);
1158
  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1159
  return data_view->buffer();
1160
}
1161

    
1162

    
1163
RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteOffset) {
1164
  HandleScope scope(isolate);
1165
  ASSERT(args.length() == 1);
1166
  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1167
  return data_view->byte_offset();
1168
}
1169

    
1170

    
1171
RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGetByteLength) {
1172
  HandleScope scope(isolate);
1173
  ASSERT(args.length() == 1);
1174
  CONVERT_ARG_HANDLE_CHECKED(JSDataView, data_view, 0);
1175
  return data_view->byte_length();
1176
}
1177

    
1178

    
1179
inline static bool NeedToFlipBytes(bool is_little_endian) {
1180
#ifdef V8_TARGET_LITTLE_ENDIAN
1181
  return !is_little_endian;
1182
#else
1183
  return is_little_endian;
1184
#endif
1185
}
1186

    
1187

    
1188
template<int n>
1189
inline void CopyBytes(uint8_t* target, uint8_t* source) {
1190
  for (int i = 0; i < n; i++) {
1191
    *(target++) = *(source++);
1192
  }
1193
}
1194

    
1195

    
1196
template<int n>
1197
inline void FlipBytes(uint8_t* target, uint8_t* source) {
1198
  source = source + (n-1);
1199
  for (int i = 0; i < n; i++) {
1200
    *(target++) = *(source--);
1201
  }
1202
}
1203

    
1204

    
1205
template<typename T>
1206
inline static bool DataViewGetValue(
1207
    Isolate* isolate,
1208
    Handle<JSDataView> data_view,
1209
    Handle<Object> byte_offset_obj,
1210
    bool is_little_endian,
1211
    T* result) {
1212
  size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
1213
  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1214

    
1215
  size_t data_view_byte_offset =
1216
      NumberToSize(isolate, data_view->byte_offset());
1217
  size_t data_view_byte_length =
1218
      NumberToSize(isolate, data_view->byte_length());
1219
  if (byte_offset + sizeof(T) > data_view_byte_length ||
1220
      byte_offset + sizeof(T) < byte_offset)  {  // overflow
1221
    return false;
1222
  }
1223

    
1224
  union Value {
1225
    T data;
1226
    uint8_t bytes[sizeof(T)];
1227
  };
1228

    
1229
  Value value;
1230
  size_t buffer_offset = data_view_byte_offset + byte_offset;
1231
  ASSERT(
1232
      NumberToSize(isolate, buffer->byte_length())
1233
      >= buffer_offset + sizeof(T));
1234
  uint8_t* source =
1235
        static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1236
  if (NeedToFlipBytes(is_little_endian)) {
1237
    FlipBytes<sizeof(T)>(value.bytes, source);
1238
  } else {
1239
    CopyBytes<sizeof(T)>(value.bytes, source);
1240
  }
1241
  *result = value.data;
1242
  return true;
1243
}
1244

    
1245

    
1246
template<typename T>
1247
static bool DataViewSetValue(
1248
    Isolate* isolate,
1249
    Handle<JSDataView> data_view,
1250
    Handle<Object> byte_offset_obj,
1251
    bool is_little_endian,
1252
    T data) {
1253
  size_t byte_offset = NumberToSize(isolate, *byte_offset_obj);
1254
  Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(data_view->buffer()));
1255

    
1256
  size_t data_view_byte_offset =
1257
      NumberToSize(isolate, data_view->byte_offset());
1258
  size_t data_view_byte_length =
1259
      NumberToSize(isolate, data_view->byte_length());
1260
  if (byte_offset + sizeof(T) > data_view_byte_length ||
1261
      byte_offset + sizeof(T) < byte_offset)  {  // overflow
1262
    return false;
1263
  }
1264

    
1265
  union Value {
1266
    T data;
1267
    uint8_t bytes[sizeof(T)];
1268
  };
1269

    
1270
  Value value;
1271
  value.data = data;
1272
  size_t buffer_offset = data_view_byte_offset + byte_offset;
1273
  ASSERT(
1274
      NumberToSize(isolate, buffer->byte_length())
1275
      >= buffer_offset + sizeof(T));
1276
  uint8_t* target =
1277
        static_cast<uint8_t*>(buffer->backing_store()) + buffer_offset;
1278
  if (NeedToFlipBytes(is_little_endian)) {
1279
    FlipBytes<sizeof(T)>(target, value.bytes);
1280
  } else {
1281
    CopyBytes<sizeof(T)>(target, value.bytes);
1282
  }
1283
  return true;
1284
}
1285

    
1286

    
1287
#define DATA_VIEW_GETTER(TypeName, Type, Converter)                           \
1288
  RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewGet##TypeName) {             \
1289
    HandleScope scope(isolate);                                               \
1290
    ASSERT(args.length() == 3);                                               \
1291
    CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1292
    CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1293
    CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 2);                         \
1294
    Type result;                                                              \
1295
    if (DataViewGetValue(                                                     \
1296
          isolate, holder, offset, is_little_endian, &result)) {              \
1297
      return isolate->heap()->Converter(result);                              \
1298
    } else {                                                                  \
1299
      return isolate->Throw(*isolate->factory()->NewRangeError(               \
1300
          "invalid_data_view_accessor_offset",                                \
1301
          HandleVector<Object>(NULL, 0)));                                    \
1302
    }                                                                         \
1303
  }
1304

    
1305
DATA_VIEW_GETTER(Uint8, uint8_t, NumberFromUint32)
1306
DATA_VIEW_GETTER(Int8, int8_t, NumberFromInt32)
1307
DATA_VIEW_GETTER(Uint16, uint16_t, NumberFromUint32)
1308
DATA_VIEW_GETTER(Int16, int16_t, NumberFromInt32)
1309
DATA_VIEW_GETTER(Uint32, uint32_t, NumberFromUint32)
1310
DATA_VIEW_GETTER(Int32, int32_t, NumberFromInt32)
1311
DATA_VIEW_GETTER(Float32, float, NumberFromDouble)
1312
DATA_VIEW_GETTER(Float64, double, NumberFromDouble)
1313

    
1314
#undef DATA_VIEW_GETTER
1315

    
1316

    
1317
template <typename T>
1318
static T DataViewConvertValue(double value);
1319

    
1320

    
1321
template <>
1322
int8_t DataViewConvertValue<int8_t>(double value) {
1323
  return static_cast<int8_t>(DoubleToInt32(value));
1324
}
1325

    
1326

    
1327
template <>
1328
int16_t DataViewConvertValue<int16_t>(double value) {
1329
  return static_cast<int16_t>(DoubleToInt32(value));
1330
}
1331

    
1332

    
1333
template <>
1334
int32_t DataViewConvertValue<int32_t>(double value) {
1335
  return DoubleToInt32(value);
1336
}
1337

    
1338

    
1339
template <>
1340
uint8_t DataViewConvertValue<uint8_t>(double value) {
1341
  return static_cast<uint8_t>(DoubleToUint32(value));
1342
}
1343

    
1344

    
1345
template <>
1346
uint16_t DataViewConvertValue<uint16_t>(double value) {
1347
  return static_cast<uint16_t>(DoubleToUint32(value));
1348
}
1349

    
1350

    
1351
template <>
1352
uint32_t DataViewConvertValue<uint32_t>(double value) {
1353
  return DoubleToUint32(value);
1354
}
1355

    
1356

    
1357
template <>
1358
float DataViewConvertValue<float>(double value) {
1359
  return static_cast<float>(value);
1360
}
1361

    
1362

    
1363
template <>
1364
double DataViewConvertValue<double>(double value) {
1365
  return value;
1366
}
1367

    
1368

    
1369
#define DATA_VIEW_SETTER(TypeName, Type)                                      \
1370
  RUNTIME_FUNCTION(MaybeObject*, Runtime_DataViewSet##TypeName) {             \
1371
    HandleScope scope(isolate);                                               \
1372
    ASSERT(args.length() == 4);                                               \
1373
    CONVERT_ARG_HANDLE_CHECKED(JSDataView, holder, 0);                        \
1374
    CONVERT_ARG_HANDLE_CHECKED(Object, offset, 1);                            \
1375
    CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);                             \
1376
    CONVERT_BOOLEAN_ARG_CHECKED(is_little_endian, 3);                         \
1377
    Type v = DataViewConvertValue<Type>(value->Number());                     \
1378
    if (DataViewSetValue(                                                     \
1379
          isolate, holder, offset, is_little_endian, v)) {                    \
1380
      return isolate->heap()->undefined_value();                              \
1381
    } else {                                                                  \
1382
      return isolate->Throw(*isolate->factory()->NewRangeError(               \
1383
          "invalid_data_view_accessor_offset",                                \
1384
          HandleVector<Object>(NULL, 0)));                                    \
1385
    }                                                                         \
1386
  }
1387

    
1388
DATA_VIEW_SETTER(Uint8, uint8_t)
1389
DATA_VIEW_SETTER(Int8, int8_t)
1390
DATA_VIEW_SETTER(Uint16, uint16_t)
1391
DATA_VIEW_SETTER(Int16, int16_t)
1392
DATA_VIEW_SETTER(Uint32, uint32_t)
1393
DATA_VIEW_SETTER(Int32, int32_t)
1394
DATA_VIEW_SETTER(Float32, float)
1395
DATA_VIEW_SETTER(Float64, double)
1396

    
1397
#undef DATA_VIEW_SETTER
1398

    
1399

    
1400
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
1401
  HandleScope scope(isolate);
1402
  ASSERT(args.length() == 1);
1403
  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1404
  Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
1405
  holder->set_table(*table);
1406
  return *holder;
1407
}
1408

    
1409

    
1410
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
1411
  HandleScope scope(isolate);
1412
  ASSERT(args.length() == 2);
1413
  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1414
  Handle<Object> key(args[1], isolate);
1415
  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1416
  table = ObjectHashSetAdd(table, key);
1417
  holder->set_table(*table);
1418
  return isolate->heap()->undefined_value();
1419
}
1420

    
1421

    
1422
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
1423
  HandleScope scope(isolate);
1424
  ASSERT(args.length() == 2);
1425
  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1426
  Handle<Object> key(args[1], isolate);
1427
  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1428
  return isolate->heap()->ToBoolean(table->Contains(*key));
1429
}
1430

    
1431

    
1432
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
1433
  HandleScope scope(isolate);
1434
  ASSERT(args.length() == 2);
1435
  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1436
  Handle<Object> key(args[1], isolate);
1437
  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1438
  table = ObjectHashSetRemove(table, key);
1439
  holder->set_table(*table);
1440
  return isolate->heap()->undefined_value();
1441
}
1442

    
1443

    
1444
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetGetSize) {
1445
  HandleScope scope(isolate);
1446
  ASSERT(args.length() == 1);
1447
  CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
1448
  Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
1449
  return Smi::FromInt(table->NumberOfElements());
1450
}
1451

    
1452

    
1453
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
1454
  HandleScope scope(isolate);
1455
  ASSERT(args.length() == 1);
1456
  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1457
  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1458
  holder->set_table(*table);
1459
  return *holder;
1460
}
1461

    
1462

    
1463
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
1464
  HandleScope scope(isolate);
1465
  ASSERT(args.length() == 2);
1466
  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1467
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1468
  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1469
  Handle<Object> lookup(table->Lookup(*key), isolate);
1470
  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1471
}
1472

    
1473

    
1474
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
1475
  HandleScope scope(isolate);
1476
  ASSERT(args.length() == 2);
1477
  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1478
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1479
  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1480
  Handle<Object> lookup(table->Lookup(*key), isolate);
1481
  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1482
}
1483

    
1484

    
1485
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
1486
  HandleScope scope(isolate);
1487
  ASSERT(args.length() == 2);
1488
  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1489
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1490
  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1491
  Handle<Object> lookup(table->Lookup(*key), isolate);
1492
  Handle<ObjectHashTable> new_table =
1493
      PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
1494
  holder->set_table(*new_table);
1495
  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1496
}
1497

    
1498

    
1499
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
1500
  HandleScope scope(isolate);
1501
  ASSERT(args.length() == 3);
1502
  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1503
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1504
  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
1505
  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1506
  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
1507
  holder->set_table(*new_table);
1508
  return isolate->heap()->undefined_value();
1509
}
1510

    
1511

    
1512
RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGetSize) {
1513
  HandleScope scope(isolate);
1514
  ASSERT(args.length() == 1);
1515
  CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
1516
  Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
1517
  return Smi::FromInt(table->NumberOfElements());
1518
}
1519

    
1520

    
1521
static JSWeakCollection* WeakCollectionInitialize(Isolate* isolate,
1522
    Handle<JSWeakCollection> weak_collection) {
1523
  ASSERT(weak_collection->map()->inobject_properties() == 0);
1524
  Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
1525
  weak_collection->set_table(*table);
1526
  weak_collection->set_next(Smi::FromInt(0));
1527
  return *weak_collection;
1528
}
1529

    
1530

    
1531
RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionInitialize) {
1532
  HandleScope scope(isolate);
1533
  ASSERT(args.length() == 1);
1534
  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1535
  return WeakCollectionInitialize(isolate, weak_collection);
1536
}
1537

    
1538

    
1539
RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionGet) {
1540
  HandleScope scope(isolate);
1541
  ASSERT(args.length() == 2);
1542
  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1543
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1544
  Handle<ObjectHashTable> table(
1545
      ObjectHashTable::cast(weak_collection->table()));
1546
  Handle<Object> lookup(table->Lookup(*key), isolate);
1547
  return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
1548
}
1549

    
1550

    
1551
RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionHas) {
1552
  HandleScope scope(isolate);
1553
  ASSERT(args.length() == 2);
1554
  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1555
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1556
  Handle<ObjectHashTable> table(
1557
      ObjectHashTable::cast(weak_collection->table()));
1558
  Handle<Object> lookup(table->Lookup(*key), isolate);
1559
  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1560
}
1561

    
1562

    
1563
RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionDelete) {
1564
  HandleScope scope(isolate);
1565
  ASSERT(args.length() == 2);
1566
  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1567
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1568
  Handle<ObjectHashTable> table(ObjectHashTable::cast(
1569
      weak_collection->table()));
1570
  Handle<Object> lookup(table->Lookup(*key), isolate);
1571
  Handle<ObjectHashTable> new_table =
1572
      PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
1573
  weak_collection->set_table(*new_table);
1574
  return isolate->heap()->ToBoolean(!lookup->IsTheHole());
1575
}
1576

    
1577

    
1578
RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakCollectionSet) {
1579
  HandleScope scope(isolate);
1580
  ASSERT(args.length() == 3);
1581
  CONVERT_ARG_HANDLE_CHECKED(JSWeakCollection, weak_collection, 0);
1582
  CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
1583
  Handle<Object> value(args[2], isolate);
1584
  Handle<ObjectHashTable> table(
1585
      ObjectHashTable::cast(weak_collection->table()));
1586
  Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
1587
  weak_collection->set_table(*new_table);
1588
  return isolate->heap()->undefined_value();
1589
}
1590

    
1591

    
1592
RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
1593
  SealHandleScope shs(isolate);
1594
  ASSERT(args.length() == 1);
1595
  Object* obj = args[0];
1596
  if (!obj->IsJSObject()) return isolate->heap()->null_value();
1597
  return JSObject::cast(obj)->class_name();
1598
}
1599

    
1600

    
1601
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
1602
  HandleScope scope(isolate);
1603
  ASSERT(args.length() == 1);
1604
  CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
1605
  // We don't expect access checks to be needed on JSProxy objects.
1606
  ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
1607
  do {
1608
    if (obj->IsAccessCheckNeeded() &&
1609
        !isolate->MayNamedAccessWrapper(Handle<JSObject>::cast(obj),
1610
                                        isolate->factory()->proto_string(),
1611
                                        v8::ACCESS_GET)) {
1612
      isolate->ReportFailedAccessCheck(JSObject::cast(*obj), v8::ACCESS_GET);
1613
      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
1614
      return isolate->heap()->undefined_value();
1615
    }
1616
    obj = handle(obj->GetPrototype(isolate), isolate);
1617
  } while (obj->IsJSObject() &&
1618
           JSObject::cast(*obj)->map()->is_hidden_prototype());
1619
  return *obj;
1620
}
1621

    
1622

    
1623
static inline Object* GetPrototypeSkipHiddenPrototypes(Isolate* isolate,
1624
                                                       Object* receiver) {
1625
  Object* current = receiver->GetPrototype(isolate);
1626
  while (current->IsJSObject() &&
1627
         JSObject::cast(current)->map()->is_hidden_prototype()) {
1628
    current = current->GetPrototype(isolate);
1629
  }
1630
  return current;
1631
}
1632

    
1633

    
1634
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetPrototype) {
1635
  HandleScope scope(isolate);
1636
  ASSERT(args.length() == 2);
1637
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1638
  CONVERT_ARG_HANDLE_CHECKED(Object, prototype, 1);
1639
  if (FLAG_harmony_observation && obj->map()->is_observed()) {
1640
    Handle<Object> old_value(
1641
        GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1642

    
1643
    Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1644
    RETURN_IF_EMPTY_HANDLE(isolate, result);
1645

    
1646
    Handle<Object> new_value(
1647
        GetPrototypeSkipHiddenPrototypes(isolate, *obj), isolate);
1648
    if (!new_value->SameValue(*old_value)) {
1649
      JSObject::EnqueueChangeRecord(obj, "prototype",
1650
                                    isolate->factory()->proto_string(),
1651
                                    old_value);
1652
    }
1653
    return *result;
1654
  }
1655
  Handle<Object> result = JSObject::SetPrototype(obj, prototype, true);
1656
  RETURN_IF_EMPTY_HANDLE(isolate, result);
1657
  return *result;
1658
}
1659

    
1660

    
1661
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
1662
  SealHandleScope shs(isolate);
1663
  ASSERT(args.length() == 2);
1664
  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
1665
  Object* O = args[0];
1666
  Object* V = args[1];
1667
  while (true) {
1668
    Object* prototype = V->GetPrototype(isolate);
1669
    if (prototype->IsNull()) return isolate->heap()->false_value();
1670
    if (O == prototype) return isolate->heap()->true_value();
1671
    V = prototype;
1672
  }
1673
}
1674

    
1675

    
1676
static bool CheckAccessException(Object* callback,
1677
                                 v8::AccessType access_type) {
1678
  DisallowHeapAllocation no_gc;
1679
  if (callback->IsAccessorInfo()) {
1680
    AccessorInfo* info = AccessorInfo::cast(callback);
1681
    return
1682
        (access_type == v8::ACCESS_HAS &&
1683
           (info->all_can_read() || info->all_can_write())) ||
1684
        (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1685
        (access_type == v8::ACCESS_SET && info->all_can_write());
1686
  }
1687
  if (callback->IsAccessorPair()) {
1688
    AccessorPair* info = AccessorPair::cast(callback);
1689
    return
1690
        (access_type == v8::ACCESS_HAS &&
1691
           (info->all_can_read() || info->all_can_write())) ||
1692
        (access_type == v8::ACCESS_GET && info->all_can_read()) ||
1693
        (access_type == v8::ACCESS_SET && info->all_can_write());
1694
  }
1695
  return false;
1696
}
1697

    
1698

    
1699
template<class Key>
1700
static bool CheckGenericAccess(
1701
    Handle<JSObject> receiver,
1702
    Handle<JSObject> holder,
1703
    Key key,
1704
    v8::AccessType access_type,
1705
    bool (Isolate::*mayAccess)(Handle<JSObject>, Key, v8::AccessType)) {
1706
  Isolate* isolate = receiver->GetIsolate();
1707
  for (Handle<JSObject> current = receiver;
1708
       true;
1709
       current = handle(JSObject::cast(current->GetPrototype()), isolate)) {
1710
    if (current->IsAccessCheckNeeded() &&
1711
        !(isolate->*mayAccess)(current, key, access_type)) {
1712
      return false;
1713
    }
1714
    if (current.is_identical_to(holder)) break;
1715
  }
1716
  return true;
1717
}
1718

    
1719

    
1720
enum AccessCheckResult {
1721
  ACCESS_FORBIDDEN,
1722
  ACCESS_ALLOWED,
1723
  ACCESS_ABSENT
1724
};
1725

    
1726

    
1727
static AccessCheckResult CheckPropertyAccess(Handle<JSObject> obj,
1728
                                             Handle<Name> name,
1729
                                             v8::AccessType access_type) {
1730
  uint32_t index;
1731
  if (name->AsArrayIndex(&index)) {
1732
    // TODO(1095): we should traverse hidden prototype hierachy as well.
1733
    if (CheckGenericAccess(
1734
            obj, obj, index, access_type, &Isolate::MayIndexedAccessWrapper)) {
1735
      return ACCESS_ALLOWED;
1736
    }
1737

    
1738
    obj->GetIsolate()->ReportFailedAccessCheck(*obj, access_type);
1739
    return ACCESS_FORBIDDEN;
1740
  }
1741

    
1742
  Isolate* isolate = obj->GetIsolate();
1743
  LookupResult lookup(isolate);
1744
  obj->LocalLookup(*name, &lookup, true);
1745

    
1746
  if (!lookup.IsProperty()) return ACCESS_ABSENT;
1747
  Handle<JSObject> holder(lookup.holder(), isolate);
1748
  if (CheckGenericAccess<Handle<Object> >(
1749
          obj, holder, name, access_type, &Isolate::MayNamedAccessWrapper)) {
1750
    return ACCESS_ALLOWED;
1751
  }
1752

    
1753
  // Access check callback denied the access, but some properties
1754
  // can have a special permissions which override callbacks descision
1755
  // (currently see v8::AccessControl).
1756
  // API callbacks can have per callback access exceptions.
1757
  switch (lookup.type()) {
1758
    case CALLBACKS:
1759
      if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1760
        return ACCESS_ALLOWED;
1761
      }
1762
      break;
1763
    case INTERCEPTOR:
1764
      // If the object has an interceptor, try real named properties.
1765
      // Overwrite the result to fetch the correct property later.
1766
      holder->LookupRealNamedProperty(*name, &lookup);
1767
      if (lookup.IsProperty() && lookup.IsPropertyCallbacks()) {
1768
        if (CheckAccessException(lookup.GetCallbackObject(), access_type)) {
1769
          return ACCESS_ALLOWED;
1770
        }
1771
      }
1772
      break;
1773
    default:
1774
      break;
1775
  }
1776

    
1777
  isolate->ReportFailedAccessCheck(*obj, access_type);
1778
  return ACCESS_FORBIDDEN;
1779
}
1780

    
1781

    
1782
// Enumerator used as indices into the array returned from GetOwnProperty
1783
enum PropertyDescriptorIndices {
1784
  IS_ACCESSOR_INDEX,
1785
  VALUE_INDEX,
1786
  GETTER_INDEX,
1787
  SETTER_INDEX,
1788
  WRITABLE_INDEX,
1789
  ENUMERABLE_INDEX,
1790
  CONFIGURABLE_INDEX,
1791
  DESCRIPTOR_SIZE
1792
};
1793

    
1794

    
1795
static Handle<Object> GetOwnProperty(Isolate* isolate,
1796
                                     Handle<JSObject> obj,
1797
                                     Handle<Name> name) {
1798
  Heap* heap = isolate->heap();
1799
  Factory* factory = isolate->factory();
1800
  // Due to some WebKit tests, we want to make sure that we do not log
1801
  // more than one access failure here.
1802
  AccessCheckResult access_check_result =
1803
      CheckPropertyAccess(obj, name, v8::ACCESS_HAS);
1804
  RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1805
  switch (access_check_result) {
1806
    case ACCESS_FORBIDDEN: return factory->false_value();
1807
    case ACCESS_ALLOWED: break;
1808
    case ACCESS_ABSENT: return factory->undefined_value();
1809
  }
1810

    
1811
  PropertyAttributes attrs = obj->GetLocalPropertyAttribute(*name);
1812
  if (attrs == ABSENT) {
1813
    RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1814
    return factory->undefined_value();
1815
  }
1816
  ASSERT(!isolate->has_scheduled_exception());
1817
  AccessorPair* raw_accessors = obj->GetLocalPropertyAccessorPair(*name);
1818
  Handle<AccessorPair> accessors(raw_accessors, isolate);
1819
  Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1820
  elms->set(ENUMERABLE_INDEX, heap->ToBoolean((attrs & DONT_ENUM) == 0));
1821
  elms->set(CONFIGURABLE_INDEX, heap->ToBoolean((attrs & DONT_DELETE) == 0));
1822
  elms->set(IS_ACCESSOR_INDEX, heap->ToBoolean(raw_accessors != NULL));
1823

    
1824
  if (raw_accessors == NULL) {
1825
    elms->set(WRITABLE_INDEX, heap->ToBoolean((attrs & READ_ONLY) == 0));
1826
    // GetProperty does access check.
1827
    Handle<Object> value = GetProperty(isolate, obj, name);
1828
    RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<Object>::null());
1829
    elms->set(VALUE_INDEX, *value);
1830
  } else {
1831
    // Access checks are performed for both accessors separately.
1832
    // When they fail, the respective field is not set in the descriptor.
1833
    Handle<Object> getter(accessors->GetComponent(ACCESSOR_GETTER), isolate);
1834
    Handle<Object> setter(accessors->GetComponent(ACCESSOR_SETTER), isolate);
1835

    
1836
    if (!getter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_GET)) {
1837
      ASSERT(!isolate->has_scheduled_exception());
1838
      elms->set(GETTER_INDEX, *getter);
1839
    } else {
1840
      RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1841
    }
1842

    
1843
    if (!setter->IsMap() && CheckPropertyAccess(obj, name, v8::ACCESS_SET)) {
1844
      ASSERT(!isolate->has_scheduled_exception());
1845
      elms->set(SETTER_INDEX, *setter);
1846
    } else {
1847
      RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object);
1848
    }
1849
  }
1850

    
1851
  return isolate->factory()->NewJSArrayWithElements(elms);
1852
}
1853

    
1854

    
1855
// Returns an array with the property description:
1856
//  if args[1] is not a property on args[0]
1857
//          returns undefined
1858
//  if args[1] is a data property on args[0]
1859
//         [false, value, Writeable, Enumerable, Configurable]
1860
//  if args[1] is an accessor on args[0]
1861
//         [true, GetFunction, SetFunction, Enumerable, Configurable]
1862
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1863
  HandleScope scope(isolate);
1864
  ASSERT(args.length() == 2);
1865
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1866
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1867
  Handle<Object> result = GetOwnProperty(isolate, obj, name);
1868
  RETURN_IF_EMPTY_HANDLE(isolate, result);
1869
  return *result;
1870
}
1871

    
1872

    
1873
RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1874
  HandleScope scope(isolate);
1875
  ASSERT(args.length() == 1);
1876
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1877
  Handle<Object> result = JSObject::PreventExtensions(obj);
1878
  RETURN_IF_EMPTY_HANDLE(isolate, result);
1879
  return *result;
1880
}
1881

    
1882

    
1883
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1884
  SealHandleScope shs(isolate);
1885
  ASSERT(args.length() == 1);
1886
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
1887
  if (obj->IsJSGlobalProxy()) {
1888
    Object* proto = obj->GetPrototype();
1889
    if (proto->IsNull()) return isolate->heap()->false_value();
1890
    ASSERT(proto->IsJSGlobalObject());
1891
    obj = JSObject::cast(proto);
1892
  }
1893
  return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1894
}
1895

    
1896

    
1897
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1898
  HandleScope scope(isolate);
1899
  ASSERT(args.length() == 3);
1900
  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1901
  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1902
  CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1903
  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
1904
  RETURN_IF_EMPTY_HANDLE(isolate, result);
1905
  return *result;
1906
}
1907

    
1908

    
1909
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1910
  HandleScope scope(isolate);
1911
  ASSERT(args.length() == 1);
1912
  CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1913
  return *isolate->factory()->CreateApiFunction(data);
1914
}
1915

    
1916

    
1917
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1918
  SealHandleScope shs(isolate);
1919
  ASSERT(args.length() == 1);
1920
  Object* arg = args[0];
1921
  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1922
  return isolate->heap()->ToBoolean(result);
1923
}
1924

    
1925

    
1926
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1927
  SealHandleScope shs(isolate);
1928
  ASSERT(args.length() == 2);
1929
  CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1930
  CONVERT_SMI_ARG_CHECKED(index, 1)
1931
  int offset = index * kPointerSize + HeapObject::kHeaderSize;
1932
  InstanceType type = templ->map()->instance_type();
1933
  RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
1934
                 type ==  OBJECT_TEMPLATE_INFO_TYPE);
1935
  RUNTIME_ASSERT(offset > 0);
1936
  if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1937
    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1938
  } else {
1939
    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1940
  }
1941
  return *HeapObject::RawField(templ, offset);
1942
}
1943

    
1944

    
1945
RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1946
  SealHandleScope shs(isolate);
1947
  ASSERT(args.length() == 1);
1948
  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1949
  Map* old_map = object->map();
1950
  bool needs_access_checks = old_map->is_access_check_needed();
1951
  if (needs_access_checks) {
1952
    // Copy map so it won't interfere constructor's initial map.
1953
    Map* new_map;
1954
    MaybeObject* maybe_new_map = old_map->Copy();
1955
    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1956

    
1957
    new_map->set_is_access_check_needed(false);
1958
    object->set_map(new_map);
1959
  }
1960
  return isolate->heap()->ToBoolean(needs_access_checks);
1961
}
1962

    
1963

    
1964
RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1965
  SealHandleScope shs(isolate);
1966
  ASSERT(args.length() == 1);
1967
  CONVERT_ARG_CHECKED(HeapObject, object, 0);
1968
  Map* old_map = object->map();
1969
  if (!old_map->is_access_check_needed()) {
1970
    // Copy map so it won't interfere constructor's initial map.
1971
    Map* new_map;
1972
    MaybeObject* maybe_new_map = old_map->Copy();
1973
    if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1974

    
1975
    new_map->set_is_access_check_needed(true);
1976
    object->set_map(new_map);
1977
  }
1978
  return isolate->heap()->undefined_value();
1979
}
1980

    
1981

    
1982
// Transform getter or setter into something DefineAccessor can handle.
1983
static Handle<Object> InstantiateAccessorComponent(Isolate* isolate,
1984
                                                   Handle<Object> component) {
1985
  if (component->IsUndefined()) return isolate->factory()->null_value();
1986
  Handle<FunctionTemplateInfo> info =
1987
      Handle<FunctionTemplateInfo>::cast(component);
1988
  return Utils::OpenHandle(*Utils::ToLocal(info)->GetFunction());
1989
}
1990

    
1991

    
1992
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAccessorProperty) {
1993
  HandleScope scope(isolate);
1994
  ASSERT(args.length() == 6);
1995
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1996
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
1997
  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
1998
  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
1999
  CONVERT_SMI_ARG_CHECKED(attribute, 4);
2000
  CONVERT_SMI_ARG_CHECKED(access_control, 5);
2001
  JSObject::DefineAccessor(object,
2002
                           name,
2003
                           InstantiateAccessorComponent(isolate, getter),
2004
                           InstantiateAccessorComponent(isolate, setter),
2005
                           static_cast<PropertyAttributes>(attribute),
2006
                           static_cast<v8::AccessControl>(access_control));
2007
  return isolate->heap()->undefined_value();
2008
}
2009

    
2010

    
2011
static Failure* ThrowRedeclarationError(Isolate* isolate,
2012
                                        const char* type,
2013
                                        Handle<String> name) {
2014
  HandleScope scope(isolate);
2015
  Handle<Object> type_handle =
2016
      isolate->factory()->NewStringFromAscii(CStrVector(type));
2017
  Handle<Object> args[2] = { type_handle, name };
2018
  Handle<Object> error =
2019
      isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
2020
  return isolate->Throw(*error);
2021
}
2022

    
2023

    
2024
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
2025
  HandleScope scope(isolate);
2026
  ASSERT(args.length() == 3);
2027
  Handle<GlobalObject> global = Handle<GlobalObject>(
2028
      isolate->context()->global_object());
2029

    
2030
  Handle<Context> context = args.at<Context>(0);
2031
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
2032
  CONVERT_SMI_ARG_CHECKED(flags, 2);
2033

    
2034
  // Traverse the name/value pairs and set the properties.
2035
  int length = pairs->length();
2036
  for (int i = 0; i < length; i += 2) {
2037
    HandleScope scope(isolate);
2038
    Handle<String> name(String::cast(pairs->get(i)));
2039
    Handle<Object> value(pairs->get(i + 1), isolate);
2040

    
2041
    // We have to declare a global const property. To capture we only
2042
    // assign to it when evaluating the assignment for "const x =
2043
    // <expr>" the initial value is the hole.
2044
    bool is_var = value->IsUndefined();
2045
    bool is_const = value->IsTheHole();
2046
    bool is_function = value->IsSharedFunctionInfo();
2047
    ASSERT(is_var + is_const + is_function == 1);
2048

    
2049
    if (is_var || is_const) {
2050
      // Lookup the property in the global object, and don't set the
2051
      // value of the variable if the property is already there.
2052
      // Do the lookup locally only, see ES5 erratum.
2053
      LookupResult lookup(isolate);
2054
      if (FLAG_es52_globals) {
2055
        global->LocalLookup(*name, &lookup, true);
2056
      } else {
2057
        global->Lookup(*name, &lookup);
2058
      }
2059
      if (lookup.IsFound()) {
2060
        // We found an existing property. Unless it was an interceptor
2061
        // that claims the property is absent, skip this declaration.
2062
        if (!lookup.IsInterceptor()) continue;
2063
        PropertyAttributes attributes = global->GetPropertyAttribute(*name);
2064
        if (attributes != ABSENT) continue;
2065
        // Fall-through and introduce the absent property by using
2066
        // SetProperty.
2067
      }
2068
    } else if (is_function) {
2069
      // Copy the function and update its context. Use it as value.
2070
      Handle<SharedFunctionInfo> shared =
2071
          Handle<SharedFunctionInfo>::cast(value);
2072
      Handle<JSFunction> function =
2073
          isolate->factory()->NewFunctionFromSharedFunctionInfo(
2074
              shared, context, TENURED);
2075
      value = function;
2076
    }
2077

    
2078
    LookupResult lookup(isolate);
2079
    global->LocalLookup(*name, &lookup, true);
2080

    
2081
    // Compute the property attributes. According to ECMA-262,
2082
    // the property must be non-configurable except in eval.
2083
    int attr = NONE;
2084
    bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
2085
    if (!is_eval) {
2086
      attr |= DONT_DELETE;
2087
    }
2088
    bool is_native = DeclareGlobalsNativeFlag::decode(flags);
2089
    if (is_const || (is_native && is_function)) {
2090
      attr |= READ_ONLY;
2091
    }
2092

    
2093
    LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
2094

    
2095
    if (!lookup.IsFound() || is_function) {
2096
      // If the local property exists, check that we can reconfigure it
2097
      // as required for function declarations.
2098
      if (lookup.IsFound() && lookup.IsDontDelete()) {
2099
        if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
2100
            lookup.IsPropertyCallbacks()) {
2101
          return ThrowRedeclarationError(isolate, "function", name);
2102
        }
2103
        // If the existing property is not configurable, keep its attributes.
2104
        attr = lookup.GetAttributes();
2105
      }
2106
      // Define or redefine own property.
2107
      RETURN_IF_EMPTY_HANDLE(isolate,
2108
          JSObject::SetLocalPropertyIgnoreAttributes(
2109
              global, name, value, static_cast<PropertyAttributes>(attr)));
2110
    } else {
2111
      // Do a [[Put]] on the existing (own) property.
2112
      RETURN_IF_EMPTY_HANDLE(isolate,
2113
          JSObject::SetProperty(
2114
              global, name, value, static_cast<PropertyAttributes>(attr),
2115
              language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
2116
    }
2117
  }
2118

    
2119
  ASSERT(!isolate->has_pending_exception());
2120
  return isolate->heap()->undefined_value();
2121
}
2122

    
2123

    
2124
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
2125
  HandleScope scope(isolate);
2126
  ASSERT(args.length() == 4);
2127

    
2128
  // Declarations are always made in a function or native context.  In the
2129
  // case of eval code, the context passed is the context of the caller,
2130
  // which may be some nested context and not the declaration context.
2131
  RUNTIME_ASSERT(args[0]->IsContext());
2132
  Handle<Context> context(Context::cast(args[0])->declaration_context());
2133

    
2134
  Handle<String> name(String::cast(args[1]));
2135
  PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
2136
  RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
2137
  Handle<Object> initial_value(args[3], isolate);
2138

    
2139
  int index;
2140
  PropertyAttributes attributes;
2141
  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
2142
  BindingFlags binding_flags;
2143
  Handle<Object> holder =
2144
      context->Lookup(name, flags, &index, &attributes, &binding_flags);
2145

    
2146
  if (attributes != ABSENT) {
2147
    // The name was declared before; check for conflicting re-declarations.
2148
    // Note: this is actually inconsistent with what happens for globals (where
2149
    // we silently ignore such declarations).
2150
    if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
2151
      // Functions are not read-only.
2152
      ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
2153
      const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
2154
      return ThrowRedeclarationError(isolate, type, name);
2155
    }
2156

    
2157
    // Initialize it if necessary.
2158
    if (*initial_value != NULL) {
2159
      if (index >= 0) {
2160
        ASSERT(holder.is_identical_to(context));
2161
        if (((attributes & READ_ONLY) == 0) ||
2162
            context->get(index)->IsTheHole()) {
2163
          context->set(index, *initial_value);
2164
        }
2165
      } else {
2166
        // Slow case: The property is in the context extension object of a
2167
        // function context or the global object of a native context.
2168
        Handle<JSObject> object = Handle<JSObject>::cast(holder);
2169
        RETURN_IF_EMPTY_HANDLE(
2170
            isolate,
2171
            JSReceiver::SetProperty(object, name, initial_value, mode,
2172
                                    kNonStrictMode));
2173
      }
2174
    }
2175

    
2176
  } else {
2177
    // The property is not in the function context. It needs to be
2178
    // "declared" in the function context's extension context or as a
2179
    // property of the the global object.
2180
    Handle<JSObject> object;
2181
    if (context->has_extension()) {
2182
      object = Handle<JSObject>(JSObject::cast(context->extension()));
2183
    } else {
2184
      // Context extension objects are allocated lazily.
2185
      ASSERT(context->IsFunctionContext());
2186
      object = isolate->factory()->NewJSObject(
2187
          isolate->context_extension_function());
2188
      context->set_extension(*object);
2189
    }
2190
    ASSERT(*object != NULL);
2191

    
2192
    // Declare the property by setting it to the initial value if provided,
2193
    // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
2194
    // constant declarations).
2195
    ASSERT(!JSReceiver::HasLocalProperty(object, name));
2196
    Handle<Object> value(isolate->heap()->undefined_value(), isolate);
2197
    if (*initial_value != NULL) value = initial_value;
2198
    // Declaring a const context slot is a conflicting declaration if
2199
    // there is a callback with that name in a prototype. It is
2200
    // allowed to introduce const variables in
2201
    // JSContextExtensionObjects. They are treated specially in
2202
    // SetProperty and no setters are invoked for those since they are
2203
    // not real JSObjects.
2204
    if (initial_value->IsTheHole() &&
2205
        !object->IsJSContextExtensionObject()) {
2206
      LookupResult lookup(isolate);
2207
      object->Lookup(*name, &lookup);
2208
      if (lookup.IsPropertyCallbacks()) {
2209
        return ThrowRedeclarationError(isolate, "const", name);
2210
      }
2211
    }
2212
    if (object->IsJSGlobalObject()) {
2213
      // Define own property on the global object.
2214
      RETURN_IF_EMPTY_HANDLE(isolate,
2215
         JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
2216
    } else {
2217
      RETURN_IF_EMPTY_HANDLE(isolate,
2218
         JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
2219
    }
2220
  }
2221

    
2222
  return isolate->heap()->undefined_value();
2223
}
2224

    
2225

    
2226
RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
2227
  HandleScope scope(isolate);
2228
  // args[0] == name
2229
  // args[1] == language_mode
2230
  // args[2] == value (optional)
2231

    
2232
  // Determine if we need to assign to the variable if it already
2233
  // exists (based on the number of arguments).
2234
  RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
2235
  bool assign = args.length() == 3;
2236

    
2237
  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2238
  RUNTIME_ASSERT(args[1]->IsSmi());
2239
  CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
2240
  StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
2241
      ? kNonStrictMode : kStrictMode;
2242

    
2243
  // According to ECMA-262, section 12.2, page 62, the property must
2244
  // not be deletable.
2245
  PropertyAttributes attributes = DONT_DELETE;
2246

    
2247
  // Lookup the property locally in the global object. If it isn't
2248
  // there, there is a property with this name in the prototype chain.
2249
  // We follow Safari and Firefox behavior and only set the property
2250
  // locally if there is an explicit initialization value that we have
2251
  // to assign to the property.
2252
  // Note that objects can have hidden prototypes, so we need to traverse
2253
  // the whole chain of hidden prototypes to do a 'local' lookup.
2254
  LookupResult lookup(isolate);
2255
  isolate->context()->global_object()->LocalLookup(*name, &lookup, true);
2256
  if (lookup.IsInterceptor()) {
2257
    PropertyAttributes intercepted =
2258
        lookup.holder()->GetPropertyAttribute(*name);
2259
    if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
2260
      // Found an interceptor that's not read only.
2261
      if (assign) {
2262
        CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2263
        Handle<Object> result = JSObject::SetPropertyForResult(
2264
            handle(lookup.holder()), &lookup, name, value, attributes,
2265
            strict_mode_flag);
2266
        RETURN_IF_EMPTY_HANDLE(isolate, result);
2267
        return *result;
2268
      } else {
2269
        return isolate->heap()->undefined_value();
2270
      }
2271
    }
2272
  }
2273

    
2274
  if (assign) {
2275
    CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
2276
    Handle<GlobalObject> global(isolate->context()->global_object());
2277
    Handle<Object> result = JSReceiver::SetProperty(
2278
        global, name, value, attributes, strict_mode_flag);
2279
    RETURN_IF_EMPTY_HANDLE(isolate, result);
2280
    return *result;
2281
  }
2282
  return isolate->heap()->undefined_value();
2283
}
2284

    
2285

    
2286
RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
2287
  SealHandleScope shs(isolate);
2288
  // All constants are declared with an initial value. The name
2289
  // of the constant is the first argument and the initial value
2290
  // is the second.
2291
  RUNTIME_ASSERT(args.length() == 2);
2292
  CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
2293
  Handle<Object> value = args.at<Object>(1);
2294

    
2295
  // Get the current global object from top.
2296
  GlobalObject* global = isolate->context()->global_object();
2297

    
2298
  // According to ECMA-262, section 12.2, page 62, the property must
2299
  // not be deletable. Since it's a const, it must be READ_ONLY too.
2300
  PropertyAttributes attributes =
2301
      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
2302

    
2303
  // Lookup the property locally in the global object. If it isn't
2304
  // there, we add the property and take special precautions to always
2305
  // add it as a local property even in case of callbacks in the
2306
  // prototype chain (this rules out using SetProperty).
2307
  // We use SetLocalPropertyIgnoreAttributes instead
2308
  LookupResult lookup(isolate);
2309
  global->LocalLookup(*name, &lookup);
2310
  if (!lookup.IsFound()) {
2311
    HandleScope handle_scope(isolate);
2312
    Handle<GlobalObject> global(isolate->context()->global_object());
2313
    RETURN_IF_EMPTY_HANDLE(
2314
        isolate,
2315
        JSObject::SetLocalPropertyIgnoreAttributes(global, name, value,
2316
                                                   attributes));
2317
    return *value;
2318
  }
2319

    
2320
  if (!lookup.IsReadOnly()) {
2321
    // Restore global object from context (in case of GC) and continue
2322
    // with setting the value.
2323
    HandleScope handle_scope(isolate);
2324
    Handle<GlobalObject> global(isolate->context()->global_object());
2325

    
2326
    // BUG 1213575: Handle the case where we have to set a read-only
2327
    // property through an interceptor and only do it if it's
2328
    // uninitialized, e.g. the hole. Nirk...
2329
    // Passing non-strict mode because the property is writable.
2330
    RETURN_IF_EMPTY_HANDLE(
2331
        isolate,
2332
        JSReceiver::SetProperty(global, name, value, attributes,
2333
                                kNonStrictMode));
2334
    return *value;
2335
  }
2336

    
2337
  // Set the value, but only if we're assigning the initial value to a
2338
  // constant. For now, we determine this by checking if the
2339
  // current value is the hole.
2340
  // Strict mode handling not needed (const is disallowed in strict mode).
2341
  if (lookup.IsField()) {
2342
    FixedArray* properties = global->properties();
2343
    int index = lookup.GetFieldIndex().field_index();
2344
    if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
2345
      properties->set(index, *value);
2346
    }
2347
  } else if (lookup.IsNormal()) {
2348
    if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
2349
        !lookup.IsReadOnly()) {
2350
      HandleScope scope(isolate);
2351
      JSObject::SetNormalizedProperty(Handle<JSObject>(global), &lookup, value);
2352
    }
2353
  } else {
2354
    // Ignore re-initialization of constants that have already been
2355
    // assigned a constant value.
2356
    ASSERT(lookup.IsReadOnly() && lookup.IsConstant());
2357
  }
2358

    
2359
  // Use the set value as the result of the operation.
2360
  return *value;
2361
}
2362

    
2363

    
2364
RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
2365
  HandleScope scope(isolate);
2366
  ASSERT(args.length() == 3);
2367

    
2368
  Handle<Object> value(args[0], isolate);
2369
  ASSERT(!value->IsTheHole());
2370

    
2371
  // Initializations are always done in a function or native context.
2372
  RUNTIME_ASSERT(args[1]->IsContext());
2373
  Handle<Context> context(Context::cast(args[1])->declaration_context());
2374

    
2375
  Handle<String> name(String::cast(args[2]));
2376

    
2377
  int index;
2378
  PropertyAttributes attributes;
2379
  ContextLookupFlags flags = FOLLOW_CHAINS;
2380
  BindingFlags binding_flags;
2381
  Handle<Object> holder =
2382
      context->Lookup(name, flags, &index, &attributes, &binding_flags);
2383

    
2384
  if (index >= 0) {
2385
    ASSERT(holder->IsContext());
2386
    // Property was found in a context.  Perform the assignment if we
2387
    // found some non-constant or an uninitialized constant.
2388
    Handle<Context> context = Handle<Context>::cast(holder);
2389
    if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
2390
      context->set(index, *value);
2391
    }
2392
    return *value;
2393
  }
2394

    
2395
  // The property could not be found, we introduce it as a property of the
2396
  // global object.
2397
  if (attributes == ABSENT) {
2398
    Handle<JSObject> global = Handle<JSObject>(
2399
        isolate->context()->global_object());
2400
    // Strict mode not needed (const disallowed in strict mode).
2401
    RETURN_IF_EMPTY_HANDLE(
2402
        isolate,
2403
        JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
2404
    return *value;
2405
  }
2406

    
2407
  // The property was present in some function's context extension object,
2408
  // as a property on the subject of a with, or as a property of the global
2409
  // object.
2410
  //
2411
  // In most situations, eval-introduced consts should still be present in
2412
  // the context extension object.  However, because declaration and
2413
  // initialization are separate, the property might have been deleted
2414
  // before we reach the initialization point.
2415
  //
2416
  // Example:
2417
  //
2418
  //    function f() { eval("delete x; const x;"); }
2419
  //
2420
  // In that case, the initialization behaves like a normal assignment.
2421
  Handle<JSObject> object = Handle<JSObject>::cast(holder);
2422

    
2423
  if (*object == context->extension()) {
2424
    // This is the property that was introduced by the const declaration.
2425
    // Set it if it hasn't been set before.  NOTE: We cannot use
2426
    // GetProperty() to get the current value as it 'unholes' the value.
2427
    LookupResult lookup(isolate);
2428
    object->LocalLookupRealNamedProperty(*name, &lookup);
2429
    ASSERT(lookup.IsFound());  // the property was declared
2430
    ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
2431

    
2432
    if (lookup.IsField()) {
2433
      FixedArray* properties = object->properties();
2434
      int index = lookup.GetFieldIndex().field_index();
2435
      if (properties->get(index)->IsTheHole()) {
2436
        properties->set(index, *value);
2437
      }
2438
    } else if (lookup.IsNormal()) {
2439
      if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
2440
        JSObject::SetNormalizedProperty(object, &lookup, value);
2441
      }
2442
    } else {
2443
      // We should not reach here. Any real, named property should be
2444
      // either a field or a dictionary slot.
2445
      UNREACHABLE();
2446
    }
2447
  } else {
2448
    // The property was found on some other object.  Set it if it is not a
2449
    // read-only property.
2450
    if ((attributes & READ_ONLY) == 0) {
2451
      // Strict mode not needed (const disallowed in strict mode).
2452
      RETURN_IF_EMPTY_HANDLE(
2453
          isolate,
2454
          JSReceiver::SetProperty(object, name, value, attributes,
2455
                                  kNonStrictMode));
2456
    }
2457
  }
2458

    
2459
  return *value;
2460
}
2461

    
2462

    
2463
RUNTIME_FUNCTION(MaybeObject*,
2464
                 Runtime_OptimizeObjectForAddingMultipleProperties) {
2465
  HandleScope scope(isolate);
2466
  ASSERT(args.length() == 2);
2467
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
2468
  CONVERT_SMI_ARG_CHECKED(properties, 1);
2469
  if (object->HasFastProperties()) {
2470
    JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
2471
  }
2472
  return *object;
2473
}
2474

    
2475

    
2476
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
2477
  HandleScope scope(isolate);
2478
  ASSERT(args.length() == 4);
2479
  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2480
  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
2481
  // Due to the way the JS calls are constructed this must be less than the
2482
  // length of a string, i.e. it is always a Smi.  We check anyway for security.
2483
  CONVERT_SMI_ARG_CHECKED(index, 2);
2484
  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
2485
  RUNTIME_ASSERT(index >= 0);
2486
  RUNTIME_ASSERT(index <= subject->length());
2487
  isolate->counters()->regexp_entry_runtime()->Increment();
2488
  Handle<Object> result = RegExpImpl::Exec(regexp,
2489
                                           subject,
2490
                                           index,
2491
                                           last_match_info);
2492
  RETURN_IF_EMPTY_HANDLE(isolate, result);
2493
  return *result;
2494
}
2495

    
2496

    
2497
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
2498
  SealHandleScope shs(isolate);
2499
  ASSERT(args.length() == 3);
2500
  CONVERT_SMI_ARG_CHECKED(elements_count, 0);
2501
  if (elements_count < 0 ||
2502
      elements_count > FixedArray::kMaxLength ||
2503
      !Smi::IsValid(elements_count)) {
2504
    return isolate->ThrowIllegalOperation();
2505
  }
2506
  Object* new_object;
2507
  { MaybeObject* maybe_new_object =
2508
        isolate->heap()->AllocateFixedArray(elements_count);
2509
    if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2510
  }
2511
  FixedArray* elements = FixedArray::cast(new_object);
2512
  { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
2513
      JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
2514
    if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
2515
  }
2516
  {
2517
    DisallowHeapAllocation no_gc;
2518
    HandleScope scope(isolate);
2519
    reinterpret_cast<HeapObject*>(new_object)->
2520
        set_map(isolate->native_context()->regexp_result_map());
2521
  }
2522
  JSArray* array = JSArray::cast(new_object);
2523
  array->set_properties(isolate->heap()->empty_fixed_array());
2524
  array->set_elements(elements);
2525
  array->set_length(Smi::FromInt(elements_count));
2526
  // Write in-object properties after the length of the array.
2527
  array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
2528
  array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
2529
  return array;
2530
}
2531

    
2532

    
2533
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
2534
  HandleScope scope(isolate);
2535
  DisallowHeapAllocation no_allocation;
2536
  ASSERT(args.length() == 5);
2537
  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
2538
  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
2539
  // If source is the empty string we set it to "(?:)" instead as
2540
  // suggested by ECMA-262, 5th, section 15.10.4.1.
2541
  if (source->length() == 0) source = isolate->factory()->query_colon_string();
2542

    
2543
  CONVERT_ARG_HANDLE_CHECKED(Object, global, 2);
2544
  if (!global->IsTrue()) global = isolate->factory()->false_value();
2545

    
2546
  CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3);
2547
  if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value();
2548

    
2549
  CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4);
2550
  if (!multiline->IsTrue()) multiline = isolate->factory()->false_value();
2551

    
2552
  Map* map = regexp->map();
2553
  Object* constructor = map->constructor();
2554
  if (constructor->IsJSFunction() &&
2555
      JSFunction::cast(constructor)->initial_map() == map) {
2556
    // If we still have the original map, set in-object properties directly.
2557
    regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, *source);
2558
    // Both true and false are immovable immortal objects so no need for write
2559
    // barrier.
2560
    regexp->InObjectPropertyAtPut(
2561
        JSRegExp::kGlobalFieldIndex, *global, SKIP_WRITE_BARRIER);
2562
    regexp->InObjectPropertyAtPut(
2563
        JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, SKIP_WRITE_BARRIER);
2564
    regexp->InObjectPropertyAtPut(
2565
        JSRegExp::kMultilineFieldIndex, *multiline, SKIP_WRITE_BARRIER);
2566
    regexp->InObjectPropertyAtPut(
2567
        JSRegExp::kLastIndexFieldIndex, Smi::FromInt(0), SKIP_WRITE_BARRIER);
2568
    return *regexp;
2569
  }
2570

    
2571
  // Map has changed, so use generic, but slower, method.
2572
  PropertyAttributes final =
2573
      static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
2574
  PropertyAttributes writable =
2575
      static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
2576
  Handle<Object> zero(Smi::FromInt(0), isolate);
2577
  Factory* factory = isolate->factory();
2578
  CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2579
      regexp, factory->source_string(), source, final));
2580
  CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2581
      regexp, factory->global_string(), global, final));
2582
  CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2583
      regexp, factory->ignore_case_string(), ignoreCase, final));
2584
  CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2585
      regexp, factory->multiline_string(), multiline, final));
2586
  CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetLocalPropertyIgnoreAttributes(
2587
      regexp, factory->last_index_string(), zero, writable));
2588
  return *regexp;
2589
}
2590

    
2591

    
2592
RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
2593
  HandleScope scope(isolate);
2594
  ASSERT(args.length() == 1);
2595
  CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
2596
  // This is necessary to enable fast checks for absence of elements
2597
  // on Array.prototype and below.
2598
  prototype->set_elements(isolate->heap()->empty_fixed_array());
2599
  return Smi::FromInt(0);
2600
}
2601

    
2602

    
2603
static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
2604
                                         Handle<JSObject> holder,
2605
                                         const char* name,
2606
                                         Builtins::Name builtin_name) {
2607
  Handle<String> key = isolate->factory()->InternalizeUtf8String(name);
2608
  Handle<Code> code(isolate->builtins()->builtin(builtin_name));
2609
  Handle<JSFunction> optimized =
2610
      isolate->factory()->NewFunction(key,
2611
                                      JS_OBJECT_TYPE,
2612
                                      JSObject::kHeaderSize,
2613
                                      code,
2614
                                      false);
2615
  optimized->shared()->DontAdaptArguments();
2616
  JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
2617
  return optimized;
2618
}
2619

    
2620

    
2621
RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
2622
  HandleScope scope(isolate);
2623
  ASSERT(args.length() == 1);
2624
  CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
2625

    
2626
  InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
2627
  InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
2628
  InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
2629
  InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
2630
  InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
2631
  InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
2632
  InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
2633

    
2634
  return *holder;
2635
}
2636

    
2637

    
2638
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsClassicModeFunction) {
2639
  SealHandleScope shs(isolate);
2640
  ASSERT(args.length() == 1);
2641
  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2642
  if (!callable->IsJSFunction()) {
2643
    HandleScope scope(isolate);
2644
    bool threw = false;
2645
    Handle<Object> delegate = Execution::TryGetFunctionDelegate(
2646
        isolate, Handle<JSReceiver>(callable), &threw);
2647
    if (threw) return Failure::Exception();
2648
    callable = JSFunction::cast(*delegate);
2649
  }
2650
  JSFunction* function = JSFunction::cast(callable);
2651
  SharedFunctionInfo* shared = function->shared();
2652
  return isolate->heap()->ToBoolean(shared->is_classic_mode());
2653
}
2654

    
2655

    
2656
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
2657
  SealHandleScope shs(isolate);
2658
  ASSERT(args.length() == 1);
2659
  CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
2660

    
2661
  if (!callable->IsJSFunction()) {
2662
    HandleScope scope(isolate);
2663
    bool threw = false;
2664
    Handle<Object> delegate = Execution::TryGetFunctionDelegate(
2665
        isolate, Handle<JSReceiver>(callable), &threw);
2666
    if (threw) return Failure::Exception();
2667
    callable = JSFunction::cast(*delegate);
2668
  }
2669
  JSFunction* function = JSFunction::cast(callable);
2670

    
2671
  SharedFunctionInfo* shared = function->shared();
2672
  if (shared->native() || !shared->is_classic_mode()) {
2673
    return isolate->heap()->undefined_value();
2674
  }
2675
  // Returns undefined for strict or native functions, or
2676
  // the associated global receiver for "normal" functions.
2677

    
2678
  Context* native_context =
2679
      function->context()->global_object()->native_context();
2680
  return native_context->global_object()->global_receiver();
2681
}
2682

    
2683

    
2684
RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
2685
  HandleScope scope(isolate);
2686
  ASSERT(args.length() == 4);
2687
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2688
  int index = args.smi_at(1);
2689
  Handle<String> pattern = args.at<String>(2);
2690
  Handle<String> flags = args.at<String>(3);
2691

    
2692
  // Get the RegExp function from the context in the literals array.
2693
  // This is the RegExp function from the context in which the
2694
  // function was created.  We do not use the RegExp function from the
2695
  // current native context because this might be the RegExp function
2696
  // from another context which we should not have access to.
2697
  Handle<JSFunction> constructor =
2698
      Handle<JSFunction>(
2699
          JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2700
  // Compute the regular expression literal.
2701
  bool has_pending_exception;
2702
  Handle<Object> regexp =
2703
      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2704
                                      &has_pending_exception);
2705
  if (has_pending_exception) {
2706
    ASSERT(isolate->has_pending_exception());
2707
    return Failure::Exception();
2708
  }
2709
  literals->set(index, *regexp);
2710
  return *regexp;
2711
}
2712

    
2713

    
2714
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2715
  SealHandleScope shs(isolate);
2716
  ASSERT(args.length() == 1);
2717

    
2718
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2719
  return f->shared()->name();
2720
}
2721

    
2722

    
2723
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2724
  SealHandleScope shs(isolate);
2725
  ASSERT(args.length() == 2);
2726

    
2727
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2728
  CONVERT_ARG_CHECKED(String, name, 1);
2729
  f->shared()->set_name(name);
2730
  return isolate->heap()->undefined_value();
2731
}
2732

    
2733

    
2734
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2735
  SealHandleScope shs(isolate);
2736
  ASSERT(args.length() == 1);
2737
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2738
  return isolate->heap()->ToBoolean(
2739
      f->shared()->name_should_print_as_anonymous());
2740
}
2741

    
2742

    
2743
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2744
  SealHandleScope shs(isolate);
2745
  ASSERT(args.length() == 1);
2746
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2747
  f->shared()->set_name_should_print_as_anonymous(true);
2748
  return isolate->heap()->undefined_value();
2749
}
2750

    
2751

    
2752
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsGenerator) {
2753
  SealHandleScope shs(isolate);
2754
  ASSERT(args.length() == 1);
2755
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2756
  return isolate->heap()->ToBoolean(f->shared()->is_generator());
2757
}
2758

    
2759

    
2760
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2761
  SealHandleScope shs(isolate);
2762
  ASSERT(args.length() == 1);
2763

    
2764
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2765
  f->RemovePrototype();
2766

    
2767
  return isolate->heap()->undefined_value();
2768
}
2769

    
2770

    
2771
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2772
  HandleScope scope(isolate);
2773
  ASSERT(args.length() == 1);
2774

    
2775
  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2776
  Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2777
  if (!script->IsScript()) return isolate->heap()->undefined_value();
2778

    
2779
  return *GetScriptWrapper(Handle<Script>::cast(script));
2780
}
2781

    
2782

    
2783
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2784
  HandleScope scope(isolate);
2785
  ASSERT(args.length() == 1);
2786

    
2787
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2788
  Handle<SharedFunctionInfo> shared(f->shared());
2789
  return *shared->GetSourceCode();
2790
}
2791

    
2792

    
2793
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2794
  SealHandleScope shs(isolate);
2795
  ASSERT(args.length() == 1);
2796

    
2797
  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2798
  int pos = fun->shared()->start_position();
2799
  return Smi::FromInt(pos);
2800
}
2801

    
2802

    
2803
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2804
  SealHandleScope shs(isolate);
2805
  ASSERT(args.length() == 2);
2806

    
2807
  CONVERT_ARG_CHECKED(Code, code, 0);
2808
  CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2809

    
2810
  RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2811

    
2812
  Address pc = code->address() + offset;
2813
  return Smi::FromInt(code->SourcePosition(pc));
2814
}
2815

    
2816

    
2817
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2818
  SealHandleScope shs(isolate);
2819
  ASSERT(args.length() == 2);
2820

    
2821
  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2822
  CONVERT_ARG_CHECKED(String, name, 1);
2823
  fun->SetInstanceClassName(name);
2824
  return isolate->heap()->undefined_value();
2825
}
2826

    
2827

    
2828
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2829
  SealHandleScope shs(isolate);
2830
  ASSERT(args.length() == 2);
2831

    
2832
  CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2833
  CONVERT_SMI_ARG_CHECKED(length, 1);
2834
  fun->shared()->set_length(length);
2835
  return isolate->heap()->undefined_value();
2836
}
2837

    
2838

    
2839
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2840
  HandleScope scope(isolate);
2841
  ASSERT(args.length() == 2);
2842

    
2843
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
2844
  CONVERT_ARG_HANDLE_CHECKED(Object, value, 1);
2845
  ASSERT(fun->should_have_prototype());
2846
  Accessors::FunctionSetPrototype(fun, value);
2847
  return args[0];  // return TOS
2848
}
2849

    
2850

    
2851
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2852
  SealHandleScope shs(isolate);
2853
  RUNTIME_ASSERT(args.length() == 1);
2854
  CONVERT_ARG_CHECKED(JSFunction, function, 0);
2855

    
2856
  String* name = isolate->heap()->prototype_string();
2857

    
2858
  if (function->HasFastProperties()) {
2859
    // Construct a new field descriptor with updated attributes.
2860
    DescriptorArray* instance_desc = function->map()->instance_descriptors();
2861

    
2862
    int index = instance_desc->SearchWithCache(name, function->map());
2863
    ASSERT(index != DescriptorArray::kNotFound);
2864
    PropertyDetails details = instance_desc->GetDetails(index);
2865

    
2866
    CallbacksDescriptor new_desc(name,
2867
        instance_desc->GetValue(index),
2868
        static_cast<PropertyAttributes>(details.attributes() | READ_ONLY));
2869

    
2870
    // Create a new map featuring the new field descriptors array.
2871
    Map* new_map;
2872
    MaybeObject* maybe_map =
2873
        function->map()->CopyReplaceDescriptor(
2874
            instance_desc, &new_desc, index, OMIT_TRANSITION);
2875
    if (!maybe_map->To(&new_map)) return maybe_map;
2876

    
2877
    function->set_map(new_map);
2878
  } else {  // Dictionary properties.
2879
    // Directly manipulate the property details.
2880
    int entry = function->property_dictionary()->FindEntry(name);
2881
    ASSERT(entry != NameDictionary::kNotFound);
2882
    PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2883
    PropertyDetails new_details(
2884
        static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2885
        details.type(),
2886
        details.dictionary_index());
2887
    function->property_dictionary()->DetailsAtPut(entry, new_details);
2888
  }
2889
  return function;
2890
}
2891

    
2892

    
2893
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2894
  SealHandleScope shs(isolate);
2895
  ASSERT(args.length() == 1);
2896

    
2897
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2898
  return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2899
}
2900

    
2901

    
2902
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2903
  SealHandleScope shs(isolate);
2904
  ASSERT(args.length() == 1);
2905

    
2906
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
2907
  return isolate->heap()->ToBoolean(f->IsBuiltin());
2908
}
2909

    
2910

    
2911
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2912
  HandleScope scope(isolate);
2913
  ASSERT(args.length() == 2);
2914

    
2915
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2916
  Handle<Object> code = args.at<Object>(1);
2917

    
2918
  if (code->IsNull()) return *target;
2919
  RUNTIME_ASSERT(code->IsJSFunction());
2920
  Handle<JSFunction> source = Handle<JSFunction>::cast(code);
2921
  Handle<SharedFunctionInfo> target_shared(target->shared());
2922
  Handle<SharedFunctionInfo> source_shared(source->shared());
2923

    
2924
  if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
2925
    return Failure::Exception();
2926
  }
2927

    
2928
  // Mark both, the source and the target, as un-flushable because the
2929
  // shared unoptimized code makes them impossible to enqueue in a list.
2930
  ASSERT(target_shared->code()->gc_metadata() == NULL);
2931
  ASSERT(source_shared->code()->gc_metadata() == NULL);
2932
  target_shared->set_dont_flush(true);
2933
  source_shared->set_dont_flush(true);
2934

    
2935
  // Set the code, scope info, formal parameter count, and the length
2936
  // of the target shared function info.
2937
  target_shared->ReplaceCode(source_shared->code());
2938
  target_shared->set_scope_info(source_shared->scope_info());
2939
  target_shared->set_length(source_shared->length());
2940
  target_shared->set_formal_parameter_count(
2941
      source_shared->formal_parameter_count());
2942
  target_shared->set_script(source_shared->script());
2943
  target_shared->set_start_position_and_type(
2944
      source_shared->start_position_and_type());
2945
  target_shared->set_end_position(source_shared->end_position());
2946
  bool was_native = target_shared->native();
2947
  target_shared->set_compiler_hints(source_shared->compiler_hints());
2948
  target_shared->set_native(was_native);
2949

    
2950
  // Set the code of the target function.
2951
  target->ReplaceCode(source_shared->code());
2952
  ASSERT(target->next_function_link()->IsUndefined());
2953

    
2954
  // Make sure we get a fresh copy of the literal vector to avoid cross
2955
  // context contamination.
2956
  Handle<Context> context(source->context());
2957
  int number_of_literals = source->NumberOfLiterals();
2958
  Handle<FixedArray> literals =
2959
      isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2960
  if (number_of_literals > 0) {
2961
    literals->set(JSFunction::kLiteralNativeContextIndex,
2962
                  context->native_context());
2963
  }
2964
  target->set_context(*context);
2965
  target->set_literals(*literals);
2966

    
2967
  if (isolate->logger()->is_logging_code_events() ||
2968
      isolate->cpu_profiler()->is_profiling()) {
2969
    isolate->logger()->LogExistingFunction(
2970
        source_shared, Handle<Code>(source_shared->code()));
2971
  }
2972

    
2973
  return *target;
2974
}
2975

    
2976

    
2977
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2978
  HandleScope scope(isolate);
2979
  ASSERT(args.length() == 2);
2980
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
2981
  CONVERT_SMI_ARG_CHECKED(num, 1);
2982
  RUNTIME_ASSERT(num >= 0);
2983
  // If objects constructed from this function exist then changing
2984
  // 'estimated_nof_properties' is dangerous since the previous value might
2985
  // have been compiled into the fast construct stub. Moreover, the inobject
2986
  // slack tracking logic might have adjusted the previous value, so even
2987
  // passing the same value is risky.
2988
  if (!func->shared()->live_objects_may_exist()) {
2989
    func->shared()->set_expected_nof_properties(num);
2990
    if (func->has_initial_map()) {
2991
      Handle<Map> new_initial_map =
2992
          func->GetIsolate()->factory()->CopyMap(
2993
              Handle<Map>(func->initial_map()));
2994
      new_initial_map->set_unused_property_fields(num);
2995
      func->set_initial_map(*new_initial_map);
2996
    }
2997
  }
2998
  return isolate->heap()->undefined_value();
2999
}
3000

    
3001

    
3002
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSGeneratorObject) {
3003
  SealHandleScope shs(isolate);
3004
  ASSERT(args.length() == 0);
3005

    
3006
  JavaScriptFrameIterator it(isolate);
3007
  JavaScriptFrame* frame = it.frame();
3008
  JSFunction* function = frame->function();
3009
  RUNTIME_ASSERT(function->shared()->is_generator());
3010

    
3011
  JSGeneratorObject* generator;
3012
  if (frame->IsConstructor()) {
3013
    generator = JSGeneratorObject::cast(frame->receiver());
3014
  } else {
3015
    MaybeObject* maybe_generator =
3016
        isolate->heap()->AllocateJSGeneratorObject(function);
3017
    if (!maybe_generator->To(&generator)) return maybe_generator;
3018
  }
3019
  generator->set_function(function);
3020
  generator->set_context(Context::cast(frame->context()));
3021
  generator->set_receiver(frame->receiver());
3022
  generator->set_continuation(0);
3023
  generator->set_operand_stack(isolate->heap()->empty_fixed_array());
3024
  generator->set_stack_handler_index(-1);
3025

    
3026
  return generator;
3027
}
3028

    
3029

    
3030
RUNTIME_FUNCTION(MaybeObject*, Runtime_SuspendJSGeneratorObject) {
3031
  SealHandleScope shs(isolate);
3032
  ASSERT(args.length() == 1);
3033
  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3034

    
3035
  JavaScriptFrameIterator stack_iterator(isolate);
3036
  JavaScriptFrame* frame = stack_iterator.frame();
3037
  RUNTIME_ASSERT(frame->function()->shared()->is_generator());
3038
  ASSERT_EQ(frame->function(), generator_object->function());
3039

    
3040
  // The caller should have saved the context and continuation already.
3041
  ASSERT_EQ(generator_object->context(), Context::cast(frame->context()));
3042
  ASSERT_LT(0, generator_object->continuation());
3043

    
3044
  // We expect there to be at least two values on the operand stack: the return
3045
  // value of the yield expression, and the argument to this runtime call.
3046
  // Neither of those should be saved.
3047
  int operands_count = frame->ComputeOperandsCount();
3048
  ASSERT_GE(operands_count, 2);
3049
  operands_count -= 2;
3050

    
3051
  if (operands_count == 0) {
3052
    // Although it's semantically harmless to call this function with an
3053
    // operands_count of zero, it is also unnecessary.
3054
    ASSERT_EQ(generator_object->operand_stack(),
3055
              isolate->heap()->empty_fixed_array());
3056
    ASSERT_EQ(generator_object->stack_handler_index(), -1);
3057
    // If there are no operands on the stack, there shouldn't be a handler
3058
    // active either.
3059
    ASSERT(!frame->HasHandler());
3060
  } else {
3061
    int stack_handler_index = -1;
3062
    MaybeObject* alloc = isolate->heap()->AllocateFixedArray(operands_count);
3063
    FixedArray* operand_stack;
3064
    if (!alloc->To(&operand_stack)) return alloc;
3065
    frame->SaveOperandStack(operand_stack, &stack_handler_index);
3066
    generator_object->set_operand_stack(operand_stack);
3067
    generator_object->set_stack_handler_index(stack_handler_index);
3068
  }
3069

    
3070
  return isolate->heap()->undefined_value();
3071
}
3072

    
3073

    
3074
// Note that this function is the slow path for resuming generators.  It is only
3075
// called if the suspended activation had operands on the stack, stack handlers
3076
// needing rewinding, or if the resume should throw an exception.  The fast path
3077
// is handled directly in FullCodeGenerator::EmitGeneratorResume(), which is
3078
// inlined into GeneratorNext and GeneratorThrow.  EmitGeneratorResumeResume is
3079
// called in any case, as it needs to reconstruct the stack frame and make space
3080
// for arguments and operands.
3081
RUNTIME_FUNCTION(MaybeObject*, Runtime_ResumeJSGeneratorObject) {
3082
  SealHandleScope shs(isolate);
3083
  ASSERT(args.length() == 3);
3084
  CONVERT_ARG_CHECKED(JSGeneratorObject, generator_object, 0);
3085
  CONVERT_ARG_CHECKED(Object, value, 1);
3086
  CONVERT_SMI_ARG_CHECKED(resume_mode_int, 2);
3087
  JavaScriptFrameIterator stack_iterator(isolate);
3088
  JavaScriptFrame* frame = stack_iterator.frame();
3089

    
3090
  ASSERT_EQ(frame->function(), generator_object->function());
3091
  ASSERT(frame->function()->is_compiled());
3092

    
3093
  STATIC_ASSERT(JSGeneratorObject::kGeneratorExecuting <= 0);
3094
  STATIC_ASSERT(JSGeneratorObject::kGeneratorClosed <= 0);
3095

    
3096
  Address pc = generator_object->function()->code()->instruction_start();
3097
  int offset = generator_object->continuation();
3098
  ASSERT(offset > 0);
3099
  frame->set_pc(pc + offset);
3100
  generator_object->set_continuation(JSGeneratorObject::kGeneratorExecuting);
3101

    
3102
  FixedArray* operand_stack = generator_object->operand_stack();
3103
  int operands_count = operand_stack->length();
3104
  if (operands_count != 0) {
3105
    frame->RestoreOperandStack(operand_stack,
3106
                               generator_object->stack_handler_index());
3107
    generator_object->set_operand_stack(isolate->heap()->empty_fixed_array());
3108
    generator_object->set_stack_handler_index(-1);
3109
  }
3110

    
3111
  JSGeneratorObject::ResumeMode resume_mode =
3112
      static_cast<JSGeneratorObject::ResumeMode>(resume_mode_int);
3113
  switch (resume_mode) {
3114
    case JSGeneratorObject::NEXT:
3115
      return value;
3116
    case JSGeneratorObject::THROW:
3117
      return isolate->Throw(value);
3118
  }
3119

    
3120
  UNREACHABLE();
3121
  return isolate->ThrowIllegalOperation();
3122
}
3123

    
3124

    
3125
RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowGeneratorStateError) {
3126
  HandleScope scope(isolate);
3127
  ASSERT(args.length() == 1);
3128
  CONVERT_ARG_HANDLE_CHECKED(JSGeneratorObject, generator, 0);
3129
  int continuation = generator->continuation();
3130
  const char* message = continuation == JSGeneratorObject::kGeneratorClosed ?
3131
      "generator_finished" : "generator_running";
3132
  Vector< Handle<Object> > argv = HandleVector<Object>(NULL, 0);
3133
  Handle<Object> error = isolate->factory()->NewError(message, argv);
3134
  return isolate->Throw(*error);
3135
}
3136

    
3137

    
3138
RUNTIME_FUNCTION(MaybeObject*, Runtime_ObjectFreeze) {
3139
  HandleScope scope(isolate);
3140
  ASSERT(args.length() == 1);
3141
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
3142
  Handle<Object> result = JSObject::Freeze(object);
3143
  RETURN_IF_EMPTY_HANDLE(isolate, result);
3144
  return *result;
3145
}
3146

    
3147

    
3148
MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
3149
                                                 Object* char_code) {
3150
  if (char_code->IsNumber()) {
3151
    return isolate->heap()->LookupSingleCharacterStringFromCode(
3152
        NumberToUint32(char_code) & 0xffff);
3153
  }
3154
  return isolate->heap()->empty_string();
3155
}
3156

    
3157

    
3158
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
3159
  SealHandleScope shs(isolate);
3160
  ASSERT(args.length() == 2);
3161

    
3162
  CONVERT_ARG_CHECKED(String, subject, 0);
3163
  CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
3164

    
3165
  // Flatten the string.  If someone wants to get a char at an index
3166
  // in a cons string, it is likely that more indices will be
3167
  // accessed.
3168
  Object* flat;
3169
  { MaybeObject* maybe_flat = subject->TryFlatten();
3170
    if (!maybe_flat->ToObject(&flat)) return maybe_flat;
3171
  }
3172
  subject = String::cast(flat);
3173

    
3174
  if (i >= static_cast<uint32_t>(subject->length())) {
3175
    return isolate->heap()->nan_value();
3176
  }
3177

    
3178
  return Smi::FromInt(subject->Get(i));
3179
}
3180

    
3181

    
3182
RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
3183
  SealHandleScope shs(isolate);
3184
  ASSERT(args.length() == 1);
3185
  return CharFromCode(isolate, args[0]);
3186
}
3187

    
3188

    
3189
class FixedArrayBuilder {
3190
 public:
3191
  explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
3192
      : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
3193
        length_(0),
3194
        has_non_smi_elements_(false) {
3195
    // Require a non-zero initial size. Ensures that doubling the size to
3196
    // extend the array will work.
3197
    ASSERT(initial_capacity > 0);
3198
  }
3199

    
3200
  explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
3201
      : array_(backing_store),
3202
        length_(0),
3203
        has_non_smi_elements_(false) {
3204
    // Require a non-zero initial size. Ensures that doubling the size to
3205
    // extend the array will work.
3206
    ASSERT(backing_store->length() > 0);
3207
  }
3208

    
3209
  bool HasCapacity(int elements) {
3210
    int length = array_->length();
3211
    int required_length = length_ + elements;
3212
    return (length >= required_length);
3213
  }
3214

    
3215
  void EnsureCapacity(int elements) {
3216
    int length = array_->length();
3217
    int required_length = length_ + elements;
3218
    if (length < required_length) {
3219
      int new_length = length;
3220
      do {
3221
        new_length *= 2;
3222
      } while (new_length < required_length);
3223
      Handle<FixedArray> extended_array =
3224
          array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
3225
      array_->CopyTo(0, *extended_array, 0, length_);
3226
      array_ = extended_array;
3227
    }
3228
  }
3229

    
3230
  void Add(Object* value) {
3231
    ASSERT(!value->IsSmi());
3232
    ASSERT(length_ < capacity());
3233
    array_->set(length_, value);
3234
    length_++;
3235
    has_non_smi_elements_ = true;
3236
  }
3237

    
3238
  void Add(Smi* value) {
3239
    ASSERT(value->IsSmi());
3240
    ASSERT(length_ < capacity());
3241
    array_->set(length_, value);
3242
    length_++;
3243
  }
3244

    
3245
  Handle<FixedArray> array() {
3246
    return array_;
3247
  }
3248

    
3249
  int length() {
3250
    return length_;
3251
  }
3252

    
3253
  int capacity() {
3254
    return array_->length();
3255
  }
3256

    
3257
  Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
3258
    Factory* factory = target_array->GetIsolate()->factory();
3259
    factory->SetContent(target_array, array_);
3260
    target_array->set_length(Smi::FromInt(length_));
3261
    return target_array;
3262
  }
3263

    
3264

    
3265
 private:
3266
  Handle<FixedArray> array_;
3267
  int length_;
3268
  bool has_non_smi_elements_;
3269
};
3270

    
3271

    
3272
// Forward declarations.
3273
const int kStringBuilderConcatHelperLengthBits = 11;
3274
const int kStringBuilderConcatHelperPositionBits = 19;
3275

    
3276
template <typename schar>
3277
static inline void StringBuilderConcatHelper(String*,
3278
                                             schar*,
3279
                                             FixedArray*,
3280
                                             int);
3281

    
3282
typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
3283
    StringBuilderSubstringLength;
3284
typedef BitField<int,
3285
                 kStringBuilderConcatHelperLengthBits,
3286
                 kStringBuilderConcatHelperPositionBits>
3287
    StringBuilderSubstringPosition;
3288

    
3289

    
3290
class ReplacementStringBuilder {
3291
 public:
3292
  ReplacementStringBuilder(Heap* heap,
3293
                           Handle<String> subject,
3294
                           int estimated_part_count)
3295
      : heap_(heap),
3296
        array_builder_(heap->isolate(), estimated_part_count),
3297
        subject_(subject),
3298
        character_count_(0),
3299
        is_ascii_(subject->IsOneByteRepresentation()) {
3300
    // Require a non-zero initial size. Ensures that doubling the size to
3301
    // extend the array will work.
3302
    ASSERT(estimated_part_count > 0);
3303
  }
3304

    
3305
  static inline void AddSubjectSlice(FixedArrayBuilder* builder,
3306
                                     int from,
3307
                                     int to) {
3308
    ASSERT(from >= 0);
3309
    int length = to - from;
3310
    ASSERT(length > 0);
3311
    if (StringBuilderSubstringLength::is_valid(length) &&
3312
        StringBuilderSubstringPosition::is_valid(from)) {
3313
      int encoded_slice = StringBuilderSubstringLength::encode(length) |
3314
          StringBuilderSubstringPosition::encode(from);
3315
      builder->Add(Smi::FromInt(encoded_slice));
3316
    } else {
3317
      // Otherwise encode as two smis.
3318
      builder->Add(Smi::FromInt(-length));
3319
      builder->Add(Smi::FromInt(from));
3320
    }
3321
  }
3322

    
3323

    
3324
  void EnsureCapacity(int elements) {
3325
    array_builder_.EnsureCapacity(elements);
3326
  }
3327

    
3328

    
3329
  void AddSubjectSlice(int from, int to) {
3330
    AddSubjectSlice(&array_builder_, from, to);
3331
    IncrementCharacterCount(to - from);
3332
  }
3333

    
3334

    
3335
  void AddString(Handle<String> string) {
3336
    int length = string->length();
3337
    ASSERT(length > 0);
3338
    AddElement(*string);
3339
    if (!string->IsOneByteRepresentation()) {
3340
      is_ascii_ = false;
3341
    }
3342
    IncrementCharacterCount(length);
3343
  }
3344

    
3345

    
3346
  Handle<String> ToString() {
3347
    if (array_builder_.length() == 0) {
3348
      return heap_->isolate()->factory()->empty_string();
3349
    }
3350

    
3351
    Handle<String> joined_string;
3352
    if (is_ascii_) {
3353
      Handle<SeqOneByteString> seq = NewRawOneByteString(character_count_);
3354
      DisallowHeapAllocation no_gc;
3355
      uint8_t* char_buffer = seq->GetChars();
3356
      StringBuilderConcatHelper(*subject_,
3357
                                char_buffer,
3358
                                *array_builder_.array(),
3359
                                array_builder_.length());
3360
      joined_string = Handle<String>::cast(seq);
3361
    } else {
3362
      // Non-ASCII.
3363
      Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
3364
      DisallowHeapAllocation no_gc;
3365
      uc16* char_buffer = seq->GetChars();
3366
      StringBuilderConcatHelper(*subject_,
3367
                                char_buffer,
3368
                                *array_builder_.array(),
3369
                                array_builder_.length());
3370
      joined_string = Handle<String>::cast(seq);
3371
    }
3372
    return joined_string;
3373
  }
3374

    
3375

    
3376
  void IncrementCharacterCount(int by) {
3377
    if (character_count_ > String::kMaxLength - by) {
3378
      V8::FatalProcessOutOfMemory("String.replace result too large.");
3379
    }
3380
    character_count_ += by;
3381
  }
3382

    
3383
 private:
3384
  Handle<SeqOneByteString> NewRawOneByteString(int length) {
3385
    return heap_->isolate()->factory()->NewRawOneByteString(length);
3386
  }
3387

    
3388

    
3389
  Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
3390
    return heap_->isolate()->factory()->NewRawTwoByteString(length);
3391
  }
3392

    
3393

    
3394
  void AddElement(Object* element) {
3395
    ASSERT(element->IsSmi() || element->IsString());
3396
    ASSERT(array_builder_.capacity() > array_builder_.length());
3397
    array_builder_.Add(element);
3398
  }
3399

    
3400
  Heap* heap_;
3401
  FixedArrayBuilder array_builder_;
3402
  Handle<String> subject_;
3403
  int character_count_;
3404
  bool is_ascii_;
3405
};
3406

    
3407

    
3408
class CompiledReplacement {
3409
 public:
3410
  explicit CompiledReplacement(Zone* zone)
3411
      : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
3412

    
3413
  // Return whether the replacement is simple.
3414
  bool Compile(Handle<String> replacement,
3415
               int capture_count,
3416
               int subject_length);
3417

    
3418
  // Use Apply only if Compile returned false.
3419
  void Apply(ReplacementStringBuilder* builder,
3420
             int match_from,
3421
             int match_to,
3422
             int32_t* match);
3423

    
3424
  // Number of distinct parts of the replacement pattern.
3425
  int parts() {
3426
    return parts_.length();
3427
  }
3428

    
3429
  Zone* zone() const { return zone_; }
3430

    
3431
 private:
3432
  enum PartType {
3433
    SUBJECT_PREFIX = 1,
3434
    SUBJECT_SUFFIX,
3435
    SUBJECT_CAPTURE,
3436
    REPLACEMENT_SUBSTRING,
3437
    REPLACEMENT_STRING,
3438

    
3439
    NUMBER_OF_PART_TYPES
3440
  };
3441

    
3442
  struct ReplacementPart {
3443
    static inline ReplacementPart SubjectMatch() {
3444
      return ReplacementPart(SUBJECT_CAPTURE, 0);
3445
    }
3446
    static inline ReplacementPart SubjectCapture(int capture_index) {
3447
      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
3448
    }
3449
    static inline ReplacementPart SubjectPrefix() {
3450
      return ReplacementPart(SUBJECT_PREFIX, 0);
3451
    }
3452
    static inline ReplacementPart SubjectSuffix(int subject_length) {
3453
      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
3454
    }
3455
    static inline ReplacementPart ReplacementString() {
3456
      return ReplacementPart(REPLACEMENT_STRING, 0);
3457
    }
3458
    static inline ReplacementPart ReplacementSubString(int from, int to) {
3459
      ASSERT(from >= 0);
3460
      ASSERT(to > from);
3461
      return ReplacementPart(-from, to);
3462
    }
3463

    
3464
    // If tag <= 0 then it is the negation of a start index of a substring of
3465
    // the replacement pattern, otherwise it's a value from PartType.
3466
    ReplacementPart(int tag, int data)
3467
        : tag(tag), data(data) {
3468
      // Must be non-positive or a PartType value.
3469
      ASSERT(tag < NUMBER_OF_PART_TYPES);
3470
    }
3471
    // Either a value of PartType or a non-positive number that is
3472
    // the negation of an index into the replacement string.
3473
    int tag;
3474
    // The data value's interpretation depends on the value of tag:
3475
    // tag == SUBJECT_PREFIX ||
3476
    // tag == SUBJECT_SUFFIX:  data is unused.
3477
    // tag == SUBJECT_CAPTURE: data is the number of the capture.
3478
    // tag == REPLACEMENT_SUBSTRING ||
3479
    // tag == REPLACEMENT_STRING:    data is index into array of substrings
3480
    //                               of the replacement string.
3481
    // tag <= 0: Temporary representation of the substring of the replacement
3482
    //           string ranging over -tag .. data.
3483
    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
3484
    //           substring objects.
3485
    int data;
3486
  };
3487

    
3488
  template<typename Char>
3489
  bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
3490
                               Vector<Char> characters,
3491
                               int capture_count,
3492
                               int subject_length,
3493
                               Zone* zone) {
3494
    int length = characters.length();
3495
    int last = 0;
3496
    for (int i = 0; i < length; i++) {
3497
      Char c = characters[i];
3498
      if (c == '$') {
3499
        int next_index = i + 1;
3500
        if (next_index == length) {  // No next character!
3501
          break;
3502
        }
3503
        Char c2 = characters[next_index];
3504
        switch (c2) {
3505
        case '$':
3506
          if (i > last) {
3507
            // There is a substring before. Include the first "$".
3508
            parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
3509
                       zone);
3510
            last = next_index + 1;  // Continue after the second "$".
3511
          } else {
3512
            // Let the next substring start with the second "$".
3513
            last = next_index;
3514
          }
3515
          i = next_index;
3516
          break;
3517
        case '`':
3518
          if (i > last) {
3519
            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3520
          }
3521
          parts->Add(ReplacementPart::SubjectPrefix(), zone);
3522
          i = next_index;
3523
          last = i + 1;
3524
          break;
3525
        case '\'':
3526
          if (i > last) {
3527
            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3528
          }
3529
          parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
3530
          i = next_index;
3531
          last = i + 1;
3532
          break;
3533
        case '&':
3534
          if (i > last) {
3535
            parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3536
          }
3537
          parts->Add(ReplacementPart::SubjectMatch(), zone);
3538
          i = next_index;
3539
          last = i + 1;
3540
          break;
3541
        case '0':
3542
        case '1':
3543
        case '2':
3544
        case '3':
3545
        case '4':
3546
        case '5':
3547
        case '6':
3548
        case '7':
3549
        case '8':
3550
        case '9': {
3551
          int capture_ref = c2 - '0';
3552
          if (capture_ref > capture_count) {
3553
            i = next_index;
3554
            continue;
3555
          }
3556
          int second_digit_index = next_index + 1;
3557
          if (second_digit_index < length) {
3558
            // Peek ahead to see if we have two digits.
3559
            Char c3 = characters[second_digit_index];
3560
            if ('0' <= c3 && c3 <= '9') {  // Double digits.
3561
              int double_digit_ref = capture_ref * 10 + c3 - '0';
3562
              if (double_digit_ref <= capture_count) {
3563
                next_index = second_digit_index;
3564
                capture_ref = double_digit_ref;
3565
              }
3566
            }
3567
          }
3568
          if (capture_ref > 0) {
3569
            if (i > last) {
3570
              parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
3571
            }
3572
            ASSERT(capture_ref <= capture_count);
3573
            parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
3574
            last = next_index + 1;
3575
          }
3576
          i = next_index;
3577
          break;
3578
        }
3579
        default:
3580
          i = next_index;
3581
          break;
3582
        }
3583
      }
3584
    }
3585
    if (length > last) {
3586
      if (last == 0) {
3587
        // Replacement is simple.  Do not use Apply to do the replacement.
3588
        return true;
3589
      } else {
3590
        parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
3591
      }
3592
    }
3593
    return false;
3594
  }
3595

    
3596
  ZoneList<ReplacementPart> parts_;
3597
  ZoneList<Handle<String> > replacement_substrings_;
3598
  Zone* zone_;
3599
};
3600

    
3601

    
3602
bool CompiledReplacement::Compile(Handle<String> replacement,
3603
                                  int capture_count,
3604
                                  int subject_length) {
3605
  {
3606
    DisallowHeapAllocation no_gc;
3607
    String::FlatContent content = replacement->GetFlatContent();
3608
    ASSERT(content.IsFlat());
3609
    bool simple = false;
3610
    if (content.IsAscii()) {
3611
      simple = ParseReplacementPattern(&parts_,
3612
                                       content.ToOneByteVector(),
3613
                                       capture_count,
3614
                                       subject_length,
3615
                                       zone());
3616
    } else {
3617
      ASSERT(content.IsTwoByte());
3618
      simple = ParseReplacementPattern(&parts_,
3619
                                       content.ToUC16Vector(),
3620
                                       capture_count,
3621
                                       subject_length,
3622
                                       zone());
3623
    }
3624
    if (simple) return true;
3625
  }
3626

    
3627
  Isolate* isolate = replacement->GetIsolate();
3628
  // Find substrings of replacement string and create them as String objects.
3629
  int substring_index = 0;
3630
  for (int i = 0, n = parts_.length(); i < n; i++) {
3631
    int tag = parts_[i].tag;
3632
    if (tag <= 0) {  // A replacement string slice.
3633
      int from = -tag;
3634
      int to = parts_[i].data;
3635
      replacement_substrings_.Add(
3636
          isolate->factory()->NewSubString(replacement, from, to), zone());
3637
      parts_[i].tag = REPLACEMENT_SUBSTRING;
3638
      parts_[i].data = substring_index;
3639
      substring_index++;
3640
    } else if (tag == REPLACEMENT_STRING) {
3641
      replacement_substrings_.Add(replacement, zone());
3642
      parts_[i].data = substring_index;
3643
      substring_index++;
3644
    }
3645
  }
3646
  return false;
3647
}
3648

    
3649

    
3650
void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
3651
                                int match_from,
3652
                                int match_to,
3653
                                int32_t* match) {
3654
  ASSERT_LT(0, parts_.length());
3655
  for (int i = 0, n = parts_.length(); i < n; i++) {
3656
    ReplacementPart part = parts_[i];
3657
    switch (part.tag) {
3658
      case SUBJECT_PREFIX:
3659
        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
3660
        break;
3661
      case SUBJECT_SUFFIX: {
3662
        int subject_length = part.data;
3663
        if (match_to < subject_length) {
3664
          builder->AddSubjectSlice(match_to, subject_length);
3665
        }
3666
        break;
3667
      }
3668
      case SUBJECT_CAPTURE: {
3669
        int capture = part.data;
3670
        int from = match[capture * 2];
3671
        int to = match[capture * 2 + 1];
3672
        if (from >= 0 && to > from) {
3673
          builder->AddSubjectSlice(from, to);
3674
        }
3675
        break;
3676
      }
3677
      case REPLACEMENT_SUBSTRING:
3678
      case REPLACEMENT_STRING:
3679
        builder->AddString(replacement_substrings_[part.data]);
3680
        break;
3681
      default:
3682
        UNREACHABLE();
3683
    }
3684
  }
3685
}
3686

    
3687

    
3688
void FindAsciiStringIndices(Vector<const uint8_t> subject,
3689
                            char pattern,
3690
                            ZoneList<int>* indices,
3691
                            unsigned int limit,
3692
                            Zone* zone) {
3693
  ASSERT(limit > 0);
3694
  // Collect indices of pattern in subject using memchr.
3695
  // Stop after finding at most limit values.
3696
  const uint8_t* subject_start = subject.start();
3697
  const uint8_t* subject_end = subject_start + subject.length();
3698
  const uint8_t* pos = subject_start;
3699
  while (limit > 0) {
3700
    pos = reinterpret_cast<const uint8_t*>(
3701
        memchr(pos, pattern, subject_end - pos));
3702
    if (pos == NULL) return;
3703
    indices->Add(static_cast<int>(pos - subject_start), zone);
3704
    pos++;
3705
    limit--;
3706
  }
3707
}
3708

    
3709

    
3710
void FindTwoByteStringIndices(const Vector<const uc16> subject,
3711
                              uc16 pattern,
3712
                              ZoneList<int>* indices,
3713
                              unsigned int limit,
3714
                              Zone* zone) {
3715
  ASSERT(limit > 0);
3716
  const uc16* subject_start = subject.start();
3717
  const uc16* subject_end = subject_start + subject.length();
3718
  for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
3719
    if (*pos == pattern) {
3720
      indices->Add(static_cast<int>(pos - subject_start), zone);
3721
      limit--;
3722
    }
3723
  }
3724
}
3725

    
3726

    
3727
template <typename SubjectChar, typename PatternChar>
3728
void FindStringIndices(Isolate* isolate,
3729
                       Vector<const SubjectChar> subject,
3730
                       Vector<const PatternChar> pattern,
3731
                       ZoneList<int>* indices,
3732
                       unsigned int limit,
3733
                       Zone* zone) {
3734
  ASSERT(limit > 0);
3735
  // Collect indices of pattern in subject.
3736
  // Stop after finding at most limit values.
3737
  int pattern_length = pattern.length();
3738
  int index = 0;
3739
  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
3740
  while (limit > 0) {
3741
    index = search.Search(subject, index);
3742
    if (index < 0) return;
3743
    indices->Add(index, zone);
3744
    index += pattern_length;
3745
    limit--;
3746
  }
3747
}
3748

    
3749

    
3750
void FindStringIndicesDispatch(Isolate* isolate,
3751
                               String* subject,
3752
                               String* pattern,
3753
                               ZoneList<int>* indices,
3754
                               unsigned int limit,
3755
                               Zone* zone) {
3756
  {
3757
    DisallowHeapAllocation no_gc;
3758
    String::FlatContent subject_content = subject->GetFlatContent();
3759
    String::FlatContent pattern_content = pattern->GetFlatContent();
3760
    ASSERT(subject_content.IsFlat());
3761
    ASSERT(pattern_content.IsFlat());
3762
    if (subject_content.IsAscii()) {
3763
      Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
3764
      if (pattern_content.IsAscii()) {
3765
        Vector<const uint8_t> pattern_vector =
3766
            pattern_content.ToOneByteVector();
3767
        if (pattern_vector.length() == 1) {
3768
          FindAsciiStringIndices(subject_vector,
3769
                                 pattern_vector[0],
3770
                                 indices,
3771
                                 limit,
3772
                                 zone);
3773
        } else {
3774
          FindStringIndices(isolate,
3775
                            subject_vector,
3776
                            pattern_vector,
3777
                            indices,
3778
                            limit,
3779
                            zone);
3780
        }
3781
      } else {
3782
        FindStringIndices(isolate,
3783
                          subject_vector,
3784
                          pattern_content.ToUC16Vector(),
3785
                          indices,
3786
                          limit,
3787
                          zone);
3788
      }
3789
    } else {
3790
      Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
3791
      if (pattern_content.IsAscii()) {
3792
        Vector<const uint8_t> pattern_vector =
3793
            pattern_content.ToOneByteVector();
3794
        if (pattern_vector.length() == 1) {
3795
          FindTwoByteStringIndices(subject_vector,
3796
                                   pattern_vector[0],
3797
                                   indices,
3798
                                   limit,
3799
                                   zone);
3800
        } else {
3801
          FindStringIndices(isolate,
3802
                            subject_vector,
3803
                            pattern_vector,
3804
                            indices,
3805
                            limit,
3806
                            zone);
3807
        }
3808
      } else {
3809
        Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
3810
        if (pattern_vector.length() == 1) {
3811
          FindTwoByteStringIndices(subject_vector,
3812
                                   pattern_vector[0],
3813
                                   indices,
3814
                                   limit,
3815
                                   zone);
3816
        } else {
3817
          FindStringIndices(isolate,
3818
                            subject_vector,
3819
                            pattern_vector,
3820
                            indices,
3821
                            limit,
3822
                            zone);
3823
        }
3824
      }
3825
    }
3826
  }
3827
}
3828

    
3829

    
3830
template<typename ResultSeqString>
3831
MUST_USE_RESULT static MaybeObject* StringReplaceGlobalAtomRegExpWithString(
3832
    Isolate* isolate,
3833
    Handle<String> subject,
3834
    Handle<JSRegExp> pattern_regexp,
3835
    Handle<String> replacement,
3836
    Handle<JSArray> last_match_info) {
3837
  ASSERT(subject->IsFlat());
3838
  ASSERT(replacement->IsFlat());
3839

    
3840
  ZoneScope zone_scope(isolate->runtime_zone());
3841
  ZoneList<int> indices(8, zone_scope.zone());
3842
  ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
3843
  String* pattern =
3844
      String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
3845
  int subject_len = subject->length();
3846
  int pattern_len = pattern->length();
3847
  int replacement_len = replacement->length();
3848

    
3849
  FindStringIndicesDispatch(
3850
      isolate, *subject, pattern, &indices, 0xffffffff, zone_scope.zone());
3851

    
3852
  int matches = indices.length();
3853
  if (matches == 0) return *subject;
3854

    
3855
  // Detect integer overflow.
3856
  int64_t result_len_64 =
3857
      (static_cast<int64_t>(replacement_len) -
3858
       static_cast<int64_t>(pattern_len)) *
3859
      static_cast<int64_t>(matches) +
3860
      static_cast<int64_t>(subject_len);
3861
  if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(0x11);
3862
  int result_len = static_cast<int>(result_len_64);
3863

    
3864
  int subject_pos = 0;
3865
  int result_pos = 0;
3866

    
3867
  Handle<ResultSeqString> result;
3868
  if (ResultSeqString::kHasAsciiEncoding) {
3869
    result = Handle<ResultSeqString>::cast(
3870
        isolate->factory()->NewRawOneByteString(result_len));
3871
  } else {
3872
    result = Handle<ResultSeqString>::cast(
3873
        isolate->factory()->NewRawTwoByteString(result_len));
3874
  }
3875

    
3876
  for (int i = 0; i < matches; i++) {
3877
    // Copy non-matched subject content.
3878
    if (subject_pos < indices.at(i)) {
3879
      String::WriteToFlat(*subject,
3880
                          result->GetChars() + result_pos,
3881
                          subject_pos,
3882
                          indices.at(i));
3883
      result_pos += indices.at(i) - subject_pos;
3884
    }
3885

    
3886
    // Replace match.
3887
    if (replacement_len > 0) {
3888
      String::WriteToFlat(*replacement,
3889
                          result->GetChars() + result_pos,
3890
                          0,
3891
                          replacement_len);
3892
      result_pos += replacement_len;
3893
    }
3894

    
3895
    subject_pos = indices.at(i) + pattern_len;
3896
  }
3897
  // Add remaining subject content at the end.
3898
  if (subject_pos < subject_len) {
3899
    String::WriteToFlat(*subject,
3900
                        result->GetChars() + result_pos,
3901
                        subject_pos,
3902
                        subject_len);
3903
  }
3904

    
3905
  int32_t match_indices[] = { indices.at(matches - 1),
3906
                              indices.at(matches - 1) + pattern_len };
3907
  RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3908

    
3909
  return *result;
3910
}
3911

    
3912

    
3913
MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithString(
3914
    Isolate* isolate,
3915
    Handle<String> subject,
3916
    Handle<JSRegExp> regexp,
3917
    Handle<String> replacement,
3918
    Handle<JSArray> last_match_info) {
3919
  ASSERT(subject->IsFlat());
3920
  ASSERT(replacement->IsFlat());
3921

    
3922
  int capture_count = regexp->CaptureCount();
3923
  int subject_length = subject->length();
3924

    
3925
  // CompiledReplacement uses zone allocation.
3926
  ZoneScope zone_scope(isolate->runtime_zone());
3927
  CompiledReplacement compiled_replacement(zone_scope.zone());
3928
  bool simple_replace = compiled_replacement.Compile(replacement,
3929
                                                     capture_count,
3930
                                                     subject_length);
3931

    
3932
  // Shortcut for simple non-regexp global replacements
3933
  if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
3934
    if (subject->HasOnlyOneByteChars() &&
3935
        replacement->HasOnlyOneByteChars()) {
3936
      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
3937
          isolate, subject, regexp, replacement, last_match_info);
3938
    } else {
3939
      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
3940
          isolate, subject, regexp, replacement, last_match_info);
3941
    }
3942
  }
3943

    
3944
  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3945
  if (global_cache.HasException()) return Failure::Exception();
3946

    
3947
  int32_t* current_match = global_cache.FetchNext();
3948
  if (current_match == NULL) {
3949
    if (global_cache.HasException()) return Failure::Exception();
3950
    return *subject;
3951
  }
3952

    
3953
  // Guessing the number of parts that the final result string is built
3954
  // from. Global regexps can match any number of times, so we guess
3955
  // conservatively.
3956
  int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
3957
  ReplacementStringBuilder builder(isolate->heap(),
3958
                                   subject,
3959
                                   expected_parts);
3960

    
3961
  // Number of parts added by compiled replacement plus preceeding
3962
  // string and possibly suffix after last match.  It is possible for
3963
  // all components to use two elements when encoded as two smis.
3964
  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3965

    
3966
  int prev = 0;
3967

    
3968
  do {
3969
    builder.EnsureCapacity(parts_added_per_loop);
3970

    
3971
    int start = current_match[0];
3972
    int end = current_match[1];
3973

    
3974
    if (prev < start) {
3975
      builder.AddSubjectSlice(prev, start);
3976
    }
3977

    
3978
    if (simple_replace) {
3979
      builder.AddString(replacement);
3980
    } else {
3981
      compiled_replacement.Apply(&builder,
3982
                                 start,
3983
                                 end,
3984
                                 current_match);
3985
    }
3986
    prev = end;
3987

    
3988
    current_match = global_cache.FetchNext();
3989
  } while (current_match != NULL);
3990

    
3991
  if (global_cache.HasException()) return Failure::Exception();
3992

    
3993
  if (prev < subject_length) {
3994
    builder.EnsureCapacity(2);
3995
    builder.AddSubjectSlice(prev, subject_length);
3996
  }
3997

    
3998
  RegExpImpl::SetLastMatchInfo(last_match_info,
3999
                               subject,
4000
                               capture_count,
4001
                               global_cache.LastSuccessfulMatch());
4002

    
4003
  return *(builder.ToString());
4004
}
4005

    
4006

    
4007
template <typename ResultSeqString>
4008
MUST_USE_RESULT static MaybeObject* StringReplaceGlobalRegExpWithEmptyString(
4009
    Isolate* isolate,
4010
    Handle<String> subject,
4011
    Handle<JSRegExp> regexp,
4012
    Handle<JSArray> last_match_info) {
4013
  ASSERT(subject->IsFlat());
4014

    
4015
  // Shortcut for simple non-regexp global replacements
4016
  if (regexp->TypeTag() == JSRegExp::ATOM) {
4017
    Handle<String> empty_string = isolate->factory()->empty_string();
4018
    if (subject->IsOneByteRepresentation()) {
4019
      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
4020
          isolate, subject, regexp, empty_string, last_match_info);
4021
    } else {
4022
      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
4023
          isolate, subject, regexp, empty_string, last_match_info);
4024
    }
4025
  }
4026

    
4027
  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4028
  if (global_cache.HasException()) return Failure::Exception();
4029

    
4030
  int32_t* current_match = global_cache.FetchNext();
4031
  if (current_match == NULL) {
4032
    if (global_cache.HasException()) return Failure::Exception();
4033
    return *subject;
4034
  }
4035

    
4036
  int start = current_match[0];
4037
  int end = current_match[1];
4038
  int capture_count = regexp->CaptureCount();
4039
  int subject_length = subject->length();
4040

    
4041
  int new_length = subject_length - (end - start);
4042
  if (new_length == 0) return isolate->heap()->empty_string();
4043

    
4044
  Handle<ResultSeqString> answer;
4045
  if (ResultSeqString::kHasAsciiEncoding) {
4046
    answer = Handle<ResultSeqString>::cast(
4047
        isolate->factory()->NewRawOneByteString(new_length));
4048
  } else {
4049
    answer = Handle<ResultSeqString>::cast(
4050
        isolate->factory()->NewRawTwoByteString(new_length));
4051
  }
4052

    
4053
  int prev = 0;
4054
  int position = 0;
4055

    
4056
  do {
4057
    start = current_match[0];
4058
    end = current_match[1];
4059
    if (prev < start) {
4060
      // Add substring subject[prev;start] to answer string.
4061
      String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
4062
      position += start - prev;
4063
    }
4064
    prev = end;
4065

    
4066
    current_match = global_cache.FetchNext();
4067
  } while (current_match != NULL);
4068

    
4069
  if (global_cache.HasException()) return Failure::Exception();
4070

    
4071
  RegExpImpl::SetLastMatchInfo(last_match_info,
4072
                               subject,
4073
                               capture_count,
4074
                               global_cache.LastSuccessfulMatch());
4075

    
4076
  if (prev < subject_length) {
4077
    // Add substring subject[prev;length] to answer string.
4078
    String::WriteToFlat(
4079
        *subject, answer->GetChars() + position, prev, subject_length);
4080
    position += subject_length - prev;
4081
  }
4082

    
4083
  if (position == 0) return isolate->heap()->empty_string();
4084

    
4085
  // Shorten string and fill
4086
  int string_size = ResultSeqString::SizeFor(position);
4087
  int allocated_string_size = ResultSeqString::SizeFor(new_length);
4088
  int delta = allocated_string_size - string_size;
4089

    
4090
  answer->set_length(position);
4091
  if (delta == 0) return *answer;
4092

    
4093
  Address end_of_string = answer->address() + string_size;
4094
  isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
4095
  if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
4096
    MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
4097
  }
4098

    
4099
  return *answer;
4100
}
4101

    
4102

    
4103
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceGlobalRegExpWithString) {
4104
  HandleScope scope(isolate);
4105
  ASSERT(args.length() == 4);
4106

    
4107
  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4108
  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
4109
  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4110
  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
4111

    
4112
  ASSERT(regexp->GetFlags().is_global());
4113

    
4114
  if (!subject->IsFlat()) subject = FlattenGetString(subject);
4115

    
4116
  if (replacement->length() == 0) {
4117
    if (subject->HasOnlyOneByteChars()) {
4118
      return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
4119
          isolate, subject, regexp, last_match_info);
4120
    } else {
4121
      return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
4122
          isolate, subject, regexp, last_match_info);
4123
    }
4124
  }
4125

    
4126
  if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
4127

    
4128
  return StringReplaceGlobalRegExpWithString(
4129
      isolate, subject, regexp, replacement, last_match_info);
4130
}
4131

    
4132

    
4133
Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
4134
                                              Handle<String> subject,
4135
                                              Handle<String> search,
4136
                                              Handle<String> replace,
4137
                                              bool* found,
4138
                                              int recursion_limit) {
4139
  if (recursion_limit == 0) return Handle<String>::null();
4140
  if (subject->IsConsString()) {
4141
    ConsString* cons = ConsString::cast(*subject);
4142
    Handle<String> first = Handle<String>(cons->first());
4143
    Handle<String> second = Handle<String>(cons->second());
4144
    Handle<String> new_first =
4145
        StringReplaceOneCharWithString(isolate,
4146
                                       first,
4147
                                       search,
4148
                                       replace,
4149
                                       found,
4150
                                       recursion_limit - 1);
4151
    if (*found) return isolate->factory()->NewConsString(new_first, second);
4152
    if (new_first.is_null()) return new_first;
4153

    
4154
    Handle<String> new_second =
4155
        StringReplaceOneCharWithString(isolate,
4156
                                       second,
4157
                                       search,
4158
                                       replace,
4159
                                       found,
4160
                                       recursion_limit - 1);
4161
    if (*found) return isolate->factory()->NewConsString(first, new_second);
4162
    if (new_second.is_null()) return new_second;
4163

    
4164
    return subject;
4165
  } else {
4166
    int index = Runtime::StringMatch(isolate, subject, search, 0);
4167
    if (index == -1) return subject;
4168
    *found = true;
4169
    Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
4170
    Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
4171
    Handle<String> second =
4172
        isolate->factory()->NewSubString(subject, index + 1, subject->length());
4173
    return isolate->factory()->NewConsString(cons1, second);
4174
  }
4175
}
4176

    
4177

    
4178
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
4179
  HandleScope scope(isolate);
4180
  ASSERT(args.length() == 3);
4181
  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4182
  CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
4183
  CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
4184

    
4185
  // If the cons string tree is too deep, we simply abort the recursion and
4186
  // retry with a flattened subject string.
4187
  const int kRecursionLimit = 0x1000;
4188
  bool found = false;
4189
  Handle<String> result = StringReplaceOneCharWithString(isolate,
4190
                                                         subject,
4191
                                                         search,
4192
                                                         replace,
4193
                                                         &found,
4194
                                                         kRecursionLimit);
4195
  if (!result.is_null()) return *result;
4196
  return *StringReplaceOneCharWithString(isolate,
4197
                                         FlattenGetString(subject),
4198
                                         search,
4199
                                         replace,
4200
                                         &found,
4201
                                         kRecursionLimit);
4202
}
4203

    
4204

    
4205
// Perform string match of pattern on subject, starting at start index.
4206
// Caller must ensure that 0 <= start_index <= sub->length(),
4207
// and should check that pat->length() + start_index <= sub->length().
4208
int Runtime::StringMatch(Isolate* isolate,
4209
                         Handle<String> sub,
4210
                         Handle<String> pat,
4211
                         int start_index) {
4212
  ASSERT(0 <= start_index);
4213
  ASSERT(start_index <= sub->length());
4214

    
4215
  int pattern_length = pat->length();
4216
  if (pattern_length == 0) return start_index;
4217

    
4218
  int subject_length = sub->length();
4219
  if (start_index + pattern_length > subject_length) return -1;
4220

    
4221
  if (!sub->IsFlat()) FlattenString(sub);
4222
  if (!pat->IsFlat()) FlattenString(pat);
4223

    
4224
  DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4225
  // Extract flattened substrings of cons strings before determining asciiness.
4226
  String::FlatContent seq_sub = sub->GetFlatContent();
4227
  String::FlatContent seq_pat = pat->GetFlatContent();
4228

    
4229
  // dispatch on type of strings
4230
  if (seq_pat.IsAscii()) {
4231
    Vector<const uint8_t> pat_vector = seq_pat.ToOneByteVector();
4232
    if (seq_sub.IsAscii()) {
4233
      return SearchString(isolate,
4234
                          seq_sub.ToOneByteVector(),
4235
                          pat_vector,
4236
                          start_index);
4237
    }
4238
    return SearchString(isolate,
4239
                        seq_sub.ToUC16Vector(),
4240
                        pat_vector,
4241
                        start_index);
4242
  }
4243
  Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
4244
  if (seq_sub.IsAscii()) {
4245
    return SearchString(isolate,
4246
                        seq_sub.ToOneByteVector(),
4247
                        pat_vector,
4248
                        start_index);
4249
  }
4250
  return SearchString(isolate,
4251
                      seq_sub.ToUC16Vector(),
4252
                      pat_vector,
4253
                      start_index);
4254
}
4255

    
4256

    
4257
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
4258
  HandleScope scope(isolate);
4259
  ASSERT(args.length() == 3);
4260

    
4261
  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4262
  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4263

    
4264
  Object* index = args[2];
4265
  uint32_t start_index;
4266
  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4267

    
4268
  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
4269
  int position =
4270
      Runtime::StringMatch(isolate, sub, pat, start_index);
4271
  return Smi::FromInt(position);
4272
}
4273

    
4274

    
4275
template <typename schar, typename pchar>
4276
static int StringMatchBackwards(Vector<const schar> subject,
4277
                                Vector<const pchar> pattern,
4278
                                int idx) {
4279
  int pattern_length = pattern.length();
4280
  ASSERT(pattern_length >= 1);
4281
  ASSERT(idx + pattern_length <= subject.length());
4282

    
4283
  if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
4284
    for (int i = 0; i < pattern_length; i++) {
4285
      uc16 c = pattern[i];
4286
      if (c > String::kMaxOneByteCharCode) {
4287
        return -1;
4288
      }
4289
    }
4290
  }
4291

    
4292
  pchar pattern_first_char = pattern[0];
4293
  for (int i = idx; i >= 0; i--) {
4294
    if (subject[i] != pattern_first_char) continue;
4295
    int j = 1;
4296
    while (j < pattern_length) {
4297
      if (pattern[j] != subject[i+j]) {
4298
        break;
4299
      }
4300
      j++;
4301
    }
4302
    if (j == pattern_length) {
4303
      return i;
4304
    }
4305
  }
4306
  return -1;
4307
}
4308

    
4309

    
4310
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
4311
  HandleScope scope(isolate);
4312
  ASSERT(args.length() == 3);
4313

    
4314
  CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
4315
  CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
4316

    
4317
  Object* index = args[2];
4318
  uint32_t start_index;
4319
  if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
4320

    
4321
  uint32_t pat_length = pat->length();
4322
  uint32_t sub_length = sub->length();
4323

    
4324
  if (start_index + pat_length > sub_length) {
4325
    start_index = sub_length - pat_length;
4326
  }
4327

    
4328
  if (pat_length == 0) {
4329
    return Smi::FromInt(start_index);
4330
  }
4331

    
4332
  if (!sub->IsFlat()) FlattenString(sub);
4333
  if (!pat->IsFlat()) FlattenString(pat);
4334

    
4335
  int position = -1;
4336
  DisallowHeapAllocation no_gc;  // ensure vectors stay valid
4337

    
4338
  String::FlatContent sub_content = sub->GetFlatContent();
4339
  String::FlatContent pat_content = pat->GetFlatContent();
4340

    
4341
  if (pat_content.IsAscii()) {
4342
    Vector<const uint8_t> pat_vector = pat_content.ToOneByteVector();
4343
    if (sub_content.IsAscii()) {
4344
      position = StringMatchBackwards(sub_content.ToOneByteVector(),
4345
                                      pat_vector,
4346
                                      start_index);
4347
    } else {
4348
      position = StringMatchBackwards(sub_content.ToUC16Vector(),
4349
                                      pat_vector,
4350
                                      start_index);
4351
    }
4352
  } else {
4353
    Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
4354
    if (sub_content.IsAscii()) {
4355
      position = StringMatchBackwards(sub_content.ToOneByteVector(),
4356
                                      pat_vector,
4357
                                      start_index);
4358
    } else {
4359
      position = StringMatchBackwards(sub_content.ToUC16Vector(),
4360
                                      pat_vector,
4361
                                      start_index);
4362
    }
4363
  }
4364

    
4365
  return Smi::FromInt(position);
4366
}
4367

    
4368

    
4369
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
4370
  SealHandleScope shs(isolate);
4371
  ASSERT(args.length() == 2);
4372

    
4373
  CONVERT_ARG_CHECKED(String, str1, 0);
4374
  CONVERT_ARG_CHECKED(String, str2, 1);
4375

    
4376
  if (str1 == str2) return Smi::FromInt(0);  // Equal.
4377
  int str1_length = str1->length();
4378
  int str2_length = str2->length();
4379

    
4380
  // Decide trivial cases without flattening.
4381
  if (str1_length == 0) {
4382
    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
4383
    return Smi::FromInt(-str2_length);
4384
  } else {
4385
    if (str2_length == 0) return Smi::FromInt(str1_length);
4386
  }
4387

    
4388
  int end = str1_length < str2_length ? str1_length : str2_length;
4389

    
4390
  // No need to flatten if we are going to find the answer on the first
4391
  // character.  At this point we know there is at least one character
4392
  // in each string, due to the trivial case handling above.
4393
  int d = str1->Get(0) - str2->Get(0);
4394
  if (d != 0) return Smi::FromInt(d);
4395

    
4396
  str1->TryFlatten();
4397
  str2->TryFlatten();
4398

    
4399
  ConsStringIteratorOp* op1 =
4400
      isolate->runtime_state()->string_locale_compare_it1();
4401
  ConsStringIteratorOp* op2 =
4402
      isolate->runtime_state()->string_locale_compare_it2();
4403
  // TODO(dcarney) Can do array compares here more efficiently.
4404
  StringCharacterStream stream1(str1, op1);
4405
  StringCharacterStream stream2(str2, op2);
4406

    
4407
  for (int i = 0; i < end; i++) {
4408
    uint16_t char1 = stream1.GetNext();
4409
    uint16_t char2 = stream2.GetNext();
4410
    if (char1 != char2) return Smi::FromInt(char1 - char2);
4411
  }
4412

    
4413
  return Smi::FromInt(str1_length - str2_length);
4414
}
4415

    
4416

    
4417
RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
4418
  SealHandleScope shs(isolate);
4419
  ASSERT(args.length() == 3);
4420

    
4421
  CONVERT_ARG_CHECKED(String, value, 0);
4422
  int start, end;
4423
  // We have a fast integer-only case here to avoid a conversion to double in
4424
  // the common case where from and to are Smis.
4425
  if (args[1]->IsSmi() && args[2]->IsSmi()) {
4426
    CONVERT_SMI_ARG_CHECKED(from_number, 1);
4427
    CONVERT_SMI_ARG_CHECKED(to_number, 2);
4428
    start = from_number;
4429
    end = to_number;
4430
  } else {
4431
    CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
4432
    CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
4433
    start = FastD2IChecked(from_number);
4434
    end = FastD2IChecked(to_number);
4435
  }
4436
  RUNTIME_ASSERT(end >= start);
4437
  RUNTIME_ASSERT(start >= 0);
4438
  RUNTIME_ASSERT(end <= value->length());
4439
  isolate->counters()->sub_string_runtime()->Increment();
4440
  if (end - start == 1) {
4441
     return isolate->heap()->LookupSingleCharacterStringFromCode(
4442
         value->Get(start));
4443
  }
4444
  return value->SubString(start, end);
4445
}
4446

    
4447

    
4448
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
4449
  HandleScope handles(isolate);
4450
  ASSERT_EQ(3, args.length());
4451

    
4452
  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
4453
  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
4454
  CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
4455

    
4456
  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4457
  if (global_cache.HasException()) return Failure::Exception();
4458

    
4459
  int capture_count = regexp->CaptureCount();
4460

    
4461
  ZoneScope zone_scope(isolate->runtime_zone());
4462
  ZoneList<int> offsets(8, zone_scope.zone());
4463

    
4464
  while (true) {
4465
    int32_t* match = global_cache.FetchNext();
4466
    if (match == NULL) break;
4467
    offsets.Add(match[0], zone_scope.zone());  // start
4468
    offsets.Add(match[1], zone_scope.zone());  // end
4469
  }
4470

    
4471
  if (global_cache.HasException()) return Failure::Exception();
4472

    
4473
  if (offsets.length() == 0) {
4474
    // Not a single match.
4475
    return isolate->heap()->null_value();
4476
  }
4477

    
4478
  RegExpImpl::SetLastMatchInfo(regexp_info,
4479
                               subject,
4480
                               capture_count,
4481
                               global_cache.LastSuccessfulMatch());
4482

    
4483
  int matches = offsets.length() / 2;
4484
  Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
4485
  Handle<String> substring =
4486
      isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
4487
  elements->set(0, *substring);
4488
  for (int i = 1; i < matches; i++) {
4489
    HandleScope temp_scope(isolate);
4490
    int from = offsets.at(i * 2);
4491
    int to = offsets.at(i * 2 + 1);
4492
    Handle<String> substring =
4493
        isolate->factory()->NewProperSubString(subject, from, to);
4494
    elements->set(i, *substring);
4495
  }
4496
  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
4497
  result->set_length(Smi::FromInt(matches));
4498
  return *result;
4499
}
4500

    
4501

    
4502
// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
4503
// separate last match info.  See comment on that function.
4504
template<bool has_capture>
4505
static MaybeObject* SearchRegExpMultiple(
4506
    Isolate* isolate,
4507
    Handle<String> subject,
4508
    Handle<JSRegExp> regexp,
4509
    Handle<JSArray> last_match_array,
4510
    Handle<JSArray> result_array) {
4511
  ASSERT(subject->IsFlat());
4512
  ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
4513

    
4514
  int capture_count = regexp->CaptureCount();
4515
  int subject_length = subject->length();
4516

    
4517
  static const int kMinLengthToCache = 0x1000;
4518

    
4519
  if (subject_length > kMinLengthToCache) {
4520
    Handle<Object> cached_answer(RegExpResultsCache::Lookup(
4521
        isolate->heap(),
4522
        *subject,
4523
        regexp->data(),
4524
        RegExpResultsCache::REGEXP_MULTIPLE_INDICES), isolate);
4525
    if (*cached_answer != Smi::FromInt(0)) {
4526
      Handle<FixedArray> cached_fixed_array =
4527
          Handle<FixedArray>(FixedArray::cast(*cached_answer));
4528
      // The cache FixedArray is a COW-array and can therefore be reused.
4529
      isolate->factory()->SetContent(result_array, cached_fixed_array);
4530
      // The actual length of the result array is stored in the last element of
4531
      // the backing store (the backing FixedArray may have a larger capacity).
4532
      Object* cached_fixed_array_last_element =
4533
          cached_fixed_array->get(cached_fixed_array->length() - 1);
4534
      Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
4535
      result_array->set_length(js_array_length);
4536
      RegExpImpl::SetLastMatchInfo(
4537
          last_match_array, subject, capture_count, NULL);
4538
      return *result_array;
4539
    }
4540
  }
4541

    
4542
  RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
4543
  if (global_cache.HasException()) return Failure::Exception();
4544

    
4545
  Handle<FixedArray> result_elements;
4546
  if (result_array->HasFastObjectElements()) {
4547
    result_elements =
4548
        Handle<FixedArray>(FixedArray::cast(result_array->elements()));
4549
  }
4550
  if (result_elements.is_null() || result_elements->length() < 16) {
4551
    result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
4552
  }
4553

    
4554
  FixedArrayBuilder builder(result_elements);
4555

    
4556
  // Position to search from.
4557
  int match_start = -1;
4558
  int match_end = 0;
4559
  bool first = true;
4560

    
4561
  // Two smis before and after the match, for very long strings.
4562
  static const int kMaxBuilderEntriesPerRegExpMatch = 5;
4563

    
4564
  while (true) {
4565
    int32_t* current_match = global_cache.FetchNext();
4566
    if (current_match == NULL) break;
4567
    match_start = current_match[0];
4568
    builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
4569
    if (match_end < match_start) {
4570
      ReplacementStringBuilder::AddSubjectSlice(&builder,
4571
                                                match_end,
4572
                                                match_start);
4573
    }
4574
    match_end = current_match[1];
4575
    {
4576
      // Avoid accumulating new handles inside loop.
4577
      HandleScope temp_scope(isolate);
4578
      Handle<String> match;
4579
      if (!first) {
4580
        match = isolate->factory()->NewProperSubString(subject,
4581
                                                       match_start,
4582
                                                       match_end);
4583
      } else {
4584
        match = isolate->factory()->NewSubString(subject,
4585
                                                 match_start,
4586
                                                 match_end);
4587
        first = false;
4588
      }
4589

    
4590
      if (has_capture) {
4591
        // Arguments array to replace function is match, captures, index and
4592
        // subject, i.e., 3 + capture count in total.
4593
        Handle<FixedArray> elements =
4594
            isolate->factory()->NewFixedArray(3 + capture_count);
4595

    
4596
        elements->set(0, *match);
4597
        for (int i = 1; i <= capture_count; i++) {
4598
          int start = current_match[i * 2];
4599
          if (start >= 0) {
4600
            int end = current_match[i * 2 + 1];
4601
            ASSERT(start <= end);
4602
            Handle<String> substring =
4603
                isolate->factory()->NewSubString(subject, start, end);
4604
            elements->set(i, *substring);
4605
          } else {
4606
            ASSERT(current_match[i * 2 + 1] < 0);
4607
            elements->set(i, isolate->heap()->undefined_value());
4608
          }
4609
        }
4610
        elements->set(capture_count + 1, Smi::FromInt(match_start));
4611
        elements->set(capture_count + 2, *subject);
4612
        builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
4613
      } else {
4614
        builder.Add(*match);
4615
      }
4616
    }
4617
  }
4618

    
4619
  if (global_cache.HasException()) return Failure::Exception();
4620

    
4621
  if (match_start >= 0) {
4622
    // Finished matching, with at least one match.
4623
    if (match_end < subject_length) {
4624
      ReplacementStringBuilder::AddSubjectSlice(&builder,
4625
                                                match_end,
4626
                                                subject_length);
4627
    }
4628

    
4629
    RegExpImpl::SetLastMatchInfo(
4630
        last_match_array, subject, capture_count, NULL);
4631

    
4632
    if (subject_length > kMinLengthToCache) {
4633
      // Store the length of the result array into the last element of the
4634
      // backing FixedArray.
4635
      builder.EnsureCapacity(1);
4636
      Handle<FixedArray> fixed_array = builder.array();
4637
      fixed_array->set(fixed_array->length() - 1,
4638
                       Smi::FromInt(builder.length()));
4639
      // Cache the result and turn the FixedArray into a COW array.
4640
      RegExpResultsCache::Enter(isolate->heap(),
4641
                                *subject,
4642
                                regexp->data(),
4643
                                *fixed_array,
4644
                                RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
4645
    }
4646
    return *builder.ToJSArray(result_array);
4647
  } else {
4648
    return isolate->heap()->null_value();  // No matches at all.
4649
  }
4650
}
4651

    
4652

    
4653
// This is only called for StringReplaceGlobalRegExpWithFunction.  This sets
4654
// lastMatchInfoOverride to maintain the last match info, so we don't need to
4655
// set any other last match array info.
4656
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
4657
  HandleScope handles(isolate);
4658
  ASSERT(args.length() == 4);
4659

    
4660
  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
4661
  if (!subject->IsFlat()) FlattenString(subject);
4662
  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
4663
  CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
4664
  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
4665

    
4666
  ASSERT(regexp->GetFlags().is_global());
4667

    
4668
  if (regexp->CaptureCount() == 0) {
4669
    return SearchRegExpMultiple<false>(
4670
        isolate, subject, regexp, last_match_info, result_array);
4671
  } else {
4672
    return SearchRegExpMultiple<true>(
4673
        isolate, subject, regexp, last_match_info, result_array);
4674
  }
4675
}
4676

    
4677

    
4678
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
4679
  SealHandleScope shs(isolate);
4680
  ASSERT(args.length() == 2);
4681
  CONVERT_SMI_ARG_CHECKED(radix, 1);
4682
  RUNTIME_ASSERT(2 <= radix && radix <= 36);
4683

    
4684
  // Fast case where the result is a one character string.
4685
  if (args[0]->IsSmi()) {
4686
    int value = args.smi_at(0);
4687
    if (value >= 0 && value < radix) {
4688
      // Character array used for conversion.
4689
      static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
4690
      return isolate->heap()->
4691
          LookupSingleCharacterStringFromCode(kCharTable[value]);
4692
    }
4693
  }
4694

    
4695
  // Slow case.
4696
  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4697
  if (std::isnan(value)) {
4698
    return *isolate->factory()->nan_string();
4699
  }
4700
  if (std::isinf(value)) {
4701
    if (value < 0) {
4702
      return *isolate->factory()->minus_infinity_string();
4703
    }
4704
    return *isolate->factory()->infinity_string();
4705
  }
4706
  char* str = DoubleToRadixCString(value, radix);
4707
  MaybeObject* result =
4708
      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4709
  DeleteArray(str);
4710
  return result;
4711
}
4712

    
4713

    
4714
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
4715
  SealHandleScope shs(isolate);
4716
  ASSERT(args.length() == 2);
4717

    
4718
  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4719
  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4720
  int f = FastD2IChecked(f_number);
4721
  RUNTIME_ASSERT(f >= 0);
4722
  char* str = DoubleToFixedCString(value, f);
4723
  MaybeObject* res =
4724
      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4725
  DeleteArray(str);
4726
  return res;
4727
}
4728

    
4729

    
4730
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
4731
  SealHandleScope shs(isolate);
4732
  ASSERT(args.length() == 2);
4733

    
4734
  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4735
  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4736
  int f = FastD2IChecked(f_number);
4737
  RUNTIME_ASSERT(f >= -1 && f <= 20);
4738
  char* str = DoubleToExponentialCString(value, f);
4739
  MaybeObject* res =
4740
      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4741
  DeleteArray(str);
4742
  return res;
4743
}
4744

    
4745

    
4746
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
4747
  SealHandleScope shs(isolate);
4748
  ASSERT(args.length() == 2);
4749

    
4750
  CONVERT_DOUBLE_ARG_CHECKED(value, 0);
4751
  CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
4752
  int f = FastD2IChecked(f_number);
4753
  RUNTIME_ASSERT(f >= 1 && f <= 21);
4754
  char* str = DoubleToPrecisionCString(value, f);
4755
  MaybeObject* res =
4756
      isolate->heap()->AllocateStringFromOneByte(CStrVector(str));
4757
  DeleteArray(str);
4758
  return res;
4759
}
4760

    
4761

    
4762
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsValidSmi) {
4763
  HandleScope shs(isolate);
4764
  ASSERT(args.length() == 1);
4765

    
4766
  CONVERT_NUMBER_CHECKED(int32_t, number, Int32, args[0]);
4767
  if (Smi::IsValid(number)) {
4768
    return isolate->heap()->true_value();
4769
  } else {
4770
    return isolate->heap()->false_value();
4771
  }
4772
}
4773

    
4774

    
4775
// Returns a single character string where first character equals
4776
// string->Get(index).
4777
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
4778
  if (index < static_cast<uint32_t>(string->length())) {
4779
    string->TryFlatten();
4780
    return LookupSingleCharacterStringFromCode(
4781
        string->GetIsolate(),
4782
        string->Get(index));
4783
  }
4784
  return Execution::CharAt(string, index);
4785
}
4786

    
4787

    
4788
MaybeObject* Runtime::GetElementOrCharAtOrFail(Isolate* isolate,
4789
                                               Handle<Object> object,
4790
                                               uint32_t index) {
4791
  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4792
      GetElementOrCharAt(isolate, object, index));
4793
}
4794

    
4795

    
4796
MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
4797
                                         Handle<Object> object,
4798
                                         uint32_t index) {
4799
  // Handle [] indexing on Strings
4800
  if (object->IsString()) {
4801
    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
4802
    if (!result->IsUndefined()) return *result;
4803
  }
4804

    
4805
  // Handle [] indexing on String objects
4806
  if (object->IsStringObjectWithCharacterAt(index)) {
4807
    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
4808
    Handle<Object> result =
4809
        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
4810
    if (!result->IsUndefined()) return *result;
4811
  }
4812

    
4813
  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
4814
    return object->GetPrototype(isolate)->GetElement(isolate, index);
4815
  }
4816

    
4817
  return object->GetElement(isolate, index);
4818
}
4819

    
4820

    
4821
MaybeObject* Runtime::HasObjectProperty(Isolate* isolate,
4822
                                        Handle<JSReceiver> object,
4823
                                        Handle<Object> key) {
4824
  HandleScope scope(isolate);
4825

    
4826
  // Check if the given key is an array index.
4827
  uint32_t index;
4828
  if (key->ToArrayIndex(&index)) {
4829
    return isolate->heap()->ToBoolean(JSReceiver::HasElement(object, index));
4830
  }
4831

    
4832
  // Convert the key to a name - possibly by calling back into JavaScript.
4833
  Handle<Name> name;
4834
  if (key->IsName()) {
4835
    name = Handle<Name>::cast(key);
4836
  } else {
4837
    bool has_pending_exception = false;
4838
    Handle<Object> converted =
4839
        Execution::ToString(isolate, key, &has_pending_exception);
4840
    if (has_pending_exception) return Failure::Exception();
4841
    name = Handle<Name>::cast(converted);
4842
  }
4843

    
4844
  return isolate->heap()->ToBoolean(JSReceiver::HasProperty(object, name));
4845
}
4846

    
4847
MaybeObject* Runtime::GetObjectPropertyOrFail(
4848
    Isolate* isolate,
4849
    Handle<Object> object,
4850
    Handle<Object> key) {
4851
  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
4852
      GetObjectProperty(isolate, object, key));
4853
}
4854

    
4855
MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
4856
                                        Handle<Object> object,
4857
                                        Handle<Object> key) {
4858
  HandleScope scope(isolate);
4859

    
4860
  if (object->IsUndefined() || object->IsNull()) {
4861
    Handle<Object> args[2] = { key, object };
4862
    Handle<Object> error =
4863
        isolate->factory()->NewTypeError("non_object_property_load",
4864
                                         HandleVector(args, 2));
4865
    return isolate->Throw(*error);
4866
  }
4867

    
4868
  // Check if the given key is an array index.
4869
  uint32_t index;
4870
  if (key->ToArrayIndex(&index)) {
4871
    return GetElementOrCharAt(isolate, object, index);
4872
  }
4873

    
4874
  // Convert the key to a name - possibly by calling back into JavaScript.
4875
  Handle<Name> name;
4876
  if (key->IsName()) {
4877
    name = Handle<Name>::cast(key);
4878
  } else {
4879
    bool has_pending_exception = false;
4880
    Handle<Object> converted =
4881
        Execution::ToString(isolate, key, &has_pending_exception);
4882
    if (has_pending_exception) return Failure::Exception();
4883
    name = Handle<Name>::cast(converted);
4884
  }
4885

    
4886
  // Check if the name is trivially convertible to an index and get
4887
  // the element if so.
4888
  if (name->AsArrayIndex(&index)) {
4889
    return GetElementOrCharAt(isolate, object, index);
4890
  } else {
4891
    return object->GetProperty(*name);
4892
  }
4893
}
4894

    
4895

    
4896
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4897
  SealHandleScope shs(isolate);
4898
  ASSERT(args.length() == 2);
4899

    
4900
  Handle<Object> object = args.at<Object>(0);
4901
  Handle<Object> key = args.at<Object>(1);
4902

    
4903
  return Runtime::GetObjectProperty(isolate, object, key);
4904
}
4905

    
4906

    
4907
// KeyedGetProperty is called from KeyedLoadIC::GenerateGeneric.
4908
RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4909
  SealHandleScope shs(isolate);
4910
  ASSERT(args.length() == 2);
4911

    
4912
  // Fast cases for getting named properties of the receiver JSObject
4913
  // itself.
4914
  //
4915
  // The global proxy objects has to be excluded since LocalLookup on
4916
  // the global proxy object can return a valid result even though the
4917
  // global proxy object never has properties.  This is the case
4918
  // because the global proxy object forwards everything to its hidden
4919
  // prototype including local lookups.
4920
  //
4921
  // Additionally, we need to make sure that we do not cache results
4922
  // for objects that require access checks.
4923
  if (args[0]->IsJSObject()) {
4924
    if (!args[0]->IsJSGlobalProxy() &&
4925
        !args[0]->IsAccessCheckNeeded() &&
4926
        args[1]->IsName()) {
4927
      JSObject* receiver = JSObject::cast(args[0]);
4928
      Name* key = Name::cast(args[1]);
4929
      if (receiver->HasFastProperties()) {
4930
        // Attempt to use lookup cache.
4931
        Map* receiver_map = receiver->map();
4932
        KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4933
        int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4934
        if (offset != -1) {
4935
          // Doubles are not cached, so raw read the value.
4936
          Object* value = receiver->RawFastPropertyAt(offset);
4937
          return value->IsTheHole()
4938
              ? isolate->heap()->undefined_value()
4939
              : value;
4940
        }
4941
        // Lookup cache miss.  Perform lookup and update the cache if
4942
        // appropriate.
4943
        LookupResult result(isolate);
4944
        receiver->LocalLookup(key, &result);
4945
        if (result.IsField()) {
4946
          int offset = result.GetFieldIndex().field_index();
4947
          // Do not track double fields in the keyed lookup cache. Reading
4948
          // double values requires boxing.
4949
          if (!FLAG_track_double_fields ||
4950
              !result.representation().IsDouble()) {
4951
            keyed_lookup_cache->Update(receiver_map, key, offset);
4952
          }
4953
          return receiver->FastPropertyAt(result.representation(), offset);
4954
        }
4955
      } else {
4956
        // Attempt dictionary lookup.
4957
        NameDictionary* dictionary = receiver->property_dictionary();
4958
        int entry = dictionary->FindEntry(key);
4959
        if ((entry != NameDictionary::kNotFound) &&
4960
            (dictionary->DetailsAt(entry).type() == NORMAL)) {
4961
          Object* value = dictionary->ValueAt(entry);
4962
          if (!receiver->IsGlobalObject()) return value;
4963
          value = PropertyCell::cast(value)->value();
4964
          if (!value->IsTheHole()) return value;
4965
          // If value is the hole do the general lookup.
4966
        }
4967
      }
4968
    } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4969
      // JSObject without a name key. If the key is a Smi, check for a
4970
      // definite out-of-bounds access to elements, which is a strong indicator
4971
      // that subsequent accesses will also call the runtime. Proactively
4972
      // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4973
      // doubles for those future calls in the case that the elements would
4974
      // become FAST_DOUBLE_ELEMENTS.
4975
      Handle<JSObject> js_object(args.at<JSObject>(0));
4976
      ElementsKind elements_kind = js_object->GetElementsKind();
4977
      if (IsFastDoubleElementsKind(elements_kind)) {
4978
        FixedArrayBase* elements = js_object->elements();
4979
        if (args.at<Smi>(1)->value() >= elements->length()) {
4980
          if (IsFastHoleyElementsKind(elements_kind)) {
4981
            elements_kind = FAST_HOLEY_ELEMENTS;
4982
          } else {
4983
            elements_kind = FAST_ELEMENTS;
4984
          }
4985
          MaybeObject* maybe_object = TransitionElements(js_object,
4986
                                                         elements_kind,
4987
                                                         isolate);
4988
          if (maybe_object->IsFailure()) return maybe_object;
4989
        }
4990
      } else {
4991
        ASSERT(IsFastSmiOrObjectElementsKind(elements_kind) ||
4992
               !IsFastElementsKind(elements_kind));
4993
      }
4994
    }
4995
  } else if (args[0]->IsString() && args[1]->IsSmi()) {
4996
    // Fast case for string indexing using [] with a smi index.
4997
    HandleScope scope(isolate);
4998
    Handle<String> str = args.at<String>(0);
4999
    int index = args.smi_at(1);
5000
    if (index >= 0 && index < str->length()) {
5001
      Handle<Object> result = GetCharAt(str, index);
5002
      return *result;
5003
    }
5004
  }
5005

    
5006
  // Fall back to GetObjectProperty.
5007
  return Runtime::GetObjectProperty(isolate,
5008
                                    args.at<Object>(0),
5009
                                    args.at<Object>(1));
5010
}
5011

    
5012

    
5013
static bool IsValidAccessor(Handle<Object> obj) {
5014
  return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
5015
}
5016

    
5017

    
5018
// Implements part of 8.12.9 DefineOwnProperty.
5019
// There are 3 cases that lead here:
5020
// Step 4b - define a new accessor property.
5021
// Steps 9c & 12 - replace an existing data property with an accessor property.
5022
// Step 12 - update an existing accessor property with an accessor or generic
5023
//           descriptor.
5024
RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
5025
  HandleScope scope(isolate);
5026
  ASSERT(args.length() == 5);
5027
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5028
  RUNTIME_ASSERT(!obj->IsNull());
5029
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5030
  CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
5031
  RUNTIME_ASSERT(IsValidAccessor(getter));
5032
  CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
5033
  RUNTIME_ASSERT(IsValidAccessor(setter));
5034
  CONVERT_SMI_ARG_CHECKED(unchecked, 4);
5035
  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5036
  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5037

    
5038
  bool fast = obj->HasFastProperties();
5039
  JSObject::DefineAccessor(obj, name, getter, setter, attr);
5040
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5041
  if (fast) JSObject::TransformToFastProperties(obj, 0);
5042
  return isolate->heap()->undefined_value();
5043
}
5044

    
5045

    
5046
// Implements part of 8.12.9 DefineOwnProperty.
5047
// There are 3 cases that lead here:
5048
// Step 4a - define a new data property.
5049
// Steps 9b & 12 - replace an existing accessor property with a data property.
5050
// Step 12 - update an existing data property with a data or generic
5051
//           descriptor.
5052
RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
5053
  HandleScope scope(isolate);
5054
  ASSERT(args.length() == 4);
5055
  CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
5056
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5057
  CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
5058
  CONVERT_SMI_ARG_CHECKED(unchecked, 3);
5059
  RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5060
  PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
5061

    
5062
  LookupResult result(isolate);
5063
  js_object->LocalLookupRealNamedProperty(*name, &result);
5064

    
5065
  // Special case for callback properties.
5066
  if (result.IsPropertyCallbacks()) {
5067
    Object* callback = result.GetCallbackObject();
5068
    // To be compatible with Safari we do not change the value on API objects
5069
    // in Object.defineProperty(). Firefox disagrees here, and actually changes
5070
    // the value.
5071
    if (callback->IsAccessorInfo()) {
5072
      return isolate->heap()->undefined_value();
5073
    }
5074
    // Avoid redefining foreign callback as data property, just use the stored
5075
    // setter to update the value instead.
5076
    // TODO(mstarzinger): So far this only works if property attributes don't
5077
    // change, this should be fixed once we cleanup the underlying code.
5078
    if (callback->IsForeign() && result.GetAttributes() == attr) {
5079
      Handle<Object> result_object =
5080
          JSObject::SetPropertyWithCallback(js_object,
5081
                                            handle(callback, isolate),
5082
                                            name,
5083
                                            obj_value,
5084
                                            handle(result.holder()),
5085
                                            kStrictMode);
5086
      RETURN_IF_EMPTY_HANDLE(isolate, result_object);
5087
      return *result_object;
5088
    }
5089
  }
5090

    
5091
  // Take special care when attributes are different and there is already
5092
  // a property. For simplicity we normalize the property which enables us
5093
  // to not worry about changing the instance_descriptor and creating a new
5094
  // map. The current version of SetObjectProperty does not handle attributes
5095
  // correctly in the case where a property is a field and is reset with
5096
  // new attributes.
5097
  if (result.IsFound() &&
5098
      (attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
5099
    // New attributes - normalize to avoid writing to instance descriptor
5100
    if (js_object->IsJSGlobalProxy()) {
5101
      // Since the result is a property, the prototype will exist so
5102
      // we don't have to check for null.
5103
      js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
5104
    }
5105
    JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
5106
    // Use IgnoreAttributes version since a readonly property may be
5107
    // overridden and SetProperty does not allow this.
5108
    Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5109
        js_object, name, obj_value, attr);
5110
    RETURN_IF_EMPTY_HANDLE(isolate, result);
5111
    return *result;
5112
  }
5113

    
5114
  return Runtime::ForceSetObjectProperty(isolate,
5115
                                         js_object,
5116
                                         name,
5117
                                         obj_value,
5118
                                         attr);
5119
}
5120

    
5121

    
5122
// Return property without being observable by accessors or interceptors.
5123
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDataProperty) {
5124
  SealHandleScope shs(isolate);
5125
  ASSERT(args.length() == 2);
5126
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5127
  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5128
  LookupResult lookup(isolate);
5129
  object->LookupRealNamedProperty(*key, &lookup);
5130
  if (!lookup.IsFound()) return isolate->heap()->undefined_value();
5131
  switch (lookup.type()) {
5132
    case NORMAL:
5133
      return lookup.holder()->GetNormalizedProperty(&lookup);
5134
    case FIELD:
5135
      return lookup.holder()->FastPropertyAt(
5136
          lookup.representation(),
5137
          lookup.GetFieldIndex().field_index());
5138
    case CONSTANT:
5139
      return lookup.GetConstant();
5140
    case CALLBACKS:
5141
    case HANDLER:
5142
    case INTERCEPTOR:
5143
    case TRANSITION:
5144
      return isolate->heap()->undefined_value();
5145
    case NONEXISTENT:
5146
      UNREACHABLE();
5147
  }
5148
  return isolate->heap()->undefined_value();
5149
}
5150

    
5151

    
5152
MaybeObject* Runtime::SetObjectPropertyOrFail(
5153
    Isolate* isolate,
5154
    Handle<Object> object,
5155
    Handle<Object> key,
5156
    Handle<Object> value,
5157
    PropertyAttributes attr,
5158
    StrictModeFlag strict_mode) {
5159
  CALL_HEAP_FUNCTION_PASS_EXCEPTION(isolate,
5160
      SetObjectProperty(isolate, object, key, value, attr, strict_mode));
5161
}
5162

    
5163

    
5164
MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
5165
                                        Handle<Object> object,
5166
                                        Handle<Object> key,
5167
                                        Handle<Object> value,
5168
                                        PropertyAttributes attr,
5169
                                        StrictModeFlag strict_mode) {
5170
  SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
5171
  HandleScope scope(isolate);
5172

    
5173
  if (object->IsUndefined() || object->IsNull()) {
5174
    Handle<Object> args[2] = { key, object };
5175
    Handle<Object> error =
5176
        isolate->factory()->NewTypeError("non_object_property_store",
5177
                                         HandleVector(args, 2));
5178
    return isolate->Throw(*error);
5179
  }
5180

    
5181
  if (object->IsJSProxy()) {
5182
    bool has_pending_exception = false;
5183
    Handle<Object> name_object = key->IsSymbol()
5184
        ? key : Execution::ToString(isolate, key, &has_pending_exception);
5185
    if (has_pending_exception) return Failure::Exception();
5186
    Handle<Name> name = Handle<Name>::cast(name_object);
5187
    Handle<Object> result = JSReceiver::SetProperty(
5188
        Handle<JSProxy>::cast(object), name, value, attr, strict_mode);
5189
    RETURN_IF_EMPTY_HANDLE(isolate, result);
5190
    return *result;
5191
  }
5192

    
5193
  // If the object isn't a JavaScript object, we ignore the store.
5194
  if (!object->IsJSObject()) return *value;
5195

    
5196
  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
5197

    
5198
  // Check if the given key is an array index.
5199
  uint32_t index;
5200
  if (key->ToArrayIndex(&index)) {
5201
    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5202
    // of a string using [] notation.  We need to support this too in
5203
    // JavaScript.
5204
    // In the case of a String object we just need to redirect the assignment to
5205
    // the underlying string if the index is in range.  Since the underlying
5206
    // string does nothing with the assignment then we can ignore such
5207
    // assignments.
5208
    if (js_object->IsStringObjectWithCharacterAt(index)) {
5209
      return *value;
5210
    }
5211

    
5212
    js_object->ValidateElements();
5213
    if (js_object->HasExternalArrayElements()) {
5214
      if (!value->IsNumber() && !value->IsUndefined()) {
5215
        bool has_exception;
5216
        Handle<Object> number =
5217
            Execution::ToNumber(isolate, value, &has_exception);
5218
        if (has_exception) return Failure::Exception();
5219
        value = number;
5220
      }
5221
    }
5222
    MaybeObject* result = js_object->SetElement(
5223
        index, *value, attr, strict_mode, true, set_mode);
5224
    js_object->ValidateElements();
5225
    if (result->IsFailure()) return result;
5226
    return *value;
5227
  }
5228

    
5229
  if (key->IsName()) {
5230
    Handle<Name> name = Handle<Name>::cast(key);
5231
    if (name->AsArrayIndex(&index)) {
5232
      if (js_object->HasExternalArrayElements()) {
5233
        if (!value->IsNumber() && !value->IsUndefined()) {
5234
          bool has_exception;
5235
          Handle<Object> number =
5236
              Execution::ToNumber(isolate, value, &has_exception);
5237
          if (has_exception) return Failure::Exception();
5238
          value = number;
5239
        }
5240
      }
5241
      MaybeObject* result = js_object->SetElement(
5242
          index, *value, attr, strict_mode, true, set_mode);
5243
      if (result->IsFailure()) return result;
5244
    } else {
5245
      if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5246
      Handle<Object> result =
5247
          JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5248
      RETURN_IF_EMPTY_HANDLE(isolate, result);
5249
    }
5250
    return *value;
5251
  }
5252

    
5253
  // Call-back into JavaScript to convert the key to a string.
5254
  bool has_pending_exception = false;
5255
  Handle<Object> converted =
5256
      Execution::ToString(isolate, key, &has_pending_exception);
5257
  if (has_pending_exception) return Failure::Exception();
5258
  Handle<String> name = Handle<String>::cast(converted);
5259

    
5260
  if (name->AsArrayIndex(&index)) {
5261
    return js_object->SetElement(
5262
        index, *value, attr, strict_mode, true, set_mode);
5263
  } else {
5264
    Handle<Object> result =
5265
        JSReceiver::SetProperty(js_object, name, value, attr, strict_mode);
5266
    RETURN_IF_EMPTY_HANDLE(isolate, result);
5267
    return *result;
5268
  }
5269
}
5270

    
5271

    
5272
MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
5273
                                             Handle<JSObject> js_object,
5274
                                             Handle<Object> key,
5275
                                             Handle<Object> value,
5276
                                             PropertyAttributes attr) {
5277
  HandleScope scope(isolate);
5278

    
5279
  // Check if the given key is an array index.
5280
  uint32_t index;
5281
  if (key->ToArrayIndex(&index)) {
5282
    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
5283
    // of a string using [] notation.  We need to support this too in
5284
    // JavaScript.
5285
    // In the case of a String object we just need to redirect the assignment to
5286
    // the underlying string if the index is in range.  Since the underlying
5287
    // string does nothing with the assignment then we can ignore such
5288
    // assignments.
5289
    if (js_object->IsStringObjectWithCharacterAt(index)) {
5290
      return *value;
5291
    }
5292

    
5293
    return js_object->SetElement(
5294
        index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5295
  }
5296

    
5297
  if (key->IsName()) {
5298
    Handle<Name> name = Handle<Name>::cast(key);
5299
    if (name->AsArrayIndex(&index)) {
5300
      return js_object->SetElement(
5301
          index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5302
    } else {
5303
      if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5304
      Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5305
          js_object, name, value, attr);
5306
      RETURN_IF_EMPTY_HANDLE(isolate, result);
5307
      return *result;
5308
    }
5309
  }
5310

    
5311
  // Call-back into JavaScript to convert the key to a string.
5312
  bool has_pending_exception = false;
5313
  Handle<Object> converted =
5314
      Execution::ToString(isolate, key, &has_pending_exception);
5315
  if (has_pending_exception) return Failure::Exception();
5316
  Handle<String> name = Handle<String>::cast(converted);
5317

    
5318
  if (name->AsArrayIndex(&index)) {
5319
    return js_object->SetElement(
5320
        index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
5321
  } else {
5322
    Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5323
        js_object, name, value, attr);
5324
    RETURN_IF_EMPTY_HANDLE(isolate, result);
5325
    return *result;
5326
  }
5327
}
5328

    
5329

    
5330
MaybeObject* Runtime::DeleteObjectProperty(Isolate* isolate,
5331
                                           Handle<JSReceiver> receiver,
5332
                                           Handle<Object> key,
5333
                                           JSReceiver::DeleteMode mode) {
5334
  HandleScope scope(isolate);
5335

    
5336
  // Check if the given key is an array index.
5337
  uint32_t index;
5338
  if (key->ToArrayIndex(&index)) {
5339
    // In Firefox/SpiderMonkey, Safari and Opera you can access the
5340
    // characters of a string using [] notation.  In the case of a
5341
    // String object we just need to redirect the deletion to the
5342
    // underlying string if the index is in range.  Since the
5343
    // underlying string does nothing with the deletion, we can ignore
5344
    // such deletions.
5345
    if (receiver->IsStringObjectWithCharacterAt(index)) {
5346
      return isolate->heap()->true_value();
5347
    }
5348

    
5349
    Handle<Object> result = JSReceiver::DeleteElement(receiver, index, mode);
5350
    RETURN_IF_EMPTY_HANDLE(isolate, result);
5351
    return *result;
5352
  }
5353

    
5354
  Handle<Name> name;
5355
  if (key->IsName()) {
5356
    name = Handle<Name>::cast(key);
5357
  } else {
5358
    // Call-back into JavaScript to convert the key to a string.
5359
    bool has_pending_exception = false;
5360
    Handle<Object> converted = Execution::ToString(
5361
        isolate, key, &has_pending_exception);
5362
    if (has_pending_exception) return Failure::Exception();
5363
    name = Handle<String>::cast(converted);
5364
  }
5365

    
5366
  if (name->IsString()) Handle<String>::cast(name)->TryFlatten();
5367
  Handle<Object> result = JSReceiver::DeleteProperty(receiver, name, mode);
5368
  RETURN_IF_EMPTY_HANDLE(isolate, result);
5369
  return *result;
5370
}
5371

    
5372

    
5373
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
5374
  SealHandleScope shs(isolate);
5375
  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5376

    
5377
  Handle<Object> object = args.at<Object>(0);
5378
  Handle<Object> key = args.at<Object>(1);
5379
  Handle<Object> value = args.at<Object>(2);
5380
  CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
5381
  RUNTIME_ASSERT(
5382
      (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5383
  // Compute attributes.
5384
  PropertyAttributes attributes =
5385
      static_cast<PropertyAttributes>(unchecked_attributes);
5386

    
5387
  StrictModeFlag strict_mode = kNonStrictMode;
5388
  if (args.length() == 5) {
5389
    CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
5390
    strict_mode = strict_mode_flag;
5391
  }
5392

    
5393
  return Runtime::SetObjectProperty(isolate,
5394
                                    object,
5395
                                    key,
5396
                                    value,
5397
                                    attributes,
5398
                                    strict_mode);
5399
}
5400

    
5401

    
5402
RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsKind) {
5403
  HandleScope scope(isolate);
5404
  RUNTIME_ASSERT(args.length() == 2);
5405
  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
5406
  CONVERT_ARG_HANDLE_CHECKED(Map, map, 1);
5407
  JSObject::TransitionElementsKind(array, map->elements_kind());
5408
  return *array;
5409
}
5410

    
5411

    
5412
// Set the native flag on the function.
5413
// This is used to decide if we should transform null and undefined
5414
// into the global object when doing call and apply.
5415
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
5416
  SealHandleScope shs(isolate);
5417
  RUNTIME_ASSERT(args.length() == 1);
5418

    
5419
  Handle<Object> object = args.at<Object>(0);
5420

    
5421
  if (object->IsJSFunction()) {
5422
    JSFunction* func = JSFunction::cast(*object);
5423
    func->shared()->set_native(true);
5424
  }
5425
  return isolate->heap()->undefined_value();
5426
}
5427

    
5428

    
5429
RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreArrayLiteralElement) {
5430
  HandleScope scope(isolate);
5431
  RUNTIME_ASSERT(args.length() == 5);
5432
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5433
  CONVERT_SMI_ARG_CHECKED(store_index, 1);
5434
  Handle<Object> value = args.at<Object>(2);
5435
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 3);
5436
  CONVERT_SMI_ARG_CHECKED(literal_index, 4);
5437

    
5438
  Object* raw_literal_cell = literals->get(literal_index);
5439
  JSArray* boilerplate = NULL;
5440
  if (raw_literal_cell->IsAllocationSite()) {
5441
    AllocationSite* site = AllocationSite::cast(raw_literal_cell);
5442
    boilerplate = JSArray::cast(site->transition_info());
5443
  } else {
5444
    boilerplate = JSArray::cast(raw_literal_cell);
5445
  }
5446
  Handle<JSArray> boilerplate_object(boilerplate);
5447
  ElementsKind elements_kind = object->GetElementsKind();
5448
  ASSERT(IsFastElementsKind(elements_kind));
5449
  // Smis should never trigger transitions.
5450
  ASSERT(!value->IsSmi());
5451

    
5452
  if (value->IsNumber()) {
5453
    ASSERT(IsFastSmiElementsKind(elements_kind));
5454
    ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5455
        ? FAST_HOLEY_DOUBLE_ELEMENTS
5456
        : FAST_DOUBLE_ELEMENTS;
5457
    if (IsMoreGeneralElementsKindTransition(
5458
            boilerplate_object->GetElementsKind(),
5459
            transitioned_kind)) {
5460
      JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5461
    }
5462
    JSObject::TransitionElementsKind(object, transitioned_kind);
5463
    ASSERT(IsFastDoubleElementsKind(object->GetElementsKind()));
5464
    FixedDoubleArray* double_array = FixedDoubleArray::cast(object->elements());
5465
    HeapNumber* number = HeapNumber::cast(*value);
5466
    double_array->set(store_index, number->Number());
5467
  } else {
5468
    ASSERT(IsFastSmiElementsKind(elements_kind) ||
5469
           IsFastDoubleElementsKind(elements_kind));
5470
    ElementsKind transitioned_kind = IsFastHoleyElementsKind(elements_kind)
5471
        ? FAST_HOLEY_ELEMENTS
5472
        : FAST_ELEMENTS;
5473
    JSObject::TransitionElementsKind(object, transitioned_kind);
5474
    if (IsMoreGeneralElementsKindTransition(
5475
            boilerplate_object->GetElementsKind(),
5476
            transitioned_kind)) {
5477
      JSObject::TransitionElementsKind(boilerplate_object, transitioned_kind);
5478
    }
5479
    FixedArray* object_array = FixedArray::cast(object->elements());
5480
    object_array->set(store_index, *value);
5481
  }
5482
  return *object;
5483
}
5484

    
5485

    
5486
// Check whether debugger and is about to step into the callback that is passed
5487
// to a built-in function such as Array.forEach.
5488
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
5489
  SealHandleScope shs(isolate);
5490
#ifdef ENABLE_DEBUGGER_SUPPORT
5491
  if (!isolate->IsDebuggerActive() || !isolate->debug()->StepInActive()) {
5492
    return isolate->heap()->false_value();
5493
  }
5494
  CONVERT_ARG_CHECKED(Object, callback, 0);
5495
  // We do not step into the callback if it's a builtin or not even a function.
5496
  if (!callback->IsJSFunction() || JSFunction::cast(callback)->IsBuiltin()) {
5497
    return isolate->heap()->false_value();
5498
  }
5499
  return isolate->heap()->true_value();
5500
#else
5501
  return isolate->heap()->false_value();
5502
#endif  // ENABLE_DEBUGGER_SUPPORT
5503
}
5504

    
5505

    
5506
// Set one shot breakpoints for the callback function that is passed to a
5507
// built-in function such as Array.forEach to enable stepping into the callback.
5508
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
5509
  SealHandleScope shs(isolate);
5510
#ifdef ENABLE_DEBUGGER_SUPPORT
5511
  Debug* debug = isolate->debug();
5512
  if (!debug->IsStepping()) return isolate->heap()->undefined_value();
5513
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
5514
  HandleScope scope(isolate);
5515
  // When leaving the callback, step out has been activated, but not performed
5516
  // if we do not leave the builtin.  To be able to step into the callback
5517
  // again, we need to clear the step out at this point.
5518
  debug->ClearStepOut();
5519
  debug->FloodWithOneShot(callback);
5520
#endif  // ENABLE_DEBUGGER_SUPPORT
5521
  return isolate->heap()->undefined_value();
5522
}
5523

    
5524

    
5525
// Set a local property, even if it is READ_ONLY.  If the property does not
5526
// exist, it will be added with attributes NONE.
5527
RUNTIME_FUNCTION(MaybeObject*, Runtime_IgnoreAttributesAndSetProperty) {
5528
  HandleScope scope(isolate);
5529
  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
5530
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
5531
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
5532
  CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
5533
  // Compute attributes.
5534
  PropertyAttributes attributes = NONE;
5535
  if (args.length() == 4) {
5536
    CONVERT_SMI_ARG_CHECKED(unchecked_value, 3);
5537
    // Only attribute bits should be set.
5538
    RUNTIME_ASSERT(
5539
        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5540
    attributes = static_cast<PropertyAttributes>(unchecked_value);
5541
  }
5542
  Handle<Object> result = JSObject::SetLocalPropertyIgnoreAttributes(
5543
      object, name, value, attributes);
5544
  RETURN_IF_EMPTY_HANDLE(isolate, result);
5545
  return *result;
5546
}
5547

    
5548

    
5549
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteProperty) {
5550
  HandleScope scope(isolate);
5551
  ASSERT(args.length() == 3);
5552
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5553
  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5554
  CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode, 2);
5555
  JSReceiver::DeleteMode delete_mode = (strict_mode == kStrictMode)
5556
      ? JSReceiver::STRICT_DELETION : JSReceiver::NORMAL_DELETION;
5557
  Handle<Object> result = JSReceiver::DeleteProperty(object, key, delete_mode);
5558
  RETURN_IF_EMPTY_HANDLE(isolate, result);
5559
  return *result;
5560
}
5561

    
5562

    
5563
static MaybeObject* HasLocalPropertyImplementation(Isolate* isolate,
5564
                                                   Handle<JSObject> object,
5565
                                                   Handle<Name> key) {
5566
  if (JSReceiver::HasLocalProperty(object, key)) {
5567
    return isolate->heap()->true_value();
5568
  }
5569
  // Handle hidden prototypes.  If there's a hidden prototype above this thing
5570
  // then we have to check it for properties, because they are supposed to
5571
  // look like they are on this object.
5572
  Handle<Object> proto(object->GetPrototype(), isolate);
5573
  if (proto->IsJSObject() &&
5574
      Handle<JSObject>::cast(proto)->map()->is_hidden_prototype()) {
5575
    return HasLocalPropertyImplementation(isolate,
5576
                                          Handle<JSObject>::cast(proto),
5577
                                          key);
5578
  }
5579
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5580
  return isolate->heap()->false_value();
5581
}
5582

    
5583

    
5584
RUNTIME_FUNCTION(MaybeObject*, Runtime_HasLocalProperty) {
5585
  HandleScope scope(isolate);
5586
  ASSERT(args.length() == 2);
5587
  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5588
  Handle<Object> object = args.at<Object>(0);
5589

    
5590
  uint32_t index;
5591
  const bool key_is_array_index = key->AsArrayIndex(&index);
5592

    
5593
  // Only JS objects can have properties.
5594
  if (object->IsJSObject()) {
5595
    Handle<JSObject> js_obj = Handle<JSObject>::cast(object);
5596
    // Fast case: either the key is a real named property or it is not
5597
    // an array index and there are no interceptors or hidden
5598
    // prototypes.
5599
    if (JSObject::HasRealNamedProperty(js_obj, key)) {
5600
      ASSERT(!isolate->has_scheduled_exception());
5601
      return isolate->heap()->true_value();
5602
    } else {
5603
      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5604
    }
5605
    Map* map = js_obj->map();
5606
    if (!key_is_array_index &&
5607
        !map->has_named_interceptor() &&
5608
        !HeapObject::cast(map->prototype())->map()->is_hidden_prototype()) {
5609
      return isolate->heap()->false_value();
5610
    }
5611
    // Slow case.
5612
    return HasLocalPropertyImplementation(isolate,
5613
                                          Handle<JSObject>(js_obj),
5614
                                          Handle<Name>(key));
5615
  } else if (object->IsString() && key_is_array_index) {
5616
    // Well, there is one exception:  Handle [] on strings.
5617
    Handle<String> string = Handle<String>::cast(object);
5618
    if (index < static_cast<uint32_t>(string->length())) {
5619
      return isolate->heap()->true_value();
5620
    }
5621
  }
5622
  return isolate->heap()->false_value();
5623
}
5624

    
5625

    
5626
RUNTIME_FUNCTION(MaybeObject*, Runtime_HasProperty) {
5627
  HandleScope scope(isolate);
5628
  ASSERT(args.length() == 2);
5629
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5630
  CONVERT_ARG_HANDLE_CHECKED(Name, key, 1);
5631

    
5632
  bool result = JSReceiver::HasProperty(receiver, key);
5633
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5634
  if (isolate->has_pending_exception()) return Failure::Exception();
5635
  return isolate->heap()->ToBoolean(result);
5636
}
5637

    
5638

    
5639
RUNTIME_FUNCTION(MaybeObject*, Runtime_HasElement) {
5640
  HandleScope scope(isolate);
5641
  ASSERT(args.length() == 2);
5642
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
5643
  CONVERT_SMI_ARG_CHECKED(index, 1);
5644

    
5645
  bool result = JSReceiver::HasElement(receiver, index);
5646
  RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5647
  if (isolate->has_pending_exception()) return Failure::Exception();
5648
  return isolate->heap()->ToBoolean(result);
5649
}
5650

    
5651

    
5652
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsPropertyEnumerable) {
5653
  SealHandleScope shs(isolate);
5654
  ASSERT(args.length() == 2);
5655

    
5656
  CONVERT_ARG_CHECKED(JSObject, object, 0);
5657
  CONVERT_ARG_CHECKED(Name, key, 1);
5658

    
5659
  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
5660
  if (att == ABSENT || (att & DONT_ENUM) != 0) {
5661
    RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5662
    return isolate->heap()->false_value();
5663
  }
5664
  ASSERT(!isolate->has_scheduled_exception());
5665
  return isolate->heap()->true_value();
5666
}
5667

    
5668

    
5669
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNames) {
5670
  HandleScope scope(isolate);
5671
  ASSERT(args.length() == 1);
5672
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, object, 0);
5673
  bool threw = false;
5674
  Handle<JSArray> result = GetKeysFor(object, &threw);
5675
  if (threw) return Failure::Exception();
5676
  return *result;
5677
}
5678

    
5679

    
5680
// Returns either a FixedArray as Runtime_GetPropertyNames,
5681
// or, if the given object has an enum cache that contains
5682
// all enumerable properties of the object and its prototypes
5683
// have none, the map of the object. This is used to speed up
5684
// the check for deletions during a for-in.
5685
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPropertyNamesFast) {
5686
  SealHandleScope shs(isolate);
5687
  ASSERT(args.length() == 1);
5688

    
5689
  CONVERT_ARG_CHECKED(JSReceiver, raw_object, 0);
5690

    
5691
  if (raw_object->IsSimpleEnum()) return raw_object->map();
5692

    
5693
  HandleScope scope(isolate);
5694
  Handle<JSReceiver> object(raw_object);
5695
  bool threw = false;
5696
  Handle<FixedArray> content =
5697
      GetKeysInFixedArrayFor(object, INCLUDE_PROTOS, &threw);
5698
  if (threw) return Failure::Exception();
5699

    
5700
  // Test again, since cache may have been built by preceding call.
5701
  if (object->IsSimpleEnum()) return object->map();
5702

    
5703
  return *content;
5704
}
5705

    
5706

    
5707
// Find the length of the prototype chain that is to to handled as one. If a
5708
// prototype object is hidden it is to be viewed as part of the the object it
5709
// is prototype for.
5710
static int LocalPrototypeChainLength(JSObject* obj) {
5711
  int count = 1;
5712
  Object* proto = obj->GetPrototype();
5713
  while (proto->IsJSObject() &&
5714
         JSObject::cast(proto)->map()->is_hidden_prototype()) {
5715
    count++;
5716
    proto = JSObject::cast(proto)->GetPrototype();
5717
  }
5718
  return count;
5719
}
5720

    
5721

    
5722
// Return the names of the local named properties.
5723
// args[0]: object
5724
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) {
5725
  HandleScope scope(isolate);
5726
  ASSERT(args.length() == 2);
5727
  if (!args[0]->IsJSObject()) {
5728
    return isolate->heap()->undefined_value();
5729
  }
5730
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5731
  CONVERT_BOOLEAN_ARG_CHECKED(include_symbols, 1);
5732
  PropertyAttributes filter = include_symbols ? NONE : SYMBOLIC;
5733

    
5734
  // Skip the global proxy as it has no properties and always delegates to the
5735
  // real global object.
5736
  if (obj->IsJSGlobalProxy()) {
5737
    // Only collect names if access is permitted.
5738
    if (obj->IsAccessCheckNeeded() &&
5739
        !isolate->MayNamedAccess(*obj,
5740
                                 isolate->heap()->undefined_value(),
5741
                                 v8::ACCESS_KEYS)) {
5742
      isolate->ReportFailedAccessCheck(*obj, v8::ACCESS_KEYS);
5743
      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5744
      return *isolate->factory()->NewJSArray(0);
5745
    }
5746
    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5747
  }
5748

    
5749
  // Find the number of objects making up this.
5750
  int length = LocalPrototypeChainLength(*obj);
5751

    
5752
  // Find the number of local properties for each of the objects.
5753
  ScopedVector<int> local_property_count(length);
5754
  int total_property_count = 0;
5755
  Handle<JSObject> jsproto = obj;
5756
  for (int i = 0; i < length; i++) {
5757
    // Only collect names if access is permitted.
5758
    if (jsproto->IsAccessCheckNeeded() &&
5759
        !isolate->MayNamedAccess(*jsproto,
5760
                                 isolate->heap()->undefined_value(),
5761
                                 v8::ACCESS_KEYS)) {
5762
      isolate->ReportFailedAccessCheck(*jsproto, v8::ACCESS_KEYS);
5763
      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5764
      return *isolate->factory()->NewJSArray(0);
5765
    }
5766
    int n;
5767
    n = jsproto->NumberOfLocalProperties(filter);
5768
    local_property_count[i] = n;
5769
    total_property_count += n;
5770
    if (i < length - 1) {
5771
      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5772
    }
5773
  }
5774

    
5775
  // Allocate an array with storage for all the property names.
5776
  Handle<FixedArray> names =
5777
      isolate->factory()->NewFixedArray(total_property_count);
5778

    
5779
  // Get the property names.
5780
  jsproto = obj;
5781
  int proto_with_hidden_properties = 0;
5782
  int next_copy_index = 0;
5783
  for (int i = 0; i < length; i++) {
5784
    jsproto->GetLocalPropertyNames(*names, next_copy_index, filter);
5785
    next_copy_index += local_property_count[i];
5786
    if (jsproto->HasHiddenProperties()) {
5787
      proto_with_hidden_properties++;
5788
    }
5789
    if (i < length - 1) {
5790
      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5791
    }
5792
  }
5793

    
5794
  // Filter out name of hidden properties object.
5795
  if (proto_with_hidden_properties > 0) {
5796
    Handle<FixedArray> old_names = names;
5797
    names = isolate->factory()->NewFixedArray(
5798
        names->length() - proto_with_hidden_properties);
5799
    int dest_pos = 0;
5800
    for (int i = 0; i < total_property_count; i++) {
5801
      Object* name = old_names->get(i);
5802
      if (name == isolate->heap()->hidden_string()) {
5803
        continue;
5804
      }
5805
      names->set(dest_pos++, name);
5806
    }
5807
  }
5808

    
5809
  return *isolate->factory()->NewJSArrayWithElements(names);
5810
}
5811

    
5812

    
5813
// Return the names of the local indexed properties.
5814
// args[0]: object
5815
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalElementNames) {
5816
  HandleScope scope(isolate);
5817
  ASSERT(args.length() == 1);
5818
  if (!args[0]->IsJSObject()) {
5819
    return isolate->heap()->undefined_value();
5820
  }
5821
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5822

    
5823
  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5824
  Handle<FixedArray> names = isolate->factory()->NewFixedArray(n);
5825
  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5826
  return *isolate->factory()->NewJSArrayWithElements(names);
5827
}
5828

    
5829

    
5830
// Return information on whether an object has a named or indexed interceptor.
5831
// args[0]: object
5832
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetInterceptorInfo) {
5833
  HandleScope scope(isolate);
5834
  ASSERT(args.length() == 1);
5835
  if (!args[0]->IsJSObject()) {
5836
    return Smi::FromInt(0);
5837
  }
5838
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5839

    
5840
  int result = 0;
5841
  if (obj->HasNamedInterceptor()) result |= 2;
5842
  if (obj->HasIndexedInterceptor()) result |= 1;
5843

    
5844
  return Smi::FromInt(result);
5845
}
5846

    
5847

    
5848
// Return property names from named interceptor.
5849
// args[0]: object
5850
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetNamedInterceptorPropertyNames) {
5851
  HandleScope scope(isolate);
5852
  ASSERT(args.length() == 1);
5853
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5854

    
5855
  if (obj->HasNamedInterceptor()) {
5856
    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5857
    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5858
  }
5859
  return isolate->heap()->undefined_value();
5860
}
5861

    
5862

    
5863
// Return element names from indexed interceptor.
5864
// args[0]: object
5865
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetIndexedInterceptorElementNames) {
5866
  HandleScope scope(isolate);
5867
  ASSERT(args.length() == 1);
5868
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
5869

    
5870
  if (obj->HasIndexedInterceptor()) {
5871
    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5872
    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5873
  }
5874
  return isolate->heap()->undefined_value();
5875
}
5876

    
5877

    
5878
RUNTIME_FUNCTION(MaybeObject*, Runtime_LocalKeys) {
5879
  HandleScope scope(isolate);
5880
  ASSERT_EQ(args.length(), 1);
5881
  CONVERT_ARG_CHECKED(JSObject, raw_object, 0);
5882
  Handle<JSObject> object(raw_object);
5883

    
5884
  if (object->IsJSGlobalProxy()) {
5885
    // Do access checks before going to the global object.
5886
    if (object->IsAccessCheckNeeded() &&
5887
        !isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
5888
                             v8::ACCESS_KEYS)) {
5889
      isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS);
5890
      RETURN_IF_SCHEDULED_EXCEPTION(isolate);
5891
      return *isolate->factory()->NewJSArray(0);
5892
    }
5893

    
5894
    Handle<Object> proto(object->GetPrototype(), isolate);
5895
    // If proxy is detached we simply return an empty array.
5896
    if (proto->IsNull()) return *isolate->factory()->NewJSArray(0);
5897
    object = Handle<JSObject>::cast(proto);
5898
  }
5899

    
5900
  bool threw = false;
5901
  Handle<FixedArray> contents =
5902
      GetKeysInFixedArrayFor(object, LOCAL_ONLY, &threw);
5903
  if (threw) return Failure::Exception();
5904

    
5905
  // Some fast paths through GetKeysInFixedArrayFor reuse a cached
5906
  // property array and since the result is mutable we have to create
5907
  // a fresh clone on each invocation.
5908
  int length = contents->length();
5909
  Handle<FixedArray> copy = isolate->factory()->NewFixedArray(length);
5910
  for (int i = 0; i < length; i++) {
5911
    Object* entry = contents->get(i);
5912
    if (entry->IsString()) {
5913
      copy->set(i, entry);
5914
    } else {
5915
      ASSERT(entry->IsNumber());
5916
      HandleScope scope(isolate);
5917
      Handle<Object> entry_handle(entry, isolate);
5918
      Handle<Object> entry_str =
5919
          isolate->factory()->NumberToString(entry_handle);
5920
      copy->set(i, *entry_str);
5921
    }
5922
  }
5923
  return *isolate->factory()->NewJSArrayWithElements(copy);
5924
}
5925

    
5926

    
5927
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
5928
  SealHandleScope shs(isolate);
5929
  ASSERT(args.length() == 1);
5930

    
5931
  // Compute the frame holding the arguments.
5932
  JavaScriptFrameIterator it(isolate);
5933
  it.AdvanceToArgumentsFrame();
5934
  JavaScriptFrame* frame = it.frame();
5935

    
5936
  // Get the actual number of provided arguments.
5937
  const uint32_t n = frame->ComputeParametersCount();
5938

    
5939
  // Try to convert the key to an index. If successful and within
5940
  // index return the the argument from the frame.
5941
  uint32_t index;
5942
  if (args[0]->ToArrayIndex(&index) && index < n) {
5943
    return frame->GetParameter(index);
5944
  }
5945

    
5946
  if (args[0]->IsSymbol()) {
5947
    // Lookup in the initial Object.prototype object.
5948
    return isolate->initial_object_prototype()->GetProperty(
5949
        Symbol::cast(args[0]));
5950
  }
5951

    
5952
  // Convert the key to a string.
5953
  HandleScope scope(isolate);
5954
  bool exception = false;
5955
  Handle<Object> converted =
5956
      Execution::ToString(isolate, args.at<Object>(0), &exception);
5957
  if (exception) return Failure::Exception();
5958
  Handle<String> key = Handle<String>::cast(converted);
5959

    
5960
  // Try to convert the string key into an array index.
5961
  if (key->AsArrayIndex(&index)) {
5962
    if (index < n) {
5963
      return frame->GetParameter(index);
5964
    } else {
5965
      return isolate->initial_object_prototype()->GetElement(isolate, index);
5966
    }
5967
  }
5968

    
5969
  // Handle special arguments properties.
5970
  if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
5971
  if (key->Equals(isolate->heap()->callee_string())) {
5972
    JSFunction* function = frame->function();
5973
    if (!function->shared()->is_classic_mode()) {
5974
      return isolate->Throw(*isolate->factory()->NewTypeError(
5975
          "strict_arguments_callee", HandleVector<Object>(NULL, 0)));
5976
    }
5977
    return function;
5978
  }
5979

    
5980
  // Lookup in the initial Object.prototype object.
5981
  return isolate->initial_object_prototype()->GetProperty(*key);
5982
}
5983

    
5984

    
5985
RUNTIME_FUNCTION(MaybeObject*, Runtime_ToFastProperties) {
5986
  HandleScope scope(isolate);
5987
  ASSERT(args.length() == 1);
5988
  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
5989
  if (object->IsJSObject() && !object->IsGlobalObject()) {
5990
    JSObject::TransformToFastProperties(Handle<JSObject>::cast(object), 0);
5991
  }
5992
  return *object;
5993
}
5994

    
5995

    
5996
RUNTIME_FUNCTION(MaybeObject*, Runtime_ToBool) {
5997
  SealHandleScope shs(isolate);
5998
  ASSERT(args.length() == 1);
5999

    
6000
  return isolate->heap()->ToBoolean(args[0]->BooleanValue());
6001
}
6002

    
6003

    
6004
// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
6005
// Possible optimizations: put the type string into the oddballs.
6006
RUNTIME_FUNCTION(MaybeObject*, Runtime_Typeof) {
6007
  SealHandleScope shs(isolate);
6008

    
6009
  Object* obj = args[0];
6010
  if (obj->IsNumber()) return isolate->heap()->number_string();
6011
  HeapObject* heap_obj = HeapObject::cast(obj);
6012

    
6013
  // typeof an undetectable object is 'undefined'
6014
  if (heap_obj->map()->is_undetectable()) {
6015
    return isolate->heap()->undefined_string();
6016
  }
6017

    
6018
  InstanceType instance_type = heap_obj->map()->instance_type();
6019
  if (instance_type < FIRST_NONSTRING_TYPE) {
6020
    return isolate->heap()->string_string();
6021
  }
6022

    
6023
  switch (instance_type) {
6024
    case ODDBALL_TYPE:
6025
      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
6026
        return isolate->heap()->boolean_string();
6027
      }
6028
      if (heap_obj->IsNull()) {
6029
        return FLAG_harmony_typeof
6030
            ? isolate->heap()->null_string()
6031
            : isolate->heap()->object_string();
6032
      }
6033
      ASSERT(heap_obj->IsUndefined());
6034
      return isolate->heap()->undefined_string();
6035
    case SYMBOL_TYPE:
6036
      return isolate->heap()->symbol_string();
6037
    case JS_FUNCTION_TYPE:
6038
    case JS_FUNCTION_PROXY_TYPE:
6039
      return isolate->heap()->function_string();
6040
    default:
6041
      // For any kind of object not handled above, the spec rule for
6042
      // host objects gives that it is okay to return "object"
6043
      return isolate->heap()->object_string();
6044
  }
6045
}
6046

    
6047

    
6048
static bool AreDigits(const uint8_t*s, int from, int to) {
6049
  for (int i = from; i < to; i++) {
6050
    if (s[i] < '0' || s[i] > '9') return false;
6051
  }
6052

    
6053
  return true;
6054
}
6055

    
6056

    
6057
static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
6058
  ASSERT(to - from < 10);  // Overflow is not possible.
6059
  ASSERT(from < to);
6060
  int d = s[from] - '0';
6061

    
6062
  for (int i = from + 1; i < to; i++) {
6063
    d = 10 * d + (s[i] - '0');
6064
  }
6065

    
6066
  return d;
6067
}
6068

    
6069

    
6070
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
6071
  SealHandleScope shs(isolate);
6072
  ASSERT(args.length() == 1);
6073
  CONVERT_ARG_CHECKED(String, subject, 0);
6074
  subject->TryFlatten();
6075

    
6076
  // Fast case: short integer or some sorts of junk values.
6077
  int len = subject->length();
6078
  if (subject->IsSeqOneByteString()) {
6079
    if (len == 0) return Smi::FromInt(0);
6080

    
6081
    uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
6082
    bool minus = (data[0] == '-');
6083
    int start_pos = (minus ? 1 : 0);
6084

    
6085
    if (start_pos == len) {
6086
      return isolate->heap()->nan_value();
6087
    } else if (data[start_pos] > '9') {
6088
      // Fast check for a junk value. A valid string may start from a
6089
      // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
6090
      // the 'I' character ('Infinity'). All of that have codes not greater than
6091
      // '9' except 'I' and &nbsp;.
6092
      if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
6093
        return isolate->heap()->nan_value();
6094
      }
6095
    } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
6096
      // The maximal/minimal smi has 10 digits. If the string has less digits we
6097
      // know it will fit into the smi-data type.
6098
      int d = ParseDecimalInteger(data, start_pos, len);
6099
      if (minus) {
6100
        if (d == 0) return isolate->heap()->minus_zero_value();
6101
        d = -d;
6102
      } else if (!subject->HasHashCode() &&
6103
                 len <= String::kMaxArrayIndexSize &&
6104
                 (len == 1 || data[0] != '0')) {
6105
        // String hash is not calculated yet but all the data are present.
6106
        // Update the hash field to speed up sequential convertions.
6107
        uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
6108
#ifdef DEBUG
6109
        subject->Hash();  // Force hash calculation.
6110
        ASSERT_EQ(static_cast<int>(subject->hash_field()),
6111
                  static_cast<int>(hash));
6112
#endif
6113
        subject->set_hash_field(hash);
6114
      }
6115
      return Smi::FromInt(d);
6116
    }
6117
  }
6118

    
6119
  // Slower case.
6120
  int flags = ALLOW_HEX;
6121
  if (FLAG_harmony_numeric_literals) {
6122
    // The current spec draft has not updated "ToNumber Applied to the String
6123
    // Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
6124
    flags |= ALLOW_OCTAL | ALLOW_BINARY;
6125
  }
6126
  return isolate->heap()->NumberFromDouble(
6127
      StringToDouble(isolate->unicode_cache(), subject, flags));
6128
}
6129

    
6130

    
6131
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewString) {
6132
  SealHandleScope shs(isolate);
6133
  CONVERT_SMI_ARG_CHECKED(length, 0);
6134
  CONVERT_BOOLEAN_ARG_CHECKED(is_one_byte, 1);
6135
  if (length == 0) return isolate->heap()->empty_string();
6136
  if (is_one_byte) {
6137
    return isolate->heap()->AllocateRawOneByteString(length);
6138
  } else {
6139
    return isolate->heap()->AllocateRawTwoByteString(length);
6140
  }
6141
}
6142

    
6143

    
6144
RUNTIME_FUNCTION(MaybeObject*, Runtime_TruncateString) {
6145
  HandleScope scope(isolate);
6146
  CONVERT_ARG_HANDLE_CHECKED(SeqString, string, 0);
6147
  CONVERT_SMI_ARG_CHECKED(new_length, 1);
6148
  return *SeqString::Truncate(string, new_length);
6149
}
6150

    
6151

    
6152
RUNTIME_FUNCTION(MaybeObject*, Runtime_URIEscape) {
6153
  HandleScope scope(isolate);
6154
  ASSERT(args.length() == 1);
6155
  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6156
  Handle<String> string = FlattenGetString(source);
6157
  ASSERT(string->IsFlat());
6158
  Handle<String> result = string->IsOneByteRepresentationUnderneath()
6159
      ? URIEscape::Escape<uint8_t>(isolate, source)
6160
      : URIEscape::Escape<uc16>(isolate, source);
6161
  if (result.is_null()) return Failure::OutOfMemoryException(0x12);
6162
  return *result;
6163
}
6164

    
6165

    
6166
RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
6167
  HandleScope scope(isolate);
6168
  ASSERT(args.length() == 1);
6169
  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
6170
  Handle<String> string = FlattenGetString(source);
6171
  ASSERT(string->IsFlat());
6172
  return string->IsOneByteRepresentationUnderneath()
6173
      ? *URIUnescape::Unescape<uint8_t>(isolate, source)
6174
      : *URIUnescape::Unescape<uc16>(isolate, source);
6175
}
6176

    
6177

    
6178
RUNTIME_FUNCTION(MaybeObject*, Runtime_QuoteJSONString) {
6179
  HandleScope scope(isolate);
6180
  CONVERT_ARG_HANDLE_CHECKED(String, string, 0);
6181
  ASSERT(args.length() == 1);
6182
  return BasicJsonStringifier::StringifyString(isolate, string);
6183
}
6184

    
6185

    
6186
RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
6187
  HandleScope scope(isolate);
6188
  ASSERT(args.length() == 1);
6189
  BasicJsonStringifier stringifier(isolate);
6190
  return stringifier.Stringify(Handle<Object>(args[0], isolate));
6191
}
6192

    
6193

    
6194
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
6195
  SealHandleScope shs(isolate);
6196

    
6197
  CONVERT_ARG_CHECKED(String, s, 0);
6198
  CONVERT_SMI_ARG_CHECKED(radix, 1);
6199

    
6200
  s->TryFlatten();
6201

    
6202
  RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
6203
  double value = StringToInt(isolate->unicode_cache(), s, radix);
6204
  return isolate->heap()->NumberFromDouble(value);
6205
}
6206

    
6207

    
6208
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
6209
  SealHandleScope shs(isolate);
6210
  CONVERT_ARG_CHECKED(String, str, 0);
6211

    
6212
  // ECMA-262 section 15.1.2.3, empty string is NaN
6213
  double value = StringToDouble(isolate->unicode_cache(),
6214
                                str, ALLOW_TRAILING_JUNK, OS::nan_value());
6215

    
6216
  // Create a number object from the value.
6217
  return isolate->heap()->NumberFromDouble(value);
6218
}
6219

    
6220

    
6221
template <class Converter>
6222
MUST_USE_RESULT static MaybeObject* ConvertCaseHelper(
6223
    Isolate* isolate,
6224
    String* s,
6225
    int length,
6226
    int input_string_length,
6227
    unibrow::Mapping<Converter, 128>* mapping) {
6228
  // We try this twice, once with the assumption that the result is no longer
6229
  // than the input and, if that assumption breaks, again with the exact
6230
  // length.  This may not be pretty, but it is nicer than what was here before
6231
  // and I hereby claim my vaffel-is.
6232
  //
6233
  // Allocate the resulting string.
6234
  //
6235
  // NOTE: This assumes that the upper/lower case of an ASCII
6236
  // character is also ASCII.  This is currently the case, but it
6237
  // might break in the future if we implement more context and locale
6238
  // dependent upper/lower conversions.
6239
  Object* o;
6240
  { MaybeObject* maybe_o = s->IsOneByteRepresentation()
6241
        ? isolate->heap()->AllocateRawOneByteString(length)
6242
        : isolate->heap()->AllocateRawTwoByteString(length);
6243
    if (!maybe_o->ToObject(&o)) return maybe_o;
6244
  }
6245
  String* result = String::cast(o);
6246
  bool has_changed_character = false;
6247

    
6248
  // Convert all characters to upper case, assuming that they will fit
6249
  // in the buffer
6250
  Access<ConsStringIteratorOp> op(
6251
      isolate->runtime_state()->string_iterator());
6252
  StringCharacterStream stream(s, op.value());
6253
  unibrow::uchar chars[Converter::kMaxWidth];
6254
  // We can assume that the string is not empty
6255
  uc32 current = stream.GetNext();
6256
  for (int i = 0; i < length;) {
6257
    bool has_next = stream.HasMore();
6258
    uc32 next = has_next ? stream.GetNext() : 0;
6259
    int char_length = mapping->get(current, next, chars);
6260
    if (char_length == 0) {
6261
      // The case conversion of this character is the character itself.
6262
      result->Set(i, current);
6263
      i++;
6264
    } else if (char_length == 1) {
6265
      // Common case: converting the letter resulted in one character.
6266
      ASSERT(static_cast<uc32>(chars[0]) != current);
6267
      result->Set(i, chars[0]);
6268
      has_changed_character = true;
6269
      i++;
6270
    } else if (length == input_string_length) {
6271
      // We've assumed that the result would be as long as the
6272
      // input but here is a character that converts to several
6273
      // characters.  No matter, we calculate the exact length
6274
      // of the result and try the whole thing again.
6275
      //
6276
      // Note that this leaves room for optimization.  We could just
6277
      // memcpy what we already have to the result string.  Also,
6278
      // the result string is the last object allocated we could
6279
      // "realloc" it and probably, in the vast majority of cases,
6280
      // extend the existing string to be able to hold the full
6281
      // result.
6282
      int next_length = 0;
6283
      if (has_next) {
6284
        next_length = mapping->get(next, 0, chars);
6285
        if (next_length == 0) next_length = 1;
6286
      }
6287
      int current_length = i + char_length + next_length;
6288
      while (stream.HasMore()) {
6289
        current = stream.GetNext();
6290
        // NOTE: we use 0 as the next character here because, while
6291
        // the next character may affect what a character converts to,
6292
        // it does not in any case affect the length of what it convert
6293
        // to.
6294
        int char_length = mapping->get(current, 0, chars);
6295
        if (char_length == 0) char_length = 1;
6296
        current_length += char_length;
6297
        if (current_length > Smi::kMaxValue) {
6298
          isolate->context()->mark_out_of_memory();
6299
          return Failure::OutOfMemoryException(0x13);
6300
        }
6301
      }
6302
      // Try again with the real length.
6303
      return Smi::FromInt(current_length);
6304
    } else {
6305
      for (int j = 0; j < char_length; j++) {
6306
        result->Set(i, chars[j]);
6307
        i++;
6308
      }
6309
      has_changed_character = true;
6310
    }
6311
    current = next;
6312
  }
6313
  if (has_changed_character) {
6314
    return result;
6315
  } else {
6316
    // If we didn't actually change anything in doing the conversion
6317
    // we simple return the result and let the converted string
6318
    // become garbage; there is no reason to keep two identical strings
6319
    // alive.
6320
    return s;
6321
  }
6322
}
6323

    
6324

    
6325
namespace {
6326

    
6327
static const uintptr_t kOneInEveryByte = kUintptrAllBitsSet / 0xFF;
6328
static const uintptr_t kAsciiMask = kOneInEveryByte << 7;
6329

    
6330
// Given a word and two range boundaries returns a word with high bit
6331
// set in every byte iff the corresponding input byte was strictly in
6332
// the range (m, n). All the other bits in the result are cleared.
6333
// This function is only useful when it can be inlined and the
6334
// boundaries are statically known.
6335
// Requires: all bytes in the input word and the boundaries must be
6336
// ASCII (less than 0x7F).
6337
static inline uintptr_t AsciiRangeMask(uintptr_t w, char m, char n) {
6338
  // Use strict inequalities since in edge cases the function could be
6339
  // further simplified.
6340
  ASSERT(0 < m && m < n);
6341
  // Has high bit set in every w byte less than n.
6342
  uintptr_t tmp1 = kOneInEveryByte * (0x7F + n) - w;
6343
  // Has high bit set in every w byte greater than m.
6344
  uintptr_t tmp2 = w + kOneInEveryByte * (0x7F - m);
6345
  return (tmp1 & tmp2 & (kOneInEveryByte * 0x80));
6346
}
6347

    
6348

    
6349
enum AsciiCaseConversion {
6350
  ASCII_TO_LOWER,
6351
  ASCII_TO_UPPER
6352
};
6353

    
6354

    
6355
template <AsciiCaseConversion dir>
6356
struct FastAsciiConverter {
6357
  static bool Convert(char* dst, char* src, int length, bool* changed_out) {
6358
#ifdef DEBUG
6359
    char* saved_dst = dst;
6360
    char* saved_src = src;
6361
#endif
6362
    // We rely on the distance between upper and lower case letters
6363
    // being a known power of 2.
6364
    ASSERT('a' - 'A' == (1 << 5));
6365
    // Boundaries for the range of input characters than require conversion.
6366
    const char lo = (dir == ASCII_TO_LOWER) ? 'A' - 1 : 'a' - 1;
6367
    const char hi = (dir == ASCII_TO_LOWER) ? 'Z' + 1 : 'z' + 1;
6368
    bool changed = false;
6369
    uintptr_t or_acc = 0;
6370
    char* const limit = src + length;
6371
#ifdef V8_HOST_CAN_READ_UNALIGNED
6372
    // Process the prefix of the input that requires no conversion one
6373
    // (machine) word at a time.
6374
    while (src <= limit - sizeof(uintptr_t)) {
6375
      uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6376
      or_acc |= w;
6377
      if (AsciiRangeMask(w, lo, hi) != 0) {
6378
        changed = true;
6379
        break;
6380
      }
6381
      *reinterpret_cast<uintptr_t*>(dst) = w;
6382
      src += sizeof(uintptr_t);
6383
      dst += sizeof(uintptr_t);
6384
    }
6385
    // Process the remainder of the input performing conversion when
6386
    // required one word at a time.
6387
    while (src <= limit - sizeof(uintptr_t)) {
6388
      uintptr_t w = *reinterpret_cast<uintptr_t*>(src);
6389
      or_acc |= w;
6390
      uintptr_t m = AsciiRangeMask(w, lo, hi);
6391
      // The mask has high (7th) bit set in every byte that needs
6392
      // conversion and we know that the distance between cases is
6393
      // 1 << 5.
6394
      *reinterpret_cast<uintptr_t*>(dst) = w ^ (m >> 2);
6395
      src += sizeof(uintptr_t);
6396
      dst += sizeof(uintptr_t);
6397
    }
6398
#endif
6399
    // Process the last few bytes of the input (or the whole input if
6400
    // unaligned access is not supported).
6401
    while (src < limit) {
6402
      char c = *src;
6403
      or_acc |= c;
6404
      if (lo < c && c < hi) {
6405
        c ^= (1 << 5);
6406
        changed = true;
6407
      }
6408
      *dst = c;
6409
      ++src;
6410
      ++dst;
6411
    }
6412
    if ((or_acc & kAsciiMask) != 0) {
6413
      return false;
6414
    }
6415
#ifdef DEBUG
6416
    CheckConvert(saved_dst, saved_src, length, changed);
6417
#endif
6418
    *changed_out = changed;
6419
    return true;
6420
  }
6421

    
6422
#ifdef DEBUG
6423
  static void CheckConvert(char* dst, char* src, int length, bool changed) {
6424
    bool expected_changed = false;
6425
    for (int i = 0; i < length; i++) {
6426
      if (dst[i] == src[i]) continue;
6427
      expected_changed = true;
6428
      if (dir == ASCII_TO_LOWER) {
6429
        ASSERT('A' <= src[i] && src[i] <= 'Z');
6430
        ASSERT(dst[i] == src[i] + ('a' - 'A'));
6431
      } else {
6432
        ASSERT(dir == ASCII_TO_UPPER);
6433
        ASSERT('a' <= src[i] && src[i] <= 'z');
6434
        ASSERT(dst[i] == src[i] - ('a' - 'A'));
6435
      }
6436
    }
6437
    ASSERT(expected_changed == changed);
6438
  }
6439
#endif
6440
};
6441

    
6442

    
6443
struct ToLowerTraits {
6444
  typedef unibrow::ToLowercase UnibrowConverter;
6445

    
6446
  typedef FastAsciiConverter<ASCII_TO_LOWER> AsciiConverter;
6447
};
6448

    
6449

    
6450
struct ToUpperTraits {
6451
  typedef unibrow::ToUppercase UnibrowConverter;
6452

    
6453
  typedef FastAsciiConverter<ASCII_TO_UPPER> AsciiConverter;
6454
};
6455

    
6456
}  // namespace
6457

    
6458

    
6459
template <typename ConvertTraits>
6460
MUST_USE_RESULT static MaybeObject* ConvertCase(
6461
    Arguments args,
6462
    Isolate* isolate,
6463
    unibrow::Mapping<typename ConvertTraits::UnibrowConverter, 128>* mapping) {
6464
  SealHandleScope shs(isolate);
6465
  CONVERT_ARG_CHECKED(String, s, 0);
6466
  s = s->TryFlattenGetString();
6467

    
6468
  const int length = s->length();
6469
  // Assume that the string is not empty; we need this assumption later
6470
  if (length == 0) return s;
6471

    
6472
  // Simpler handling of ASCII strings.
6473
  //
6474
  // NOTE: This assumes that the upper/lower case of an ASCII
6475
  // character is also ASCII.  This is currently the case, but it
6476
  // might break in the future if we implement more context and locale
6477
  // dependent upper/lower conversions.
6478
  if (s->IsSeqOneByteString()) {
6479
    Object* o;
6480
    { MaybeObject* maybe_o = isolate->heap()->AllocateRawOneByteString(length);
6481
      if (!maybe_o->ToObject(&o)) return maybe_o;
6482
    }
6483
    SeqOneByteString* result = SeqOneByteString::cast(o);
6484
    bool has_changed_character;
6485
    bool is_ascii = ConvertTraits::AsciiConverter::Convert(
6486
        reinterpret_cast<char*>(result->GetChars()),
6487
        reinterpret_cast<char*>(SeqOneByteString::cast(s)->GetChars()),
6488
        length,
6489
        &has_changed_character);
6490
    // If not ASCII, we discard the result and take the 2 byte path.
6491
    if (is_ascii) {
6492
      return has_changed_character ? result : s;
6493
    }
6494
  }
6495

    
6496
  Object* answer;
6497
  { MaybeObject* maybe_answer =
6498
        ConvertCaseHelper(isolate, s, length, length, mapping);
6499
    if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6500
  }
6501
  if (answer->IsSmi()) {
6502
    // Retry with correct length.
6503
    { MaybeObject* maybe_answer =
6504
          ConvertCaseHelper(isolate,
6505
                            s, Smi::cast(answer)->value(), length, mapping);
6506
      if (!maybe_answer->ToObject(&answer)) return maybe_answer;
6507
    }
6508
  }
6509
  return answer;
6510
}
6511

    
6512

    
6513
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToLowerCase) {
6514
  return ConvertCase<ToLowerTraits>(
6515
      args, isolate, isolate->runtime_state()->to_lower_mapping());
6516
}
6517

    
6518

    
6519
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToUpperCase) {
6520
  return ConvertCase<ToUpperTraits>(
6521
      args, isolate, isolate->runtime_state()->to_upper_mapping());
6522
}
6523

    
6524

    
6525
static inline bool IsTrimWhiteSpace(unibrow::uchar c) {
6526
  return unibrow::WhiteSpace::Is(c) || c == 0x200b || c == 0xfeff;
6527
}
6528

    
6529

    
6530
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) {
6531
  SealHandleScope shs(isolate);
6532
  ASSERT(args.length() == 3);
6533

    
6534
  CONVERT_ARG_CHECKED(String, s, 0);
6535
  CONVERT_BOOLEAN_ARG_CHECKED(trimLeft, 1);
6536
  CONVERT_BOOLEAN_ARG_CHECKED(trimRight, 2);
6537

    
6538
  s->TryFlatten();
6539
  int length = s->length();
6540

    
6541
  int left = 0;
6542
  if (trimLeft) {
6543
    while (left < length && IsTrimWhiteSpace(s->Get(left))) {
6544
      left++;
6545
    }
6546
  }
6547

    
6548
  int right = length;
6549
  if (trimRight) {
6550
    while (right > left && IsTrimWhiteSpace(s->Get(right - 1))) {
6551
      right--;
6552
    }
6553
  }
6554
  return s->SubString(left, right);
6555
}
6556

    
6557

    
6558
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) {
6559
  HandleScope handle_scope(isolate);
6560
  ASSERT(args.length() == 3);
6561
  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
6562
  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
6563
  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
6564

    
6565
  int subject_length = subject->length();
6566
  int pattern_length = pattern->length();
6567
  RUNTIME_ASSERT(pattern_length > 0);
6568

    
6569
  if (limit == 0xffffffffu) {
6570
    Handle<Object> cached_answer(
6571
        RegExpResultsCache::Lookup(isolate->heap(),
6572
                                   *subject,
6573
                                   *pattern,
6574
                                   RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
6575
        isolate);
6576
    if (*cached_answer != Smi::FromInt(0)) {
6577
      // The cache FixedArray is a COW-array and can therefore be reused.
6578
      Handle<JSArray> result =
6579
          isolate->factory()->NewJSArrayWithElements(
6580
              Handle<FixedArray>::cast(cached_answer));
6581
      return *result;
6582
    }
6583
  }
6584

    
6585
  // The limit can be very large (0xffffffffu), but since the pattern
6586
  // isn't empty, we can never create more parts than ~half the length
6587
  // of the subject.
6588

    
6589
  if (!subject->IsFlat()) FlattenString(subject);
6590

    
6591
  static const int kMaxInitialListCapacity = 16;
6592

    
6593
  ZoneScope zone_scope(isolate->runtime_zone());
6594

    
6595
  // Find (up to limit) indices of separator and end-of-string in subject
6596
  int initial_capacity = Min<uint32_t>(kMaxInitialListCapacity, limit);
6597
  ZoneList<int> indices(initial_capacity, zone_scope.zone());
6598
  if (!pattern->IsFlat()) FlattenString(pattern);
6599

    
6600
  FindStringIndicesDispatch(isolate, *subject, *pattern,
6601
                            &indices, limit, zone_scope.zone());
6602

    
6603
  if (static_cast<uint32_t>(indices.length()) < limit) {
6604
    indices.Add(subject_length, zone_scope.zone());
6605
  }
6606

    
6607
  // The list indices now contains the end of each part to create.
6608

    
6609
  // Create JSArray of substrings separated by separator.
6610
  int part_count = indices.length();
6611

    
6612
  Handle<JSArray> result = isolate->factory()->NewJSArray(part_count);
6613
  JSObject::EnsureCanContainHeapObjectElements(result);
6614
  result->set_length(Smi::FromInt(part_count));
6615

    
6616
  ASSERT(result->HasFastObjectElements());
6617

    
6618
  if (part_count == 1 && indices.at(0) == subject_length) {
6619
    FixedArray::cast(result->elements())->set(0, *subject);
6620
    return *result;
6621
  }
6622

    
6623
  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
6624
  int part_start = 0;
6625
  for (int i = 0; i < part_count; i++) {
6626
    HandleScope local_loop_handle(isolate);
6627
    int part_end = indices.at(i);
6628
    Handle<String> substring =
6629
        isolate->factory()->NewProperSubString(subject, part_start, part_end);
6630
    elements->set(i, *substring);
6631
    part_start = part_end + pattern_length;
6632
  }
6633

    
6634
  if (limit == 0xffffffffu) {
6635
    if (result->HasFastObjectElements()) {
6636
      RegExpResultsCache::Enter(isolate->heap(),
6637
                                *subject,
6638
                                *pattern,
6639
                                *elements,
6640
                                RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
6641
    }
6642
  }
6643

    
6644
  return *result;
6645
}
6646

    
6647

    
6648
// Copies ASCII characters to the given fixed array looking up
6649
// one-char strings in the cache. Gives up on the first char that is
6650
// not in the cache and fills the remainder with smi zeros. Returns
6651
// the length of the successfully copied prefix.
6652
static int CopyCachedAsciiCharsToArray(Heap* heap,
6653
                                       const uint8_t* chars,
6654
                                       FixedArray* elements,
6655
                                       int length) {
6656
  DisallowHeapAllocation no_gc;
6657
  FixedArray* ascii_cache = heap->single_character_string_cache();
6658
  Object* undefined = heap->undefined_value();
6659
  int i;
6660
  WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
6661
  for (i = 0; i < length; ++i) {
6662
    Object* value = ascii_cache->get(chars[i]);
6663
    if (value == undefined) break;
6664
    elements->set(i, value, mode);
6665
  }
6666
  if (i < length) {
6667
    ASSERT(Smi::FromInt(0) == 0);
6668
    memset(elements->data_start() + i, 0, kPointerSize * (length - i));
6669
  }
6670
#ifdef DEBUG
6671
  for (int j = 0; j < length; ++j) {
6672
    Object* element = elements->get(j);
6673
    ASSERT(element == Smi::FromInt(0) ||
6674
           (element->IsString() && String::cast(element)->LooksValid()));
6675
  }
6676
#endif
6677
  return i;
6678
}
6679

    
6680

    
6681
// Converts a String to JSArray.
6682
// For example, "foo" => ["f", "o", "o"].
6683
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToArray) {
6684
  HandleScope scope(isolate);
6685
  ASSERT(args.length() == 2);
6686
  CONVERT_ARG_HANDLE_CHECKED(String, s, 0);
6687
  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
6688

    
6689
  s = FlattenGetString(s);
6690
  const int length = static_cast<int>(Min<uint32_t>(s->length(), limit));
6691

    
6692
  Handle<FixedArray> elements;
6693
  int position = 0;
6694
  if (s->IsFlat() && s->IsOneByteRepresentation()) {
6695
    // Try using cached chars where possible.
6696
    Object* obj;
6697
    { MaybeObject* maybe_obj =
6698
          isolate->heap()->AllocateUninitializedFixedArray(length);
6699
      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
6700
    }
6701
    elements = Handle<FixedArray>(FixedArray::cast(obj), isolate);
6702
    DisallowHeapAllocation no_gc;
6703
    String::FlatContent content = s->GetFlatContent();
6704
    if (content.IsAscii()) {
6705
      Vector<const uint8_t> chars = content.ToOneByteVector();
6706
      // Note, this will initialize all elements (not only the prefix)
6707
      // to prevent GC from seeing partially initialized array.
6708
      position = CopyCachedAsciiCharsToArray(isolate->heap(),
6709
                                             chars.start(),
6710
                                             *elements,
6711
                                             length);
6712
    } else {
6713
      MemsetPointer(elements->data_start(),
6714
                    isolate->heap()->undefined_value(),
6715
                    length);
6716
    }
6717
  } else {
6718
    elements = isolate->factory()->NewFixedArray(length);
6719
  }
6720
  for (int i = position; i < length; ++i) {
6721
    Handle<Object> str =
6722
        LookupSingleCharacterStringFromCode(isolate, s->Get(i));
6723
    elements->set(i, *str);
6724
  }
6725

    
6726
#ifdef DEBUG
6727
  for (int i = 0; i < length; ++i) {
6728
    ASSERT(String::cast(elements->get(i))->length() == 1);
6729
  }
6730
#endif
6731

    
6732
  return *isolate->factory()->NewJSArrayWithElements(elements);
6733
}
6734

    
6735

    
6736
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStringWrapper) {
6737
  SealHandleScope shs(isolate);
6738
  ASSERT(args.length() == 1);
6739
  CONVERT_ARG_CHECKED(String, value, 0);
6740
  return value->ToObject(isolate);
6741
}
6742

    
6743

    
6744
bool Runtime::IsUpperCaseChar(RuntimeState* runtime_state, uint16_t ch) {
6745
  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
6746
  int char_length = runtime_state->to_upper_mapping()->get(ch, 0, chars);
6747
  return char_length == 0;
6748
}
6749

    
6750

    
6751
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToString) {
6752
  SealHandleScope shs(isolate);
6753
  ASSERT(args.length() == 1);
6754

    
6755
  Object* number = args[0];
6756
  RUNTIME_ASSERT(number->IsNumber());
6757

    
6758
  return isolate->heap()->NumberToString(number);
6759
}
6760

    
6761

    
6762
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToStringSkipCache) {
6763
  SealHandleScope shs(isolate);
6764
  ASSERT(args.length() == 1);
6765

    
6766
  Object* number = args[0];
6767
  RUNTIME_ASSERT(number->IsNumber());
6768

    
6769
  return isolate->heap()->NumberToString(
6770
      number, false, isolate->heap()->GetPretenureMode());
6771
}
6772

    
6773

    
6774
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToInteger) {
6775
  SealHandleScope shs(isolate);
6776
  ASSERT(args.length() == 1);
6777

    
6778
  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6779

    
6780
  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6781
  if (number > 0 && number <= Smi::kMaxValue) {
6782
    return Smi::FromInt(static_cast<int>(number));
6783
  }
6784
  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6785
}
6786

    
6787

    
6788
// ES6 draft 9.1.11
6789
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPositiveInteger) {
6790
  SealHandleScope shs(isolate);
6791
  ASSERT(args.length() == 1);
6792

    
6793
  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6794

    
6795
  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6796
  if (number > 0 && number <= Smi::kMaxValue) {
6797
    return Smi::FromInt(static_cast<int>(number));
6798
  }
6799
  if (number <= 0) {
6800
    return Smi::FromInt(0);
6801
  }
6802
  return isolate->heap()->NumberFromDouble(DoubleToInteger(number));
6803
}
6804

    
6805

    
6806
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToIntegerMapMinusZero) {
6807
  SealHandleScope shs(isolate);
6808
  ASSERT(args.length() == 1);
6809

    
6810
  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6811

    
6812
  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6813
  if (number > 0 && number <= Smi::kMaxValue) {
6814
    return Smi::FromInt(static_cast<int>(number));
6815
  }
6816

    
6817
  double double_value = DoubleToInteger(number);
6818
  // Map both -0 and +0 to +0.
6819
  if (double_value == 0) double_value = 0;
6820

    
6821
  return isolate->heap()->NumberFromDouble(double_value);
6822
}
6823

    
6824

    
6825
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSUint32) {
6826
  SealHandleScope shs(isolate);
6827
  ASSERT(args.length() == 1);
6828

    
6829
  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, args[0]);
6830
  return isolate->heap()->NumberFromUint32(number);
6831
}
6832

    
6833

    
6834
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToJSInt32) {
6835
  SealHandleScope shs(isolate);
6836
  ASSERT(args.length() == 1);
6837

    
6838
  CONVERT_DOUBLE_ARG_CHECKED(number, 0);
6839

    
6840
  // We do not include 0 so that we don't have to treat +0 / -0 cases.
6841
  if (number > 0 && number <= Smi::kMaxValue) {
6842
    return Smi::FromInt(static_cast<int>(number));
6843
  }
6844
  return isolate->heap()->NumberFromInt32(DoubleToInt32(number));
6845
}
6846

    
6847

    
6848
// Converts a Number to a Smi, if possible. Returns NaN if the number is not
6849
// a small integer.
6850
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToSmi) {
6851
  SealHandleScope shs(isolate);
6852
  ASSERT(args.length() == 1);
6853

    
6854
  Object* obj = args[0];
6855
  if (obj->IsSmi()) {
6856
    return obj;
6857
  }
6858
  if (obj->IsHeapNumber()) {
6859
    double value = HeapNumber::cast(obj)->value();
6860
    int int_value = FastD2I(value);
6861
    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
6862
      return Smi::FromInt(int_value);
6863
    }
6864
  }
6865
  return isolate->heap()->nan_value();
6866
}
6867

    
6868

    
6869
RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateHeapNumber) {
6870
  SealHandleScope shs(isolate);
6871
  ASSERT(args.length() == 0);
6872
  return isolate->heap()->AllocateHeapNumber(0);
6873
}
6874

    
6875

    
6876
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAdd) {
6877
  SealHandleScope shs(isolate);
6878
  ASSERT(args.length() == 2);
6879

    
6880
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6881
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6882
  return isolate->heap()->NumberFromDouble(x + y);
6883
}
6884

    
6885

    
6886
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSub) {
6887
  SealHandleScope shs(isolate);
6888
  ASSERT(args.length() == 2);
6889

    
6890
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6891
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6892
  return isolate->heap()->NumberFromDouble(x - y);
6893
}
6894

    
6895

    
6896
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMul) {
6897
  SealHandleScope shs(isolate);
6898
  ASSERT(args.length() == 2);
6899

    
6900
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6901
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6902
  return isolate->heap()->NumberFromDouble(x * y);
6903
}
6904

    
6905

    
6906
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberUnaryMinus) {
6907
  SealHandleScope shs(isolate);
6908
  ASSERT(args.length() == 1);
6909

    
6910
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6911
  return isolate->heap()->NumberFromDouble(-x);
6912
}
6913

    
6914

    
6915
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAlloc) {
6916
  SealHandleScope shs(isolate);
6917
  ASSERT(args.length() == 0);
6918

    
6919
  return isolate->heap()->NumberFromDouble(9876543210.0);
6920
}
6921

    
6922

    
6923
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberDiv) {
6924
  SealHandleScope shs(isolate);
6925
  ASSERT(args.length() == 2);
6926

    
6927
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6928
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6929
  return isolate->heap()->NumberFromDouble(x / y);
6930
}
6931

    
6932

    
6933
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberMod) {
6934
  SealHandleScope shs(isolate);
6935
  ASSERT(args.length() == 2);
6936

    
6937
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
6938
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
6939

    
6940
  x = modulo(x, y);
6941
  // NumberFromDouble may return a Smi instead of a Number object
6942
  return isolate->heap()->NumberFromDouble(x);
6943
}
6944

    
6945

    
6946
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberImul) {
6947
  SealHandleScope shs(isolate);
6948
  ASSERT(args.length() == 2);
6949

    
6950
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
6951
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
6952
  return isolate->heap()->NumberFromInt32(x * y);
6953
}
6954

    
6955

    
6956
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringAdd) {
6957
  SealHandleScope shs(isolate);
6958
  ASSERT(args.length() == 2);
6959
  CONVERT_ARG_CHECKED(String, str1, 0);
6960
  CONVERT_ARG_CHECKED(String, str2, 1);
6961
  isolate->counters()->string_add_runtime()->Increment();
6962
  return isolate->heap()->AllocateConsString(str1, str2);
6963
}
6964

    
6965

    
6966
template <typename sinkchar>
6967
static inline void StringBuilderConcatHelper(String* special,
6968
                                             sinkchar* sink,
6969
                                             FixedArray* fixed_array,
6970
                                             int array_length) {
6971
  int position = 0;
6972
  for (int i = 0; i < array_length; i++) {
6973
    Object* element = fixed_array->get(i);
6974
    if (element->IsSmi()) {
6975
      // Smi encoding of position and length.
6976
      int encoded_slice = Smi::cast(element)->value();
6977
      int pos;
6978
      int len;
6979
      if (encoded_slice > 0) {
6980
        // Position and length encoded in one smi.
6981
        pos = StringBuilderSubstringPosition::decode(encoded_slice);
6982
        len = StringBuilderSubstringLength::decode(encoded_slice);
6983
      } else {
6984
        // Position and length encoded in two smis.
6985
        Object* obj = fixed_array->get(++i);
6986
        ASSERT(obj->IsSmi());
6987
        pos = Smi::cast(obj)->value();
6988
        len = -encoded_slice;
6989
      }
6990
      String::WriteToFlat(special,
6991
                          sink + position,
6992
                          pos,
6993
                          pos + len);
6994
      position += len;
6995
    } else {
6996
      String* string = String::cast(element);
6997
      int element_length = string->length();
6998
      String::WriteToFlat(string, sink + position, 0, element_length);
6999
      position += element_length;
7000
    }
7001
  }
7002
}
7003

    
7004

    
7005
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
7006
  HandleScope scope(isolate);
7007
  ASSERT(args.length() == 3);
7008
  CONVERT_ARG_HANDLE_CHECKED(JSArray, array, 0);
7009
  if (!args[1]->IsSmi()) {
7010
    isolate->context()->mark_out_of_memory();
7011
    return Failure::OutOfMemoryException(0x14);
7012
  }
7013
  int array_length = args.smi_at(1);
7014
  CONVERT_ARG_HANDLE_CHECKED(String, special, 2);
7015

    
7016
  // This assumption is used by the slice encoding in one or two smis.
7017
  ASSERT(Smi::kMaxValue >= String::kMaxLength);
7018

    
7019
  JSObject::EnsureCanContainHeapObjectElements(array);
7020

    
7021
  int special_length = special->length();
7022
  if (!array->HasFastObjectElements()) {
7023
    return isolate->Throw(isolate->heap()->illegal_argument_string());
7024
  }
7025
  FixedArray* fixed_array = FixedArray::cast(array->elements());
7026
  if (fixed_array->length() < array_length) {
7027
    array_length = fixed_array->length();
7028
  }
7029

    
7030
  if (array_length == 0) {
7031
    return isolate->heap()->empty_string();
7032
  } else if (array_length == 1) {
7033
    Object* first = fixed_array->get(0);
7034
    if (first->IsString()) return first;
7035
  }
7036

    
7037
  bool one_byte = special->HasOnlyOneByteChars();
7038
  int position = 0;
7039
  for (int i = 0; i < array_length; i++) {
7040
    int increment = 0;
7041
    Object* elt = fixed_array->get(i);
7042
    if (elt->IsSmi()) {
7043
      // Smi encoding of position and length.
7044
      int smi_value = Smi::cast(elt)->value();
7045
      int pos;
7046
      int len;
7047
      if (smi_value > 0) {
7048
        // Position and length encoded in one smi.
7049
        pos = StringBuilderSubstringPosition::decode(smi_value);
7050
        len = StringBuilderSubstringLength::decode(smi_value);
7051
      } else {
7052
        // Position and length encoded in two smis.
7053
        len = -smi_value;
7054
        // Get the position and check that it is a positive smi.
7055
        i++;
7056
        if (i >= array_length) {
7057
          return isolate->Throw(isolate->heap()->illegal_argument_string());
7058
        }
7059
        Object* next_smi = fixed_array->get(i);
7060
        if (!next_smi->IsSmi()) {
7061
          return isolate->Throw(isolate->heap()->illegal_argument_string());
7062
        }
7063
        pos = Smi::cast(next_smi)->value();
7064
        if (pos < 0) {
7065
          return isolate->Throw(isolate->heap()->illegal_argument_string());
7066
        }
7067
      }
7068
      ASSERT(pos >= 0);
7069
      ASSERT(len >= 0);
7070
      if (pos > special_length || len > special_length - pos) {
7071
        return isolate->Throw(isolate->heap()->illegal_argument_string());
7072
      }
7073
      increment = len;
7074
    } else if (elt->IsString()) {
7075
      String* element = String::cast(elt);
7076
      int element_length = element->length();
7077
      increment = element_length;
7078
      if (one_byte && !element->HasOnlyOneByteChars()) {
7079
        one_byte = false;
7080
      }
7081
    } else {
7082
      ASSERT(!elt->IsTheHole());
7083
      return isolate->Throw(isolate->heap()->illegal_argument_string());
7084
    }
7085
    if (increment > String::kMaxLength - position) {
7086
      isolate->context()->mark_out_of_memory();
7087
      return Failure::OutOfMemoryException(0x15);
7088
    }
7089
    position += increment;
7090
  }
7091

    
7092
  int length = position;
7093
  Object* object;
7094

    
7095
  if (one_byte) {
7096
    { MaybeObject* maybe_object =
7097
          isolate->heap()->AllocateRawOneByteString(length);
7098
      if (!maybe_object->ToObject(&object)) return maybe_object;
7099
    }
7100
    SeqOneByteString* answer = SeqOneByteString::cast(object);
7101
    StringBuilderConcatHelper(*special,
7102
                              answer->GetChars(),
7103
                              fixed_array,
7104
                              array_length);
7105
    return answer;
7106
  } else {
7107
    { MaybeObject* maybe_object =
7108
          isolate->heap()->AllocateRawTwoByteString(length);
7109
      if (!maybe_object->ToObject(&object)) return maybe_object;
7110
    }
7111
    SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7112
    StringBuilderConcatHelper(*special,
7113
                              answer->GetChars(),
7114
                              fixed_array,
7115
                              array_length);
7116
    return answer;
7117
  }
7118
}
7119

    
7120

    
7121
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
7122
  SealHandleScope shs(isolate);
7123
  ASSERT(args.length() == 3);
7124
  CONVERT_ARG_CHECKED(JSArray, array, 0);
7125
  if (!args[1]->IsSmi()) {
7126
    isolate->context()->mark_out_of_memory();
7127
    return Failure::OutOfMemoryException(0x16);
7128
  }
7129
  int array_length = args.smi_at(1);
7130
  CONVERT_ARG_CHECKED(String, separator, 2);
7131

    
7132
  if (!array->HasFastObjectElements()) {
7133
    return isolate->Throw(isolate->heap()->illegal_argument_string());
7134
  }
7135
  FixedArray* fixed_array = FixedArray::cast(array->elements());
7136
  if (fixed_array->length() < array_length) {
7137
    array_length = fixed_array->length();
7138
  }
7139

    
7140
  if (array_length == 0) {
7141
    return isolate->heap()->empty_string();
7142
  } else if (array_length == 1) {
7143
    Object* first = fixed_array->get(0);
7144
    if (first->IsString()) return first;
7145
  }
7146

    
7147
  int separator_length = separator->length();
7148
  int max_nof_separators =
7149
      (String::kMaxLength + separator_length - 1) / separator_length;
7150
  if (max_nof_separators < (array_length - 1)) {
7151
      isolate->context()->mark_out_of_memory();
7152
      return Failure::OutOfMemoryException(0x17);
7153
  }
7154
  int length = (array_length - 1) * separator_length;
7155
  for (int i = 0; i < array_length; i++) {
7156
    Object* element_obj = fixed_array->get(i);
7157
    if (!element_obj->IsString()) {
7158
      // TODO(1161): handle this case.
7159
      return isolate->Throw(isolate->heap()->illegal_argument_string());
7160
    }
7161
    String* element = String::cast(element_obj);
7162
    int increment = element->length();
7163
    if (increment > String::kMaxLength - length) {
7164
      isolate->context()->mark_out_of_memory();
7165
      return Failure::OutOfMemoryException(0x18);
7166
    }
7167
    length += increment;
7168
  }
7169

    
7170
  Object* object;
7171
  { MaybeObject* maybe_object =
7172
        isolate->heap()->AllocateRawTwoByteString(length);
7173
    if (!maybe_object->ToObject(&object)) return maybe_object;
7174
  }
7175
  SeqTwoByteString* answer = SeqTwoByteString::cast(object);
7176

    
7177
  uc16* sink = answer->GetChars();
7178
#ifdef DEBUG
7179
  uc16* end = sink + length;
7180
#endif
7181

    
7182
  String* first = String::cast(fixed_array->get(0));
7183
  int first_length = first->length();
7184
  String::WriteToFlat(first, sink, 0, first_length);
7185
  sink += first_length;
7186

    
7187
  for (int i = 1; i < array_length; i++) {
7188
    ASSERT(sink + separator_length <= end);
7189
    String::WriteToFlat(separator, sink, 0, separator_length);
7190
    sink += separator_length;
7191

    
7192
    String* element = String::cast(fixed_array->get(i));
7193
    int element_length = element->length();
7194
    ASSERT(sink + element_length <= end);
7195
    String::WriteToFlat(element, sink, 0, element_length);
7196
    sink += element_length;
7197
  }
7198
  ASSERT(sink == end);
7199

    
7200
  // Use %_FastAsciiArrayJoin instead.
7201
  ASSERT(!answer->IsOneByteRepresentation());
7202
  return answer;
7203
}
7204

    
7205
template <typename Char>
7206
static void JoinSparseArrayWithSeparator(FixedArray* elements,
7207
                                         int elements_length,
7208
                                         uint32_t array_length,
7209
                                         String* separator,
7210
                                         Vector<Char> buffer) {
7211
  int previous_separator_position = 0;
7212
  int separator_length = separator->length();
7213
  int cursor = 0;
7214
  for (int i = 0; i < elements_length; i += 2) {
7215
    int position = NumberToInt32(elements->get(i));
7216
    String* string = String::cast(elements->get(i + 1));
7217
    int string_length = string->length();
7218
    if (string->length() > 0) {
7219
      while (previous_separator_position < position) {
7220
        String::WriteToFlat<Char>(separator, &buffer[cursor],
7221
                                  0, separator_length);
7222
        cursor += separator_length;
7223
        previous_separator_position++;
7224
      }
7225
      String::WriteToFlat<Char>(string, &buffer[cursor],
7226
                                0, string_length);
7227
      cursor += string->length();
7228
    }
7229
  }
7230
  if (separator_length > 0) {
7231
    // Array length must be representable as a signed 32-bit number,
7232
    // otherwise the total string length would have been too large.
7233
    ASSERT(array_length <= 0x7fffffff);  // Is int32_t.
7234
    int last_array_index = static_cast<int>(array_length - 1);
7235
    while (previous_separator_position < last_array_index) {
7236
      String::WriteToFlat<Char>(separator, &buffer[cursor],
7237
                                0, separator_length);
7238
      cursor += separator_length;
7239
      previous_separator_position++;
7240
    }
7241
  }
7242
  ASSERT(cursor <= buffer.length());
7243
}
7244

    
7245

    
7246
RUNTIME_FUNCTION(MaybeObject*, Runtime_SparseJoinWithSeparator) {
7247
  SealHandleScope shs(isolate);
7248
  ASSERT(args.length() == 3);
7249
  CONVERT_ARG_CHECKED(JSArray, elements_array, 0);
7250
  RUNTIME_ASSERT(elements_array->HasFastSmiOrObjectElements());
7251
  CONVERT_NUMBER_CHECKED(uint32_t, array_length, Uint32, args[1]);
7252
  CONVERT_ARG_CHECKED(String, separator, 2);
7253
  // elements_array is fast-mode JSarray of alternating positions
7254
  // (increasing order) and strings.
7255
  // array_length is length of original array (used to add separators);
7256
  // separator is string to put between elements. Assumed to be non-empty.
7257

    
7258
  // Find total length of join result.
7259
  int string_length = 0;
7260
  bool is_ascii = separator->IsOneByteRepresentation();
7261
  int max_string_length;
7262
  if (is_ascii) {
7263
    max_string_length = SeqOneByteString::kMaxLength;
7264
  } else {
7265
    max_string_length = SeqTwoByteString::kMaxLength;
7266
  }
7267
  bool overflow = false;
7268
  CONVERT_NUMBER_CHECKED(int, elements_length,
7269
                         Int32, elements_array->length());
7270
  RUNTIME_ASSERT((elements_length & 1) == 0);  // Even length.
7271
  FixedArray* elements = FixedArray::cast(elements_array->elements());
7272
  for (int i = 0; i < elements_length; i += 2) {
7273
    RUNTIME_ASSERT(elements->get(i)->IsNumber());
7274
    RUNTIME_ASSERT(elements->get(i + 1)->IsString());
7275
    String* string = String::cast(elements->get(i + 1));
7276
    int length = string->length();
7277
    if (is_ascii && !string->IsOneByteRepresentation()) {
7278
      is_ascii = false;
7279
      max_string_length = SeqTwoByteString::kMaxLength;
7280
    }
7281
    if (length > max_string_length ||
7282
        max_string_length - length < string_length) {
7283
      overflow = true;
7284
      break;
7285
    }
7286
    string_length += length;
7287
  }
7288
  int separator_length = separator->length();
7289
  if (!overflow && separator_length > 0) {
7290
    if (array_length <= 0x7fffffffu) {
7291
      int separator_count = static_cast<int>(array_length) - 1;
7292
      int remaining_length = max_string_length - string_length;
7293
      if ((remaining_length / separator_length) >= separator_count) {
7294
        string_length += separator_length * (array_length - 1);
7295
      } else {
7296
        // Not room for the separators within the maximal string length.
7297
        overflow = true;
7298
      }
7299
    } else {
7300
      // Nonempty separator and at least 2^31-1 separators necessary
7301
      // means that the string is too large to create.
7302
      STATIC_ASSERT(String::kMaxLength < 0x7fffffff);
7303
      overflow = true;
7304
    }
7305
  }
7306
  if (overflow) {
7307
    // Throw OutOfMemory exception for creating too large a string.
7308
    V8::FatalProcessOutOfMemory("Array join result too large.");
7309
  }
7310

    
7311
  if (is_ascii) {
7312
    MaybeObject* result_allocation =
7313
        isolate->heap()->AllocateRawOneByteString(string_length);
7314
    if (result_allocation->IsFailure()) return result_allocation;
7315
    SeqOneByteString* result_string =
7316
        SeqOneByteString::cast(result_allocation->ToObjectUnchecked());
7317
    JoinSparseArrayWithSeparator<uint8_t>(elements,
7318
                                          elements_length,
7319
                                          array_length,
7320
                                          separator,
7321
                                          Vector<uint8_t>(
7322
                                              result_string->GetChars(),
7323
                                              string_length));
7324
    return result_string;
7325
  } else {
7326
    MaybeObject* result_allocation =
7327
        isolate->heap()->AllocateRawTwoByteString(string_length);
7328
    if (result_allocation->IsFailure()) return result_allocation;
7329
    SeqTwoByteString* result_string =
7330
        SeqTwoByteString::cast(result_allocation->ToObjectUnchecked());
7331
    JoinSparseArrayWithSeparator<uc16>(elements,
7332
                                       elements_length,
7333
                                       array_length,
7334
                                       separator,
7335
                                       Vector<uc16>(result_string->GetChars(),
7336
                                                    string_length));
7337
    return result_string;
7338
  }
7339
}
7340

    
7341

    
7342
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberOr) {
7343
  SealHandleScope shs(isolate);
7344
  ASSERT(args.length() == 2);
7345

    
7346
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7347
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7348
  return isolate->heap()->NumberFromInt32(x | y);
7349
}
7350

    
7351

    
7352
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberAnd) {
7353
  SealHandleScope shs(isolate);
7354
  ASSERT(args.length() == 2);
7355

    
7356
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7357
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7358
  return isolate->heap()->NumberFromInt32(x & y);
7359
}
7360

    
7361

    
7362
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberXor) {
7363
  SealHandleScope shs(isolate);
7364
  ASSERT(args.length() == 2);
7365

    
7366
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7367
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7368
  return isolate->heap()->NumberFromInt32(x ^ y);
7369
}
7370

    
7371

    
7372
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShl) {
7373
  SealHandleScope shs(isolate);
7374
  ASSERT(args.length() == 2);
7375

    
7376
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7377
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7378
  return isolate->heap()->NumberFromInt32(x << (y & 0x1f));
7379
}
7380

    
7381

    
7382
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberShr) {
7383
  SealHandleScope shs(isolate);
7384
  ASSERT(args.length() == 2);
7385

    
7386
  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
7387
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7388
  return isolate->heap()->NumberFromUint32(x >> (y & 0x1f));
7389
}
7390

    
7391

    
7392
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberSar) {
7393
  SealHandleScope shs(isolate);
7394
  ASSERT(args.length() == 2);
7395

    
7396
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
7397
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
7398
  return isolate->heap()->NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
7399
}
7400

    
7401

    
7402
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
7403
  SealHandleScope shs(isolate);
7404
  ASSERT(args.length() == 2);
7405

    
7406
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7407
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7408
  if (std::isnan(x)) return Smi::FromInt(NOT_EQUAL);
7409
  if (std::isnan(y)) return Smi::FromInt(NOT_EQUAL);
7410
  if (x == y) return Smi::FromInt(EQUAL);
7411
  Object* result;
7412
  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
7413
    result = Smi::FromInt(EQUAL);
7414
  } else {
7415
    result = Smi::FromInt(NOT_EQUAL);
7416
  }
7417
  return result;
7418
}
7419

    
7420

    
7421
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
7422
  SealHandleScope shs(isolate);
7423
  ASSERT(args.length() == 2);
7424

    
7425
  CONVERT_ARG_CHECKED(String, x, 0);
7426
  CONVERT_ARG_CHECKED(String, y, 1);
7427

    
7428
  bool not_equal = !x->Equals(y);
7429
  // This is slightly convoluted because the value that signifies
7430
  // equality is 0 and inequality is 1 so we have to negate the result
7431
  // from String::Equals.
7432
  ASSERT(not_equal == 0 || not_equal == 1);
7433
  STATIC_CHECK(EQUAL == 0);
7434
  STATIC_CHECK(NOT_EQUAL == 1);
7435
  return Smi::FromInt(not_equal);
7436
}
7437

    
7438

    
7439
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
7440
  SealHandleScope shs(isolate);
7441
  ASSERT(args.length() == 3);
7442

    
7443
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7444
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7445
  if (std::isnan(x) || std::isnan(y)) return args[2];
7446
  if (x == y) return Smi::FromInt(EQUAL);
7447
  if (isless(x, y)) return Smi::FromInt(LESS);
7448
  return Smi::FromInt(GREATER);
7449
}
7450

    
7451

    
7452
// Compare two Smis as if they were converted to strings and then
7453
// compared lexicographically.
7454
RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
7455
  SealHandleScope shs(isolate);
7456
  ASSERT(args.length() == 2);
7457
  CONVERT_SMI_ARG_CHECKED(x_value, 0);
7458
  CONVERT_SMI_ARG_CHECKED(y_value, 1);
7459

    
7460
  // If the integers are equal so are the string representations.
7461
  if (x_value == y_value) return Smi::FromInt(EQUAL);
7462

    
7463
  // If one of the integers is zero the normal integer order is the
7464
  // same as the lexicographic order of the string representations.
7465
  if (x_value == 0 || y_value == 0)
7466
    return Smi::FromInt(x_value < y_value ? LESS : GREATER);
7467

    
7468
  // If only one of the integers is negative the negative number is
7469
  // smallest because the char code of '-' is less than the char code
7470
  // of any digit.  Otherwise, we make both values positive.
7471

    
7472
  // Use unsigned values otherwise the logic is incorrect for -MIN_INT on
7473
  // architectures using 32-bit Smis.
7474
  uint32_t x_scaled = x_value;
7475
  uint32_t y_scaled = y_value;
7476
  if (x_value < 0 || y_value < 0) {
7477
    if (y_value >= 0) return Smi::FromInt(LESS);
7478
    if (x_value >= 0) return Smi::FromInt(GREATER);
7479
    x_scaled = -x_value;
7480
    y_scaled = -y_value;
7481
  }
7482

    
7483
  static const uint32_t kPowersOf10[] = {
7484
    1, 10, 100, 1000, 10*1000, 100*1000,
7485
    1000*1000, 10*1000*1000, 100*1000*1000,
7486
    1000*1000*1000
7487
  };
7488

    
7489
  // If the integers have the same number of decimal digits they can be
7490
  // compared directly as the numeric order is the same as the
7491
  // lexicographic order.  If one integer has fewer digits, it is scaled
7492
  // by some power of 10 to have the same number of digits as the longer
7493
  // integer.  If the scaled integers are equal it means the shorter
7494
  // integer comes first in the lexicographic order.
7495

    
7496
  // From http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
7497
  int x_log2 = IntegerLog2(x_scaled);
7498
  int x_log10 = ((x_log2 + 1) * 1233) >> 12;
7499
  x_log10 -= x_scaled < kPowersOf10[x_log10];
7500

    
7501
  int y_log2 = IntegerLog2(y_scaled);
7502
  int y_log10 = ((y_log2 + 1) * 1233) >> 12;
7503
  y_log10 -= y_scaled < kPowersOf10[y_log10];
7504

    
7505
  int tie = EQUAL;
7506

    
7507
  if (x_log10 < y_log10) {
7508
    // X has fewer digits.  We would like to simply scale up X but that
7509
    // might overflow, e.g when comparing 9 with 1_000_000_000, 9 would
7510
    // be scaled up to 9_000_000_000. So we scale up by the next
7511
    // smallest power and scale down Y to drop one digit. It is OK to
7512
    // drop one digit from the longer integer since the final digit is
7513
    // past the length of the shorter integer.
7514
    x_scaled *= kPowersOf10[y_log10 - x_log10 - 1];
7515
    y_scaled /= 10;
7516
    tie = LESS;
7517
  } else if (y_log10 < x_log10) {
7518
    y_scaled *= kPowersOf10[x_log10 - y_log10 - 1];
7519
    x_scaled /= 10;
7520
    tie = GREATER;
7521
  }
7522

    
7523
  if (x_scaled < y_scaled) return Smi::FromInt(LESS);
7524
  if (x_scaled > y_scaled) return Smi::FromInt(GREATER);
7525
  return Smi::FromInt(tie);
7526
}
7527

    
7528

    
7529
static Object* StringCharacterStreamCompare(RuntimeState* state,
7530
                                        String* x,
7531
                                        String* y) {
7532
  StringCharacterStream stream_x(x, state->string_iterator_compare_x());
7533
  StringCharacterStream stream_y(y, state->string_iterator_compare_y());
7534
  while (stream_x.HasMore() && stream_y.HasMore()) {
7535
    int d = stream_x.GetNext() - stream_y.GetNext();
7536
    if (d < 0) return Smi::FromInt(LESS);
7537
    else if (d > 0) return Smi::FromInt(GREATER);
7538
  }
7539

    
7540
  // x is (non-trivial) prefix of y:
7541
  if (stream_y.HasMore()) return Smi::FromInt(LESS);
7542
  // y is prefix of x:
7543
  return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
7544
}
7545

    
7546

    
7547
static Object* FlatStringCompare(String* x, String* y) {
7548
  ASSERT(x->IsFlat());
7549
  ASSERT(y->IsFlat());
7550
  Object* equal_prefix_result = Smi::FromInt(EQUAL);
7551
  int prefix_length = x->length();
7552
  if (y->length() < prefix_length) {
7553
    prefix_length = y->length();
7554
    equal_prefix_result = Smi::FromInt(GREATER);
7555
  } else if (y->length() > prefix_length) {
7556
    equal_prefix_result = Smi::FromInt(LESS);
7557
  }
7558
  int r;
7559
  DisallowHeapAllocation no_gc;
7560
  String::FlatContent x_content = x->GetFlatContent();
7561
  String::FlatContent y_content = y->GetFlatContent();
7562
  if (x_content.IsAscii()) {
7563
    Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
7564
    if (y_content.IsAscii()) {
7565
      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7566
      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7567
    } else {
7568
      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7569
      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7570
    }
7571
  } else {
7572
    Vector<const uc16> x_chars = x_content.ToUC16Vector();
7573
    if (y_content.IsAscii()) {
7574
      Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
7575
      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7576
    } else {
7577
      Vector<const uc16> y_chars = y_content.ToUC16Vector();
7578
      r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
7579
    }
7580
  }
7581
  Object* result;
7582
  if (r == 0) {
7583
    result = equal_prefix_result;
7584
  } else {
7585
    result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
7586
  }
7587
  ASSERT(result ==
7588
      StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
7589
  return result;
7590
}
7591

    
7592

    
7593
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCompare) {
7594
  SealHandleScope shs(isolate);
7595
  ASSERT(args.length() == 2);
7596

    
7597
  CONVERT_ARG_CHECKED(String, x, 0);
7598
  CONVERT_ARG_CHECKED(String, y, 1);
7599

    
7600
  isolate->counters()->string_compare_runtime()->Increment();
7601

    
7602
  // A few fast case tests before we flatten.
7603
  if (x == y) return Smi::FromInt(EQUAL);
7604
  if (y->length() == 0) {
7605
    if (x->length() == 0) return Smi::FromInt(EQUAL);
7606
    return Smi::FromInt(GREATER);
7607
  } else if (x->length() == 0) {
7608
    return Smi::FromInt(LESS);
7609
  }
7610

    
7611
  int d = x->Get(0) - y->Get(0);
7612
  if (d < 0) return Smi::FromInt(LESS);
7613
  else if (d > 0) return Smi::FromInt(GREATER);
7614

    
7615
  Object* obj;
7616
  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
7617
    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7618
  }
7619
  { MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
7620
    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
7621
  }
7622

    
7623
  return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
7624
      : StringCharacterStreamCompare(isolate->runtime_state(), x, y);
7625
}
7626

    
7627

    
7628
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_acos) {
7629
  SealHandleScope shs(isolate);
7630
  ASSERT(args.length() == 1);
7631
  isolate->counters()->math_acos()->Increment();
7632

    
7633
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7634
  return isolate->transcendental_cache()->Get(TranscendentalCache::ACOS, x);
7635
}
7636

    
7637

    
7638
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_asin) {
7639
  SealHandleScope shs(isolate);
7640
  ASSERT(args.length() == 1);
7641
  isolate->counters()->math_asin()->Increment();
7642

    
7643
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7644
  return isolate->transcendental_cache()->Get(TranscendentalCache::ASIN, x);
7645
}
7646

    
7647

    
7648
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan) {
7649
  SealHandleScope shs(isolate);
7650
  ASSERT(args.length() == 1);
7651
  isolate->counters()->math_atan()->Increment();
7652

    
7653
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7654
  return isolate->transcendental_cache()->Get(TranscendentalCache::ATAN, x);
7655
}
7656

    
7657

    
7658
static const double kPiDividedBy4 = 0.78539816339744830962;
7659

    
7660

    
7661
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_atan2) {
7662
  SealHandleScope shs(isolate);
7663
  ASSERT(args.length() == 2);
7664
  isolate->counters()->math_atan2()->Increment();
7665

    
7666
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7667
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7668
  double result;
7669
  if (std::isinf(x) && std::isinf(y)) {
7670
    // Make sure that the result in case of two infinite arguments
7671
    // is a multiple of Pi / 4. The sign of the result is determined
7672
    // by the first argument (x) and the sign of the second argument
7673
    // determines the multiplier: one or three.
7674
    int multiplier = (x < 0) ? -1 : 1;
7675
    if (y < 0) multiplier *= 3;
7676
    result = multiplier * kPiDividedBy4;
7677
  } else {
7678
    result = atan2(x, y);
7679
  }
7680
  return isolate->heap()->AllocateHeapNumber(result);
7681
}
7682

    
7683

    
7684
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_ceil) {
7685
  SealHandleScope shs(isolate);
7686
  ASSERT(args.length() == 1);
7687
  isolate->counters()->math_ceil()->Increment();
7688

    
7689
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7690
  return isolate->heap()->NumberFromDouble(ceiling(x));
7691
}
7692

    
7693

    
7694
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_cos) {
7695
  SealHandleScope shs(isolate);
7696
  ASSERT(args.length() == 1);
7697
  isolate->counters()->math_cos()->Increment();
7698

    
7699
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7700
  return isolate->transcendental_cache()->Get(TranscendentalCache::COS, x);
7701
}
7702

    
7703

    
7704
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_exp) {
7705
  SealHandleScope shs(isolate);
7706
  ASSERT(args.length() == 1);
7707
  isolate->counters()->math_exp()->Increment();
7708

    
7709
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7710
  lazily_initialize_fast_exp();
7711
  return isolate->heap()->NumberFromDouble(fast_exp(x));
7712
}
7713

    
7714

    
7715
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_floor) {
7716
  SealHandleScope shs(isolate);
7717
  ASSERT(args.length() == 1);
7718
  isolate->counters()->math_floor()->Increment();
7719

    
7720
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7721
  return isolate->heap()->NumberFromDouble(floor(x));
7722
}
7723

    
7724

    
7725
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_log) {
7726
  SealHandleScope shs(isolate);
7727
  ASSERT(args.length() == 1);
7728
  isolate->counters()->math_log()->Increment();
7729

    
7730
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7731
  return isolate->transcendental_cache()->Get(TranscendentalCache::LOG, x);
7732
}
7733

    
7734

    
7735
// Slow version of Math.pow.  We check for fast paths for special cases.
7736
// Used if SSE2/VFP3 is not available.
7737
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow) {
7738
  SealHandleScope shs(isolate);
7739
  ASSERT(args.length() == 2);
7740
  isolate->counters()->math_pow()->Increment();
7741

    
7742
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7743

    
7744
  // If the second argument is a smi, it is much faster to call the
7745
  // custom powi() function than the generic pow().
7746
  if (args[1]->IsSmi()) {
7747
    int y = args.smi_at(1);
7748
    return isolate->heap()->NumberFromDouble(power_double_int(x, y));
7749
  }
7750

    
7751
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7752
  double result = power_helper(x, y);
7753
  if (std::isnan(result)) return isolate->heap()->nan_value();
7754
  return isolate->heap()->AllocateHeapNumber(result);
7755
}
7756

    
7757

    
7758
// Fast version of Math.pow if we know that y is not an integer and y is not
7759
// -0.5 or 0.5.  Used as slow case from full codegen.
7760
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_pow_cfunction) {
7761
  SealHandleScope shs(isolate);
7762
  ASSERT(args.length() == 2);
7763
  isolate->counters()->math_pow()->Increment();
7764

    
7765
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7766
  CONVERT_DOUBLE_ARG_CHECKED(y, 1);
7767
  if (y == 0) {
7768
    return Smi::FromInt(1);
7769
  } else {
7770
    double result = power_double_double(x, y);
7771
    if (std::isnan(result)) return isolate->heap()->nan_value();
7772
    return isolate->heap()->AllocateHeapNumber(result);
7773
  }
7774
}
7775

    
7776

    
7777
RUNTIME_FUNCTION(MaybeObject*, Runtime_RoundNumber) {
7778
  SealHandleScope shs(isolate);
7779
  ASSERT(args.length() == 1);
7780
  isolate->counters()->math_round()->Increment();
7781

    
7782
  if (!args[0]->IsHeapNumber()) {
7783
    // Must be smi. Return the argument unchanged for all the other types
7784
    // to make fuzz-natives test happy.
7785
    return args[0];
7786
  }
7787

    
7788
  HeapNumber* number = reinterpret_cast<HeapNumber*>(args[0]);
7789

    
7790
  double value = number->value();
7791
  int exponent = number->get_exponent();
7792
  int sign = number->get_sign();
7793

    
7794
  if (exponent < -1) {
7795
    // Number in range ]-0.5..0.5[. These always round to +/-zero.
7796
    if (sign) return isolate->heap()->minus_zero_value();
7797
    return Smi::FromInt(0);
7798
  }
7799

    
7800
  // We compare with kSmiValueSize - 2 because (2^30 - 0.1) has exponent 29 and
7801
  // should be rounded to 2^30, which is not smi (for 31-bit smis, similar
7802
  // argument holds for 32-bit smis).
7803
  if (!sign && exponent < kSmiValueSize - 2) {
7804
    return Smi::FromInt(static_cast<int>(value + 0.5));
7805
  }
7806

    
7807
  // If the magnitude is big enough, there's no place for fraction part. If we
7808
  // try to add 0.5 to this number, 1.0 will be added instead.
7809
  if (exponent >= 52) {
7810
    return number;
7811
  }
7812

    
7813
  if (sign && value >= -0.5) return isolate->heap()->minus_zero_value();
7814

    
7815
  // Do not call NumberFromDouble() to avoid extra checks.
7816
  return isolate->heap()->AllocateHeapNumber(floor(value + 0.5));
7817
}
7818

    
7819

    
7820
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sin) {
7821
  SealHandleScope shs(isolate);
7822
  ASSERT(args.length() == 1);
7823
  isolate->counters()->math_sin()->Increment();
7824

    
7825
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7826
  return isolate->transcendental_cache()->Get(TranscendentalCache::SIN, x);
7827
}
7828

    
7829

    
7830
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_sqrt) {
7831
  SealHandleScope shs(isolate);
7832
  ASSERT(args.length() == 1);
7833
  isolate->counters()->math_sqrt()->Increment();
7834

    
7835
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7836
  return isolate->heap()->AllocateHeapNumber(fast_sqrt(x));
7837
}
7838

    
7839

    
7840
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math_tan) {
7841
  SealHandleScope shs(isolate);
7842
  ASSERT(args.length() == 1);
7843
  isolate->counters()->math_tan()->Increment();
7844

    
7845
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
7846
  return isolate->transcendental_cache()->Get(TranscendentalCache::TAN, x);
7847
}
7848

    
7849

    
7850
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateMakeDay) {
7851
  SealHandleScope shs(isolate);
7852
  ASSERT(args.length() == 2);
7853

    
7854
  CONVERT_SMI_ARG_CHECKED(year, 0);
7855
  CONVERT_SMI_ARG_CHECKED(month, 1);
7856

    
7857
  return Smi::FromInt(isolate->date_cache()->DaysFromYearMonth(year, month));
7858
}
7859

    
7860

    
7861
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateSetValue) {
7862
  HandleScope scope(isolate);
7863
  ASSERT(args.length() == 3);
7864

    
7865
  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 0);
7866
  CONVERT_DOUBLE_ARG_CHECKED(time, 1);
7867
  CONVERT_SMI_ARG_CHECKED(is_utc, 2);
7868

    
7869
  DateCache* date_cache = isolate->date_cache();
7870

    
7871
  Object* value = NULL;
7872
  bool is_value_nan = false;
7873
  if (std::isnan(time)) {
7874
    value = isolate->heap()->nan_value();
7875
    is_value_nan = true;
7876
  } else if (!is_utc &&
7877
             (time < -DateCache::kMaxTimeBeforeUTCInMs ||
7878
              time > DateCache::kMaxTimeBeforeUTCInMs)) {
7879
    value = isolate->heap()->nan_value();
7880
    is_value_nan = true;
7881
  } else {
7882
    time = is_utc ? time : date_cache->ToUTC(static_cast<int64_t>(time));
7883
    if (time < -DateCache::kMaxTimeInMs ||
7884
        time > DateCache::kMaxTimeInMs) {
7885
      value = isolate->heap()->nan_value();
7886
      is_value_nan = true;
7887
    } else  {
7888
      MaybeObject* maybe_result =
7889
          isolate->heap()->AllocateHeapNumber(DoubleToInteger(time));
7890
      if (!maybe_result->ToObject(&value)) return maybe_result;
7891
    }
7892
  }
7893
  date->SetValue(value, is_value_nan);
7894
  return value;
7895
}
7896

    
7897

    
7898
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewArgumentsFast) {
7899
  HandleScope scope(isolate);
7900
  ASSERT(args.length() == 3);
7901

    
7902
  Handle<JSFunction> callee = args.at<JSFunction>(0);
7903
  Object** parameters = reinterpret_cast<Object**>(args[1]);
7904
  const int argument_count = Smi::cast(args[2])->value();
7905

    
7906
  Handle<JSObject> result =
7907
      isolate->factory()->NewArgumentsObject(callee, argument_count);
7908
  // Allocate the elements if needed.
7909
  int parameter_count = callee->shared()->formal_parameter_count();
7910
  if (argument_count > 0) {
7911
    if (parameter_count > 0) {
7912
      int mapped_count = Min(argument_count, parameter_count);
7913
      Handle<FixedArray> parameter_map =
7914
          isolate->factory()->NewFixedArray(mapped_count + 2, NOT_TENURED);
7915
      parameter_map->set_map(
7916
          isolate->heap()->non_strict_arguments_elements_map());
7917

    
7918
      Handle<Map> old_map(result->map());
7919
      Handle<Map> new_map = isolate->factory()->CopyMap(old_map);
7920
      new_map->set_elements_kind(NON_STRICT_ARGUMENTS_ELEMENTS);
7921

    
7922
      result->set_map(*new_map);
7923
      result->set_elements(*parameter_map);
7924

    
7925
      // Store the context and the arguments array at the beginning of the
7926
      // parameter map.
7927
      Handle<Context> context(isolate->context());
7928
      Handle<FixedArray> arguments =
7929
          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7930
      parameter_map->set(0, *context);
7931
      parameter_map->set(1, *arguments);
7932

    
7933
      // Loop over the actual parameters backwards.
7934
      int index = argument_count - 1;
7935
      while (index >= mapped_count) {
7936
        // These go directly in the arguments array and have no
7937
        // corresponding slot in the parameter map.
7938
        arguments->set(index, *(parameters - index - 1));
7939
        --index;
7940
      }
7941

    
7942
      Handle<ScopeInfo> scope_info(callee->shared()->scope_info());
7943
      while (index >= 0) {
7944
        // Detect duplicate names to the right in the parameter list.
7945
        Handle<String> name(scope_info->ParameterName(index));
7946
        int context_local_count = scope_info->ContextLocalCount();
7947
        bool duplicate = false;
7948
        for (int j = index + 1; j < parameter_count; ++j) {
7949
          if (scope_info->ParameterName(j) == *name) {
7950
            duplicate = true;
7951
            break;
7952
          }
7953
        }
7954

    
7955
        if (duplicate) {
7956
          // This goes directly in the arguments array with a hole in the
7957
          // parameter map.
7958
          arguments->set(index, *(parameters - index - 1));
7959
          parameter_map->set_the_hole(index + 2);
7960
        } else {
7961
          // The context index goes in the parameter map with a hole in the
7962
          // arguments array.
7963
          int context_index = -1;
7964
          for (int j = 0; j < context_local_count; ++j) {
7965
            if (scope_info->ContextLocalName(j) == *name) {
7966
              context_index = j;
7967
              break;
7968
            }
7969
          }
7970
          ASSERT(context_index >= 0);
7971
          arguments->set_the_hole(index);
7972
          parameter_map->set(index + 2, Smi::FromInt(
7973
              Context::MIN_CONTEXT_SLOTS + context_index));
7974
        }
7975

    
7976
        --index;
7977
      }
7978
    } else {
7979
      // If there is no aliasing, the arguments object elements are not
7980
      // special in any way.
7981
      Handle<FixedArray> elements =
7982
          isolate->factory()->NewFixedArray(argument_count, NOT_TENURED);
7983
      result->set_elements(*elements);
7984
      for (int i = 0; i < argument_count; ++i) {
7985
        elements->set(i, *(parameters - i - 1));
7986
      }
7987
    }
7988
  }
7989
  return *result;
7990
}
7991

    
7992

    
7993
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewStrictArgumentsFast) {
7994
  SealHandleScope shs(isolate);
7995
  ASSERT(args.length() == 3);
7996

    
7997
  JSFunction* callee = JSFunction::cast(args[0]);
7998
  Object** parameters = reinterpret_cast<Object**>(args[1]);
7999
  const int length = args.smi_at(2);
8000

    
8001
  Object* result;
8002
  { MaybeObject* maybe_result =
8003
        isolate->heap()->AllocateArgumentsObject(callee, length);
8004
    if (!maybe_result->ToObject(&result)) return maybe_result;
8005
  }
8006
  // Allocate the elements if needed.
8007
  if (length > 0) {
8008
    // Allocate the fixed array.
8009
    FixedArray* array;
8010
    { MaybeObject* maybe_obj =
8011
          isolate->heap()->AllocateUninitializedFixedArray(length);
8012
      if (!maybe_obj->To(&array)) return maybe_obj;
8013
    }
8014

    
8015
    DisallowHeapAllocation no_gc;
8016
    WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc);
8017
    for (int i = 0; i < length; i++) {
8018
      array->set(i, *--parameters, mode);
8019
    }
8020
    JSObject::cast(result)->set_elements(array);
8021
  }
8022
  return result;
8023
}
8024

    
8025

    
8026
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosureFromStubFailure) {
8027
  HandleScope scope(isolate);
8028
  ASSERT(args.length() == 1);
8029
  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 0);
8030
  Handle<Context> context(isolate->context());
8031
  PretenureFlag pretenure_flag = NOT_TENURED;
8032
  Handle<JSFunction> result =
8033
      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8034
                                                            context,
8035
                                                            pretenure_flag);
8036
  return *result;
8037
}
8038

    
8039

    
8040
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewClosure) {
8041
  HandleScope scope(isolate);
8042
  ASSERT(args.length() == 3);
8043
  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
8044
  CONVERT_ARG_HANDLE_CHECKED(SharedFunctionInfo, shared, 1);
8045
  CONVERT_BOOLEAN_ARG_CHECKED(pretenure, 2);
8046

    
8047
  // The caller ensures that we pretenure closures that are assigned
8048
  // directly to properties.
8049
  PretenureFlag pretenure_flag = pretenure ? TENURED : NOT_TENURED;
8050
  Handle<JSFunction> result =
8051
      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
8052
                                                            context,
8053
                                                            pretenure_flag);
8054
  return *result;
8055
}
8056

    
8057

    
8058
// Find the arguments of the JavaScript function invocation that called
8059
// into C++ code. Collect these in a newly allocated array of handles (possibly
8060
// prefixed by a number of empty handles).
8061
static SmartArrayPointer<Handle<Object> > GetCallerArguments(
8062
    Isolate* isolate,
8063
    int prefix_argc,
8064
    int* total_argc) {
8065
  // Find frame containing arguments passed to the caller.
8066
  JavaScriptFrameIterator it(isolate);
8067
  JavaScriptFrame* frame = it.frame();
8068
  List<JSFunction*> functions(2);
8069
  frame->GetFunctions(&functions);
8070
  if (functions.length() > 1) {
8071
    int inlined_jsframe_index = functions.length() - 1;
8072
    JSFunction* inlined_function = functions[inlined_jsframe_index];
8073
    Vector<SlotRef> args_slots =
8074
        SlotRef::ComputeSlotMappingForArguments(
8075
            frame,
8076
            inlined_jsframe_index,
8077
            inlined_function->shared()->formal_parameter_count());
8078

    
8079
    int args_count = args_slots.length();
8080

    
8081
    *total_argc = prefix_argc + args_count;
8082
    SmartArrayPointer<Handle<Object> > param_data(
8083
        NewArray<Handle<Object> >(*total_argc));
8084
    for (int i = 0; i < args_count; i++) {
8085
      Handle<Object> val = args_slots[i].GetValue(isolate);
8086
      param_data[prefix_argc + i] = val;
8087
    }
8088

    
8089
    args_slots.Dispose();
8090

    
8091
    return param_data;
8092
  } else {
8093
    it.AdvanceToArgumentsFrame();
8094
    frame = it.frame();
8095
    int args_count = frame->ComputeParametersCount();
8096

    
8097
    *total_argc = prefix_argc + args_count;
8098
    SmartArrayPointer<Handle<Object> > param_data(
8099
        NewArray<Handle<Object> >(*total_argc));
8100
    for (int i = 0; i < args_count; i++) {
8101
      Handle<Object> val = Handle<Object>(frame->GetParameter(i), isolate);
8102
      param_data[prefix_argc + i] = val;
8103
    }
8104
    return param_data;
8105
  }
8106
}
8107

    
8108

    
8109
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionBindArguments) {
8110
  HandleScope scope(isolate);
8111
  ASSERT(args.length() == 4);
8112
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, bound_function, 0);
8113
  RUNTIME_ASSERT(args[3]->IsNumber());
8114
  Handle<Object> bindee = args.at<Object>(1);
8115

    
8116
  // TODO(lrn): Create bound function in C++ code from premade shared info.
8117
  bound_function->shared()->set_bound(true);
8118
  // Get all arguments of calling function (Function.prototype.bind).
8119
  int argc = 0;
8120
  SmartArrayPointer<Handle<Object> > arguments =
8121
      GetCallerArguments(isolate, 0, &argc);
8122
  // Don't count the this-arg.
8123
  if (argc > 0) {
8124
    ASSERT(*arguments[0] == args[2]);
8125
    argc--;
8126
  } else {
8127
    ASSERT(args[2]->IsUndefined());
8128
  }
8129
  // Initialize array of bindings (function, this, and any existing arguments
8130
  // if the function was already bound).
8131
  Handle<FixedArray> new_bindings;
8132
  int i;
8133
  if (bindee->IsJSFunction() && JSFunction::cast(*bindee)->shared()->bound()) {
8134
    Handle<FixedArray> old_bindings(
8135
        JSFunction::cast(*bindee)->function_bindings());
8136
    new_bindings =
8137
        isolate->factory()->NewFixedArray(old_bindings->length() + argc);
8138
    bindee = Handle<Object>(old_bindings->get(JSFunction::kBoundFunctionIndex),
8139
                            isolate);
8140
    i = 0;
8141
    for (int n = old_bindings->length(); i < n; i++) {
8142
      new_bindings->set(i, old_bindings->get(i));
8143
    }
8144
  } else {
8145
    int array_size = JSFunction::kBoundArgumentsStartIndex + argc;
8146
    new_bindings = isolate->factory()->NewFixedArray(array_size);
8147
    new_bindings->set(JSFunction::kBoundFunctionIndex, *bindee);
8148
    new_bindings->set(JSFunction::kBoundThisIndex, args[2]);
8149
    i = 2;
8150
  }
8151
  // Copy arguments, skipping the first which is "this_arg".
8152
  for (int j = 0; j < argc; j++, i++) {
8153
    new_bindings->set(i, *arguments[j + 1]);
8154
  }
8155
  new_bindings->set_map_no_write_barrier(
8156
      isolate->heap()->fixed_cow_array_map());
8157
  bound_function->set_function_bindings(*new_bindings);
8158

    
8159
  // Update length.
8160
  Handle<String> length_string = isolate->factory()->length_string();
8161
  Handle<Object> new_length(args.at<Object>(3));
8162
  PropertyAttributes attr =
8163
      static_cast<PropertyAttributes>(DONT_DELETE | DONT_ENUM | READ_ONLY);
8164
  ForceSetProperty(bound_function, length_string, new_length, attr);
8165
  return *bound_function;
8166
}
8167

    
8168

    
8169
RUNTIME_FUNCTION(MaybeObject*, Runtime_BoundFunctionGetBindings) {
8170
  HandleScope handles(isolate);
8171
  ASSERT(args.length() == 1);
8172
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, callable, 0);
8173
  if (callable->IsJSFunction()) {
8174
    Handle<JSFunction> function = Handle<JSFunction>::cast(callable);
8175
    if (function->shared()->bound()) {
8176
      Handle<FixedArray> bindings(function->function_bindings());
8177
      ASSERT(bindings->map() == isolate->heap()->fixed_cow_array_map());
8178
      return *isolate->factory()->NewJSArrayWithElements(bindings);
8179
    }
8180
  }
8181
  return isolate->heap()->undefined_value();
8182
}
8183

    
8184

    
8185
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObjectFromBound) {
8186
  HandleScope scope(isolate);
8187
  ASSERT(args.length() == 1);
8188
  // First argument is a function to use as a constructor.
8189
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8190
  RUNTIME_ASSERT(function->shared()->bound());
8191

    
8192
  // The argument is a bound function. Extract its bound arguments
8193
  // and callable.
8194
  Handle<FixedArray> bound_args =
8195
      Handle<FixedArray>(FixedArray::cast(function->function_bindings()));
8196
  int bound_argc = bound_args->length() - JSFunction::kBoundArgumentsStartIndex;
8197
  Handle<Object> bound_function(
8198
      JSReceiver::cast(bound_args->get(JSFunction::kBoundFunctionIndex)),
8199
      isolate);
8200
  ASSERT(!bound_function->IsJSFunction() ||
8201
         !Handle<JSFunction>::cast(bound_function)->shared()->bound());
8202

    
8203
  int total_argc = 0;
8204
  SmartArrayPointer<Handle<Object> > param_data =
8205
      GetCallerArguments(isolate, bound_argc, &total_argc);
8206
  for (int i = 0; i < bound_argc; i++) {
8207
    param_data[i] = Handle<Object>(bound_args->get(
8208
        JSFunction::kBoundArgumentsStartIndex + i), isolate);
8209
  }
8210

    
8211
  if (!bound_function->IsJSFunction()) {
8212
    bool exception_thrown;
8213
    bound_function = Execution::TryGetConstructorDelegate(isolate,
8214
                                                          bound_function,
8215
                                                          &exception_thrown);
8216
    if (exception_thrown) return Failure::Exception();
8217
  }
8218
  ASSERT(bound_function->IsJSFunction());
8219

    
8220
  bool exception = false;
8221
  Handle<Object> result =
8222
      Execution::New(Handle<JSFunction>::cast(bound_function),
8223
                     total_argc, *param_data, &exception);
8224
  if (exception) {
8225
    return Failure::Exception();
8226
  }
8227
  ASSERT(!result.is_null());
8228
  return *result;
8229
}
8230

    
8231

    
8232
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
8233
  HandleScope scope(isolate);
8234
  ASSERT(args.length() == 1);
8235

    
8236
  Handle<Object> constructor = args.at<Object>(0);
8237

    
8238
  // If the constructor isn't a proper function we throw a type error.
8239
  if (!constructor->IsJSFunction()) {
8240
    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8241
    Handle<Object> type_error =
8242
        isolate->factory()->NewTypeError("not_constructor", arguments);
8243
    return isolate->Throw(*type_error);
8244
  }
8245

    
8246
  Handle<JSFunction> function = Handle<JSFunction>::cast(constructor);
8247

    
8248
  // If function should not have prototype, construction is not allowed. In this
8249
  // case generated code bailouts here, since function has no initial_map.
8250
  if (!function->should_have_prototype() && !function->shared()->bound()) {
8251
    Vector< Handle<Object> > arguments = HandleVector(&constructor, 1);
8252
    Handle<Object> type_error =
8253
        isolate->factory()->NewTypeError("not_constructor", arguments);
8254
    return isolate->Throw(*type_error);
8255
  }
8256

    
8257
#ifdef ENABLE_DEBUGGER_SUPPORT
8258
  Debug* debug = isolate->debug();
8259
  // Handle stepping into constructors if step into is active.
8260
  if (debug->StepInActive()) {
8261
    debug->HandleStepIn(function, Handle<Object>::null(), 0, true);
8262
  }
8263
#endif
8264

    
8265
  if (function->has_initial_map()) {
8266
    if (function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
8267
      // The 'Function' function ignores the receiver object when
8268
      // called using 'new' and creates a new JSFunction object that
8269
      // is returned.  The receiver object is only used for error
8270
      // reporting if an error occurs when constructing the new
8271
      // JSFunction. Factory::NewJSObject() should not be used to
8272
      // allocate JSFunctions since it does not properly initialize
8273
      // the shared part of the function. Since the receiver is
8274
      // ignored anyway, we use the global object as the receiver
8275
      // instead of a new JSFunction object. This way, errors are
8276
      // reported the same way whether or not 'Function' is called
8277
      // using 'new'.
8278
      return isolate->context()->global_object();
8279
    }
8280
  }
8281

    
8282
  // The function should be compiled for the optimization hints to be
8283
  // available.
8284
  JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
8285

    
8286
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
8287
  if (!function->has_initial_map() &&
8288
      shared->IsInobjectSlackTrackingInProgress()) {
8289
    // The tracking is already in progress for another function. We can only
8290
    // track one initial_map at a time, so we force the completion before the
8291
    // function is called as a constructor for the first time.
8292
    shared->CompleteInobjectSlackTracking();
8293
  }
8294

    
8295
  Handle<JSObject> result = isolate->factory()->NewJSObject(function);
8296
  RETURN_IF_EMPTY_HANDLE(isolate, result);
8297

    
8298
  isolate->counters()->constructed_objects()->Increment();
8299
  isolate->counters()->constructed_objects_runtime()->Increment();
8300

    
8301
  return *result;
8302
}
8303

    
8304

    
8305
RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
8306
  HandleScope scope(isolate);
8307
  ASSERT(args.length() == 1);
8308

    
8309
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8310
  function->shared()->CompleteInobjectSlackTracking();
8311

    
8312
  return isolate->heap()->undefined_value();
8313
}
8314

    
8315

    
8316
RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
8317
  HandleScope scope(isolate);
8318
  ASSERT(args.length() == 1);
8319

    
8320
  Handle<JSFunction> function = args.at<JSFunction>(0);
8321
#ifdef DEBUG
8322
  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
8323
    PrintF("[lazy: ");
8324
    function->PrintName();
8325
    PrintF("]\n");
8326
  }
8327
#endif
8328

    
8329
  // Compile the target function.
8330
  ASSERT(!function->is_compiled());
8331
  if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
8332
    return Failure::Exception();
8333
  }
8334

    
8335
  // All done. Return the compiled code.
8336
  ASSERT(function->is_compiled());
8337
  return function->code();
8338
}
8339

    
8340

    
8341
bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
8342
  // If the function is not compiled ignore the lazy
8343
  // recompilation. This can happen if the debugger is activated and
8344
  // the function is returned to the not compiled state.
8345
  if (!function->shared()->is_compiled()) return false;
8346

    
8347
  // If the function is not optimizable or debugger is active continue using the
8348
  // code from the full compiler.
8349
  if (!isolate->use_crankshaft() ||
8350
      function->shared()->optimization_disabled() ||
8351
      isolate->DebuggerHasBreakPoints()) {
8352
    if (FLAG_trace_opt) {
8353
      PrintF("[failed to optimize ");
8354
      function->PrintName();
8355
      PrintF(": is code optimizable: %s, is debugger enabled: %s]\n",
8356
          function->shared()->optimization_disabled() ? "F" : "T",
8357
          isolate->DebuggerHasBreakPoints() ? "T" : "F");
8358
    }
8359
    return false;
8360
  }
8361
  return true;
8362
}
8363

    
8364

    
8365
RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
8366
  HandleScope scope(isolate);
8367
  ASSERT(args.length() == 1);
8368
  Handle<JSFunction> function = args.at<JSFunction>(0);
8369

    
8370
  if (!AllowOptimization(isolate, function)) {
8371
    function->ReplaceCode(function->shared()->code());
8372
    return function->code();
8373
  }
8374
  function->shared()->code()->set_profiler_ticks(0);
8375
  if (JSFunction::CompileOptimized(function, CLEAR_EXCEPTION)) {
8376
    return function->code();
8377
  }
8378
  if (FLAG_trace_opt) {
8379
    PrintF("[failed to optimize ");
8380
    function->PrintName();
8381
    PrintF(": optimized compilation failed]\n");
8382
  }
8383
  function->ReplaceCode(function->shared()->code());
8384
  return function->code();
8385
}
8386

    
8387

    
8388
RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) {
8389
  HandleScope handle_scope(isolate);
8390
  ASSERT(args.length() == 1);
8391
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8392
  if (!AllowOptimization(isolate, function)) {
8393
    function->ReplaceCode(function->shared()->code());
8394
    return isolate->heap()->undefined_value();
8395
  }
8396
  function->shared()->code()->set_profiler_ticks(0);
8397
  ASSERT(FLAG_concurrent_recompilation);
8398
  if (!Compiler::RecompileConcurrent(function)) {
8399
    function->ReplaceCode(function->shared()->code());
8400
  }
8401
  return isolate->heap()->undefined_value();
8402
}
8403

    
8404

    
8405
class ActivationsFinder : public ThreadVisitor {
8406
 public:
8407
  Code* code_;
8408
  bool has_code_activations_;
8409

    
8410
  explicit ActivationsFinder(Code* code)
8411
    : code_(code),
8412
      has_code_activations_(false) { }
8413

    
8414
  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
8415
    JavaScriptFrameIterator it(isolate, top);
8416
    VisitFrames(&it);
8417
  }
8418

    
8419
  void VisitFrames(JavaScriptFrameIterator* it) {
8420
    for (; !it->done(); it->Advance()) {
8421
      JavaScriptFrame* frame = it->frame();
8422
      if (code_->contains(frame->pc())) has_code_activations_ = true;
8423
    }
8424
  }
8425
};
8426

    
8427

    
8428
RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyStubFailure) {
8429
  HandleScope scope(isolate);
8430
  ASSERT(args.length() == 0);
8431
  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8432
  ASSERT(AllowHeapAllocation::IsAllowed());
8433
  delete deoptimizer;
8434
  return isolate->heap()->undefined_value();
8435
}
8436

    
8437

    
8438
RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyDeoptimized) {
8439
  HandleScope scope(isolate);
8440
  ASSERT(args.length() == 1);
8441
  RUNTIME_ASSERT(args[0]->IsSmi());
8442
  Deoptimizer::BailoutType type =
8443
      static_cast<Deoptimizer::BailoutType>(args.smi_at(0));
8444
  Deoptimizer* deoptimizer = Deoptimizer::Grab(isolate);
8445
  ASSERT(AllowHeapAllocation::IsAllowed());
8446

    
8447
  Handle<JSFunction> function = deoptimizer->function();
8448
  Handle<Code> optimized_code = deoptimizer->compiled_code();
8449

    
8450
  ASSERT(optimized_code->kind() == Code::OPTIMIZED_FUNCTION);
8451
  ASSERT(type == deoptimizer->bailout_type());
8452

    
8453
  // Make sure to materialize objects before causing any allocation.
8454
  JavaScriptFrameIterator it(isolate);
8455
  deoptimizer->MaterializeHeapObjects(&it);
8456
  delete deoptimizer;
8457

    
8458
  JavaScriptFrame* frame = it.frame();
8459
  RUNTIME_ASSERT(frame->function()->IsJSFunction());
8460
  ASSERT(frame->function() == *function);
8461

    
8462
  // Avoid doing too much work when running with --always-opt and keep
8463
  // the optimized code around.
8464
  if (FLAG_always_opt || type == Deoptimizer::LAZY) {
8465
    return isolate->heap()->undefined_value();
8466
  }
8467

    
8468
  // Search for other activations of the same function and code.
8469
  ActivationsFinder activations_finder(*optimized_code);
8470
  activations_finder.VisitFrames(&it);
8471
  isolate->thread_manager()->IterateArchivedThreads(&activations_finder);
8472

    
8473
  if (!activations_finder.has_code_activations_) {
8474
    if (function->code() == *optimized_code) {
8475
      if (FLAG_trace_deopt) {
8476
        PrintF("[removing optimized code for: ");
8477
        function->PrintName();
8478
        PrintF("]\n");
8479
      }
8480
      function->ReplaceCode(function->shared()->code());
8481
    }
8482
  } else {
8483
    // TODO(titzer): we should probably do DeoptimizeCodeList(code)
8484
    // unconditionally if the code is not already marked for deoptimization.
8485
    // If there is an index by shared function info, all the better.
8486
    Deoptimizer::DeoptimizeFunction(*function);
8487
  }
8488
  // Evict optimized code for this function from the cache so that it doesn't
8489
  // get used for new closures.
8490
  function->shared()->EvictFromOptimizedCodeMap(*optimized_code,
8491
                                                "notify deoptimized");
8492

    
8493
  return isolate->heap()->undefined_value();
8494
}
8495

    
8496

    
8497
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeoptimizeFunction) {
8498
  HandleScope scope(isolate);
8499
  ASSERT(args.length() == 1);
8500
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8501
  if (!function->IsOptimized()) return isolate->heap()->undefined_value();
8502

    
8503
  Deoptimizer::DeoptimizeFunction(*function);
8504

    
8505
  return isolate->heap()->undefined_value();
8506
}
8507

    
8508

    
8509
RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearFunctionTypeFeedback) {
8510
  HandleScope scope(isolate);
8511
  ASSERT(args.length() == 1);
8512
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8513
  Code* unoptimized = function->shared()->code();
8514
  if (unoptimized->kind() == Code::FUNCTION) {
8515
    unoptimized->ClearInlineCaches();
8516
    unoptimized->ClearTypeFeedbackCells(isolate->heap());
8517
  }
8518
  return isolate->heap()->undefined_value();
8519
}
8520

    
8521

    
8522
RUNTIME_FUNCTION(MaybeObject*, Runtime_RunningInSimulator) {
8523
  SealHandleScope shs(isolate);
8524
#if defined(USE_SIMULATOR)
8525
  return isolate->heap()->true_value();
8526
#else
8527
  return isolate->heap()->false_value();
8528
#endif
8529
}
8530

    
8531

    
8532
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsConcurrentRecompilationSupported) {
8533
  HandleScope scope(isolate);
8534
  return FLAG_concurrent_recompilation
8535
      ? isolate->heap()->true_value() : isolate->heap()->false_value();
8536
}
8537

    
8538

    
8539
RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
8540
  HandleScope scope(isolate);
8541
  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8542
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8543

    
8544
  if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
8545
  function->MarkForLazyRecompilation();
8546

    
8547
  Code* unoptimized = function->shared()->code();
8548
  if (args.length() == 2 &&
8549
      unoptimized->kind() == Code::FUNCTION) {
8550
    CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
8551
    if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr"))) {
8552
      // Start patching from the currently patched loop nesting level.
8553
      int current_level = unoptimized->allow_osr_at_loop_nesting_level();
8554
      ASSERT(BackEdgeTable::Verify(isolate, unoptimized, current_level));
8555
      for (int i = current_level + 1; i <= Code::kMaxLoopNestingMarker; i++) {
8556
        unoptimized->set_allow_osr_at_loop_nesting_level(i);
8557
        isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
8558
      }
8559
    } else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent"))) {
8560
      function->MarkForConcurrentRecompilation();
8561
    }
8562
  }
8563

    
8564
  return isolate->heap()->undefined_value();
8565
}
8566

    
8567

    
8568
RUNTIME_FUNCTION(MaybeObject*, Runtime_NeverOptimizeFunction) {
8569
  HandleScope scope(isolate);
8570
  ASSERT(args.length() == 1);
8571
  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8572
  ASSERT(!function->IsOptimized());
8573
  function->shared()->set_optimization_disabled(true);
8574
  return isolate->heap()->undefined_value();
8575
}
8576

    
8577

    
8578
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
8579
  HandleScope scope(isolate);
8580
  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
8581
  if (!isolate->use_crankshaft()) {
8582
    return Smi::FromInt(4);  // 4 == "never".
8583
  }
8584
  bool sync_with_compiler_thread = true;
8585
  if (args.length() == 2) {
8586
    CONVERT_ARG_HANDLE_CHECKED(String, sync, 1);
8587
    if (sync->IsOneByteEqualTo(STATIC_ASCII_VECTOR("no sync"))) {
8588
      sync_with_compiler_thread = false;
8589
    }
8590
  }
8591
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8592
  if (FLAG_concurrent_recompilation && sync_with_compiler_thread) {
8593
    while (function->IsInRecompileQueue()) {
8594
      isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
8595
      OS::Sleep(50);
8596
    }
8597
  }
8598
  if (FLAG_always_opt) {
8599
    // We may have always opt, but that is more best-effort than a real
8600
    // promise, so we still say "no" if it is not optimized.
8601
    return function->IsOptimized() ? Smi::FromInt(3)   // 3 == "always".
8602
                                   : Smi::FromInt(2);  // 2 == "no".
8603
  }
8604
  if (FLAG_deopt_every_n_times) {
8605
    return Smi::FromInt(6);  // 6 == "maybe deopted".
8606
  }
8607
  return function->IsOptimized() ? Smi::FromInt(1)   // 1 == "yes".
8608
                                 : Smi::FromInt(2);  // 2 == "no".
8609
}
8610

    
8611

    
8612
RUNTIME_FUNCTION(MaybeObject*, Runtime_UnblockConcurrentRecompilation) {
8613
  RUNTIME_ASSERT(FLAG_block_concurrent_recompilation);
8614
  isolate->optimizing_compiler_thread()->Unblock();
8615
  return isolate->heap()->undefined_value();
8616
}
8617

    
8618

    
8619
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
8620
  HandleScope scope(isolate);
8621
  ASSERT(args.length() == 1);
8622
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8623
  return Smi::FromInt(function->shared()->opt_count());
8624
}
8625

    
8626

    
8627
static bool IsSuitableForOnStackReplacement(Isolate* isolate,
8628
                                            Handle<JSFunction> function,
8629
                                            Handle<Code> unoptimized) {
8630
  // Keep track of whether we've succeeded in optimizing.
8631
  if (!isolate->use_crankshaft() || !unoptimized->optimizable()) return false;
8632
  // If we are trying to do OSR when there are already optimized
8633
  // activations of the function, it means (a) the function is directly or
8634
  // indirectly recursive and (b) an optimized invocation has been
8635
  // deoptimized so that we are currently in an unoptimized activation.
8636
  // Check for optimized activations of this function.
8637
  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
8638
    JavaScriptFrame* frame = it.frame();
8639
    if (frame->is_optimized() && frame->function() == *function) return false;
8640
  }
8641

    
8642
  return true;
8643
}
8644

    
8645

    
8646
RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
8647
  HandleScope scope(isolate);
8648
  ASSERT(args.length() == 2);
8649
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
8650
  CONVERT_NUMBER_CHECKED(uint32_t, pc_offset, Uint32, args[1]);
8651
  Handle<Code> unoptimized(function->shared()->code(), isolate);
8652

    
8653
#ifdef DEBUG
8654
  JavaScriptFrameIterator it(isolate);
8655
  JavaScriptFrame* frame = it.frame();
8656
  ASSERT_EQ(frame->function(), *function);
8657
  ASSERT_EQ(frame->LookupCode(), *unoptimized);
8658
  ASSERT(unoptimized->contains(frame->pc()));
8659

    
8660
  ASSERT(pc_offset ==
8661
         static_cast<uint32_t>(frame->pc() - unoptimized->instruction_start()));
8662
#endif  // DEBUG
8663

    
8664
  // We're not prepared to handle a function with arguments object.
8665
  ASSERT(!function->shared()->uses_arguments());
8666

    
8667
  Handle<Code> result = Handle<Code>::null();
8668
  BailoutId ast_id = BailoutId::None();
8669

    
8670
  if (FLAG_concurrent_osr) {
8671
    if (isolate->optimizing_compiler_thread()->
8672
            IsQueuedForOSR(function, pc_offset)) {
8673
      // Still waiting for the optimizing compiler thread to finish.  Carry on.
8674
      if (FLAG_trace_osr) {
8675
        PrintF("[COSR - polling recompile tasks for ");
8676
        function->PrintName();
8677
        PrintF("]\n");
8678
      }
8679
      return NULL;
8680
    }
8681

    
8682
    RecompileJob* job = isolate->optimizing_compiler_thread()->
8683
        FindReadyOSRCandidate(function, pc_offset);
8684

    
8685
    if (job == NULL) {
8686
      if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) &&
8687
          Compiler::RecompileConcurrent(function, pc_offset)) {
8688
        if (function->IsMarkedForLazyRecompilation() ||
8689
            function->IsMarkedForConcurrentRecompilation()) {
8690
          // Prevent regular recompilation if we queue this for OSR.
8691
          // TODO(yangguo): remove this as soon as OSR becomes one-shot.
8692
          function->ReplaceCode(*unoptimized);
8693
        }
8694
        return NULL;
8695
      }
8696
      // Fall through to the end in case of failure.
8697
    } else {
8698
      // TODO(titzer): don't install the OSR code into the function.
8699
      ast_id = job->info()->osr_ast_id();
8700
      result = Compiler::InstallOptimizedCode(job);
8701
    }
8702
  } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
8703
    ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset);
8704
    ASSERT(!ast_id.IsNone());
8705
    if (FLAG_trace_osr) {
8706
      PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt());
8707
      function->PrintName();
8708
      PrintF("]\n");
8709
    }
8710
    // Attempt OSR compilation.
8711
    result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION);
8712
  }
8713

    
8714
  // Revert the patched back edge table, regardless of whether OSR succeeds.
8715
  BackEdgeTable::Revert(isolate, *unoptimized);
8716

    
8717
  // Check whether we ended up with usable optimized code.
8718
  if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
8719
    DeoptimizationInputData* data =
8720
        DeoptimizationInputData::cast(result->deoptimization_data());
8721

    
8722
    if (data->OsrPcOffset()->value() >= 0) {
8723
      ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
8724
      if (FLAG_trace_osr) {
8725
        PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n",
8726
               ast_id.ToInt(), data->OsrPcOffset()->value());
8727
      }
8728
      // TODO(titzer): this is a massive hack to make the deopt counts
8729
      // match. Fix heuristics for reenabling optimizations!
8730
      function->shared()->increment_deopt_count();
8731
      return *result;
8732
    }
8733
  }
8734

    
8735
  if (FLAG_trace_osr) {
8736
    PrintF("[OSR - optimization failed for ");
8737
    function->PrintName();
8738
    PrintF("]\n");
8739
  }
8740

    
8741
  if (function->IsMarkedForLazyRecompilation() ||
8742
      function->IsMarkedForConcurrentRecompilation()) {
8743
    function->ReplaceCode(function->shared()->code());
8744
  }
8745
  return NULL;
8746
}
8747

    
8748

    
8749
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAllocationTimeout) {
8750
  SealHandleScope shs(isolate);
8751
  ASSERT(args.length() == 2);
8752
#ifdef DEBUG
8753
  CONVERT_SMI_ARG_CHECKED(interval, 0);
8754
  CONVERT_SMI_ARG_CHECKED(timeout, 1);
8755
  isolate->heap()->set_allocation_timeout(timeout);
8756
  FLAG_gc_interval = interval;
8757
#endif
8758
  return isolate->heap()->undefined_value();
8759
}
8760

    
8761

    
8762
RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckIsBootstrapping) {
8763
  SealHandleScope shs(isolate);
8764
  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8765
  return isolate->heap()->undefined_value();
8766
}
8767

    
8768

    
8769
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetRootNaN) {
8770
  SealHandleScope shs(isolate);
8771
  RUNTIME_ASSERT(isolate->bootstrapper()->IsActive());
8772
  return isolate->heap()->nan_value();
8773
}
8774

    
8775

    
8776
RUNTIME_FUNCTION(MaybeObject*, Runtime_Call) {
8777
  HandleScope scope(isolate);
8778
  ASSERT(args.length() >= 2);
8779
  int argc = args.length() - 2;
8780
  CONVERT_ARG_CHECKED(JSReceiver, fun, argc + 1);
8781
  Object* receiver = args[0];
8782

    
8783
  // If there are too many arguments, allocate argv via malloc.
8784
  const int argv_small_size = 10;
8785
  Handle<Object> argv_small_buffer[argv_small_size];
8786
  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8787
  Handle<Object>* argv = argv_small_buffer;
8788
  if (argc > argv_small_size) {
8789
    argv = new Handle<Object>[argc];
8790
    if (argv == NULL) return isolate->StackOverflow();
8791
    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8792
  }
8793

    
8794
  for (int i = 0; i < argc; ++i) {
8795
     MaybeObject* maybe = args[1 + i];
8796
     Object* object;
8797
     if (!maybe->To<Object>(&object)) return maybe;
8798
     argv[i] = Handle<Object>(object, isolate);
8799
  }
8800

    
8801
  bool threw;
8802
  Handle<JSReceiver> hfun(fun);
8803
  Handle<Object> hreceiver(receiver, isolate);
8804
  Handle<Object> result = Execution::Call(
8805
      isolate, hfun, hreceiver, argc, argv, &threw, true);
8806

    
8807
  if (threw) return Failure::Exception();
8808
  return *result;
8809
}
8810

    
8811

    
8812
RUNTIME_FUNCTION(MaybeObject*, Runtime_Apply) {
8813
  HandleScope scope(isolate);
8814
  ASSERT(args.length() == 5);
8815
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, fun, 0);
8816
  Handle<Object> receiver = args.at<Object>(1);
8817
  CONVERT_ARG_HANDLE_CHECKED(JSObject, arguments, 2);
8818
  CONVERT_SMI_ARG_CHECKED(offset, 3);
8819
  CONVERT_SMI_ARG_CHECKED(argc, 4);
8820
  RUNTIME_ASSERT(offset >= 0);
8821
  RUNTIME_ASSERT(argc >= 0);
8822

    
8823
  // If there are too many arguments, allocate argv via malloc.
8824
  const int argv_small_size = 10;
8825
  Handle<Object> argv_small_buffer[argv_small_size];
8826
  SmartArrayPointer<Handle<Object> > argv_large_buffer;
8827
  Handle<Object>* argv = argv_small_buffer;
8828
  if (argc > argv_small_size) {
8829
    argv = new Handle<Object>[argc];
8830
    if (argv == NULL) return isolate->StackOverflow();
8831
    argv_large_buffer = SmartArrayPointer<Handle<Object> >(argv);
8832
  }
8833

    
8834
  for (int i = 0; i < argc; ++i) {
8835
    argv[i] = Object::GetElement(isolate, arguments, offset + i);
8836
  }
8837

    
8838
  bool threw;
8839
  Handle<Object> result = Execution::Call(
8840
      isolate, fun, receiver, argc, argv, &threw, true);
8841

    
8842
  if (threw) return Failure::Exception();
8843
  return *result;
8844
}
8845

    
8846

    
8847
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionDelegate) {
8848
  HandleScope scope(isolate);
8849
  ASSERT(args.length() == 1);
8850
  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8851
  return *Execution::GetFunctionDelegate(isolate, args.at<Object>(0));
8852
}
8853

    
8854

    
8855
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructorDelegate) {
8856
  HandleScope scope(isolate);
8857
  ASSERT(args.length() == 1);
8858
  RUNTIME_ASSERT(!args[0]->IsJSFunction());
8859
  return *Execution::GetConstructorDelegate(isolate, args.at<Object>(0));
8860
}
8861

    
8862

    
8863
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewGlobalContext) {
8864
  SealHandleScope shs(isolate);
8865
  ASSERT(args.length() == 2);
8866

    
8867
  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8868
  CONVERT_ARG_CHECKED(ScopeInfo, scope_info, 1);
8869
  Context* result;
8870
  MaybeObject* maybe_result =
8871
      isolate->heap()->AllocateGlobalContext(function, scope_info);
8872
  if (!maybe_result->To(&result)) return maybe_result;
8873

    
8874
  ASSERT(function->context() == isolate->context());
8875
  ASSERT(function->context()->global_object() == result->global_object());
8876
  isolate->set_context(result);
8877
  result->global_object()->set_global_context(result);
8878

    
8879
  return result;  // non-failure
8880
}
8881

    
8882

    
8883
RUNTIME_FUNCTION(MaybeObject*, Runtime_NewFunctionContext) {
8884
  SealHandleScope shs(isolate);
8885
  ASSERT(args.length() == 1);
8886

    
8887
  CONVERT_ARG_CHECKED(JSFunction, function, 0);
8888
  int length = function->shared()->scope_info()->ContextLength();
8889
  Context* result;
8890
  MaybeObject* maybe_result =
8891
      isolate->heap()->AllocateFunctionContext(length, function);
8892
  if (!maybe_result->To(&result)) return maybe_result;
8893

    
8894
  isolate->set_context(result);
8895

    
8896
  return result;  // non-failure
8897
}
8898

    
8899

    
8900
RUNTIME_FUNCTION(MaybeObject*, Runtime_PushWithContext) {
8901
  SealHandleScope shs(isolate);
8902
  ASSERT(args.length() == 2);
8903
  JSReceiver* extension_object;
8904
  if (args[0]->IsJSReceiver()) {
8905
    extension_object = JSReceiver::cast(args[0]);
8906
  } else {
8907
    // Convert the object to a proper JavaScript object.
8908
    MaybeObject* maybe_js_object = args[0]->ToObject(isolate);
8909
    if (!maybe_js_object->To(&extension_object)) {
8910
      if (Failure::cast(maybe_js_object)->IsInternalError()) {
8911
        HandleScope scope(isolate);
8912
        Handle<Object> handle = args.at<Object>(0);
8913
        Handle<Object> result =
8914
            isolate->factory()->NewTypeError("with_expression",
8915
                                             HandleVector(&handle, 1));
8916
        return isolate->Throw(*result);
8917
      } else {
8918
        return maybe_js_object;
8919
      }
8920
    }
8921
  }
8922

    
8923
  JSFunction* function;
8924
  if (args[1]->IsSmi()) {
8925
    // A smi sentinel indicates a context nested inside global code rather
8926
    // than some function.  There is a canonical empty function that can be
8927
    // gotten from the native context.
8928
    function = isolate->context()->native_context()->closure();
8929
  } else {
8930
    function = JSFunction::cast(args[1]);
8931
  }
8932

    
8933
  Context* context;
8934
  MaybeObject* maybe_context =
8935
      isolate->heap()->AllocateWithContext(function,
8936
                                           isolate->context(),
8937
                                           extension_object);
8938
  if (!maybe_context->To(&context)) return maybe_context;
8939
  isolate->set_context(context);
8940
  return context;
8941
}
8942

    
8943

    
8944
RUNTIME_FUNCTION(MaybeObject*, Runtime_PushCatchContext) {
8945
  SealHandleScope shs(isolate);
8946
  ASSERT(args.length() == 3);
8947
  String* name = String::cast(args[0]);
8948
  Object* thrown_object = args[1];
8949
  JSFunction* function;
8950
  if (args[2]->IsSmi()) {
8951
    // A smi sentinel indicates a context nested inside global code rather
8952
    // than some function.  There is a canonical empty function that can be
8953
    // gotten from the native context.
8954
    function = isolate->context()->native_context()->closure();
8955
  } else {
8956
    function = JSFunction::cast(args[2]);
8957
  }
8958
  Context* context;
8959
  MaybeObject* maybe_context =
8960
      isolate->heap()->AllocateCatchContext(function,
8961
                                            isolate->context(),
8962
                                            name,
8963
                                            thrown_object);
8964
  if (!maybe_context->To(&context)) return maybe_context;
8965
  isolate->set_context(context);
8966
  return context;
8967
}
8968

    
8969

    
8970
RUNTIME_FUNCTION(MaybeObject*, Runtime_PushBlockContext) {
8971
  SealHandleScope shs(isolate);
8972
  ASSERT(args.length() == 2);
8973
  ScopeInfo* scope_info = ScopeInfo::cast(args[0]);
8974
  JSFunction* function;
8975
  if (args[1]->IsSmi()) {
8976
    // A smi sentinel indicates a context nested inside global code rather
8977
    // than some function.  There is a canonical empty function that can be
8978
    // gotten from the native context.
8979
    function = isolate->context()->native_context()->closure();
8980
  } else {
8981
    function = JSFunction::cast(args[1]);
8982
  }
8983
  Context* context;
8984
  MaybeObject* maybe_context =
8985
      isolate->heap()->AllocateBlockContext(function,
8986
                                            isolate->context(),
8987
                                            scope_info);
8988
  if (!maybe_context->To(&context)) return maybe_context;
8989
  isolate->set_context(context);
8990
  return context;
8991
}
8992

    
8993

    
8994
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSModule) {
8995
  SealHandleScope shs(isolate);
8996
  ASSERT(args.length() == 1);
8997
  Object* obj = args[0];
8998
  return isolate->heap()->ToBoolean(obj->IsJSModule());
8999
}
9000

    
9001

    
9002
RUNTIME_FUNCTION(MaybeObject*, Runtime_PushModuleContext) {
9003
  SealHandleScope shs(isolate);
9004
  ASSERT(args.length() == 2);
9005
  CONVERT_SMI_ARG_CHECKED(index, 0);
9006

    
9007
  if (!args[1]->IsScopeInfo()) {
9008
    // Module already initialized. Find hosting context and retrieve context.
9009
    Context* host = Context::cast(isolate->context())->global_context();
9010
    Context* context = Context::cast(host->get(index));
9011
    ASSERT(context->previous() == isolate->context());
9012
    isolate->set_context(context);
9013
    return context;
9014
  }
9015

    
9016
  CONVERT_ARG_HANDLE_CHECKED(ScopeInfo, scope_info, 1);
9017

    
9018
  // Allocate module context.
9019
  HandleScope scope(isolate);
9020
  Factory* factory = isolate->factory();
9021
  Handle<Context> context = factory->NewModuleContext(scope_info);
9022
  Handle<JSModule> module = factory->NewJSModule(context, scope_info);
9023
  context->set_module(*module);
9024
  Context* previous = isolate->context();
9025
  context->set_previous(previous);
9026
  context->set_closure(previous->closure());
9027
  context->set_global_object(previous->global_object());
9028
  isolate->set_context(*context);
9029

    
9030
  // Find hosting scope and initialize internal variable holding module there.
9031
  previous->global_context()->set(index, *context);
9032

    
9033
  return *context;
9034
}
9035

    
9036

    
9037
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareModules) {
9038
  HandleScope scope(isolate);
9039
  ASSERT(args.length() == 1);
9040
  CONVERT_ARG_HANDLE_CHECKED(FixedArray, descriptions, 0);
9041
  Context* host_context = isolate->context();
9042

    
9043
  for (int i = 0; i < descriptions->length(); ++i) {
9044
    Handle<ModuleInfo> description(ModuleInfo::cast(descriptions->get(i)));
9045
    int host_index = description->host_index();
9046
    Handle<Context> context(Context::cast(host_context->get(host_index)));
9047
    Handle<JSModule> module(context->module());
9048

    
9049
    for (int j = 0; j < description->length(); ++j) {
9050
      Handle<String> name(description->name(j));
9051
      VariableMode mode = description->mode(j);
9052
      int index = description->index(j);
9053
      switch (mode) {
9054
        case VAR:
9055
        case LET:
9056
        case CONST:
9057
        case CONST_HARMONY: {
9058
          PropertyAttributes attr =
9059
              IsImmutableVariableMode(mode) ? FROZEN : SEALED;
9060
          Handle<AccessorInfo> info =
9061
              Accessors::MakeModuleExport(name, index, attr);
9062
          Handle<Object> result = JSObject::SetAccessor(module, info);
9063
          ASSERT(!(result.is_null() || result->IsUndefined()));
9064
          USE(result);
9065
          break;
9066
        }
9067
        case MODULE: {
9068
          Object* referenced_context = Context::cast(host_context)->get(index);
9069
          Handle<JSModule> value(Context::cast(referenced_context)->module());
9070
          JSReceiver::SetProperty(module, name, value, FROZEN, kStrictMode);
9071
          break;
9072
        }
9073
        case INTERNAL:
9074
        case TEMPORARY:
9075
        case DYNAMIC:
9076
        case DYNAMIC_GLOBAL:
9077
        case DYNAMIC_LOCAL:
9078
          UNREACHABLE();
9079
      }
9080
    }
9081

    
9082
    JSObject::PreventExtensions(module);
9083
  }
9084

    
9085
  ASSERT(!isolate->has_pending_exception());
9086
  return isolate->heap()->undefined_value();
9087
}
9088

    
9089

    
9090
RUNTIME_FUNCTION(MaybeObject*, Runtime_DeleteContextSlot) {
9091
  HandleScope scope(isolate);
9092
  ASSERT(args.length() == 2);
9093

    
9094
  CONVERT_ARG_HANDLE_CHECKED(Context, context, 0);
9095
  CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
9096

    
9097
  int index;
9098
  PropertyAttributes attributes;
9099
  ContextLookupFlags flags = FOLLOW_CHAINS;
9100
  BindingFlags binding_flags;
9101
  Handle<Object> holder = context->Lookup(name,
9102
                                          flags,
9103
                                          &index,
9104
                                          &attributes,
9105
                                          &binding_flags);
9106

    
9107
  // If the slot was not found the result is true.
9108
  if (holder.is_null()) {
9109
    return isolate->heap()->true_value();
9110
  }
9111

    
9112
  // If the slot was found in a context, it should be DONT_DELETE.
9113
  if (holder->IsContext()) {
9114
    return isolate->heap()->false_value();
9115
  }
9116

    
9117
  // The slot was found in a JSObject, either a context extension object,
9118
  // the global object, or the subject of a with.  Try to delete it
9119
  // (respecting DONT_DELETE).
9120
  Handle<JSObject> object = Handle<JSObject>::cast(holder);
9121
  Handle<Object> result = JSReceiver::DeleteProperty(object, name);
9122
  RETURN_IF_EMPTY_HANDLE(isolate, result);
9123
  return *result;
9124
}
9125

    
9126

    
9127
// A mechanism to return a pair of Object pointers in registers (if possible).
9128
// How this is achieved is calling convention-dependent.
9129
// All currently supported x86 compiles uses calling conventions that are cdecl
9130
// variants where a 64-bit value is returned in two 32-bit registers
9131
// (edx:eax on ia32, r1:r0 on ARM).
9132
// In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
9133
// In Win64 calling convention, a struct of two pointers is returned in memory,
9134
// allocated by the caller, and passed as a pointer in a hidden first parameter.
9135
#ifdef V8_HOST_ARCH_64_BIT
9136
struct ObjectPair {
9137
  MaybeObject* x;
9138
  MaybeObject* y;
9139
};
9140

    
9141

    
9142
static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9143
  ObjectPair result = {x, y};
9144
  // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
9145
  // In Win64 they are assigned to a hidden first argument.
9146
  return result;
9147
}
9148
#else
9149
typedef uint64_t ObjectPair;
9150
static inline ObjectPair MakePair(MaybeObject* x, MaybeObject* y) {
9151
  return reinterpret_cast<uint32_t>(x) |
9152
      (reinterpret_cast<ObjectPair>(y) << 32);
9153
}
9154
#endif
9155

    
9156

    
9157
static inline MaybeObject* Unhole(Heap* heap,
9158
                                  MaybeObject* x,
9159
                                  PropertyAttributes attributes) {
9160
  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
9161
  USE(attributes);
9162
  return x->IsTheHole() ? heap->undefined_value() : x;
9163
}
9164

    
9165

    
9166
static Object* ComputeReceiverForNonGlobal(Isolate* isolate,
9167
                                           JSObject* holder) {
9168
  ASSERT(!holder->IsGlobalObject());
9169
  Context* top = isolate->context();
9170
  // Get the context extension function.
9171
  JSFunction* context_extension_function =
9172
      top->native_context()->context_extension_function();
9173
  // If the holder isn't a context extension object, we just return it
9174
  // as the receiver. This allows arguments objects to be used as
9175
  // receivers, but only if they are put in the context scope chain
9176
  // explicitly via a with-statement.
9177
  Object* constructor = holder->map()->constructor();
9178
  if (constructor != context_extension_function) return holder;
9179
  // Fall back to using the global object as the implicit receiver if
9180
  // the property turns out to be a local variable allocated in a
9181
  // context extension object - introduced via eval. Implicit global
9182
  // receivers are indicated with the hole value.
9183
  return isolate->heap()->the_hole_value();
9184
}
9185

    
9186

    
9187
static ObjectPair LoadContextSlotHelper(Arguments args,
9188
                                        Isolate* isolate,
9189
                                        bool throw_error) {
9190
  HandleScope scope(isolate);
9191
  ASSERT_EQ(2, args.length());
9192

    
9193
  if (!args[0]->IsContext() || !args[1]->IsString()) {
9194
    return MakePair(isolate->ThrowIllegalOperation(), NULL);
9195
  }
9196
  Handle<Context> context = args.at<Context>(0);
9197
  Handle<String> name = args.at<String>(1);
9198

    
9199
  int index;
9200
  PropertyAttributes attributes;
9201
  ContextLookupFlags flags = FOLLOW_CHAINS;
9202
  BindingFlags binding_flags;
9203
  Handle<Object> holder = context->Lookup(name,
9204
                                          flags,
9205
                                          &index,
9206
                                          &attributes,
9207
                                          &binding_flags);
9208
  if (isolate->has_pending_exception()) {
9209
    return MakePair(Failure::Exception(), NULL);
9210
  }
9211

    
9212
  // If the index is non-negative, the slot has been found in a context.
9213
  if (index >= 0) {
9214
    ASSERT(holder->IsContext());
9215
    // If the "property" we were looking for is a local variable, the
9216
    // receiver is the global object; see ECMA-262, 3rd., 10.1.6 and 10.2.3.
9217
    //
9218
    // Use the hole as the receiver to signal that the receiver is implicit
9219
    // and that the global receiver should be used (as distinguished from an
9220
    // explicit receiver that happens to be a global object).
9221
    Handle<Object> receiver = isolate->factory()->the_hole_value();
9222
    Object* value = Context::cast(*holder)->get(index);
9223
    // Check for uninitialized bindings.
9224
    switch (binding_flags) {
9225
      case MUTABLE_CHECK_INITIALIZED:
9226
      case IMMUTABLE_CHECK_INITIALIZED_HARMONY:
9227
        if (value->IsTheHole()) {
9228
          Handle<Object> reference_error =
9229
              isolate->factory()->NewReferenceError("not_defined",
9230
                                                    HandleVector(&name, 1));
9231
          return MakePair(isolate->Throw(*reference_error), NULL);
9232
        }
9233
        // FALLTHROUGH
9234
      case MUTABLE_IS_INITIALIZED:
9235
      case IMMUTABLE_IS_INITIALIZED:
9236
      case IMMUTABLE_IS_INITIALIZED_HARMONY:
9237
        ASSERT(!value->IsTheHole());
9238
        return MakePair(value, *receiver);
9239
      case IMMUTABLE_CHECK_INITIALIZED:
9240
        return MakePair(Unhole(isolate->heap(), value, attributes), *receiver);
9241
      case MISSING_BINDING:
9242
        UNREACHABLE();
9243
        return MakePair(NULL, NULL);
9244
    }
9245
  }
9246

    
9247
  // Otherwise, if the slot was found the holder is a context extension
9248
  // object, subject of a with, or a global object.  We read the named
9249
  // property from it.
9250
  if (!holder.is_null()) {
9251
    Handle<JSReceiver> object = Handle<JSReceiver>::cast(holder);
9252
    ASSERT(object->IsJSProxy() || JSReceiver::HasProperty(object, name));
9253
    // GetProperty below can cause GC.
9254
    Handle<Object> receiver_handle(
9255
        object->IsGlobalObject()
9256
            ? GlobalObject::cast(*object)->global_receiver()
9257
            : object->IsJSProxy() ? static_cast<Object*>(*object)
9258
                : ComputeReceiverForNonGlobal(isolate, JSObject::cast(*object)),
9259
        isolate);
9260

    
9261
    // No need to unhole the value here.  This is taken care of by the
9262
    // GetProperty function.
9263
    MaybeObject* value = object->GetProperty(*name);
9264
    return MakePair(value, *receiver_handle);
9265
  }
9266

    
9267
  if (throw_error) {
9268
    // The property doesn't exist - throw exception.
9269
    Handle<Object> reference_error =
9270
        isolate->factory()->NewReferenceError("not_defined",
9271
                                              HandleVector(&name, 1));
9272
    return MakePair(isolate->Throw(*reference_error), NULL);
9273
  } else {
9274
    // The property doesn't exist - return undefined.
9275
    return MakePair(isolate->heap()->undefined_value(),
9276
                    isolate->heap()->undefined_value());
9277
  }
9278
}
9279

    
9280

    
9281
RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlot) {
9282
  return LoadContextSlotHelper(args, isolate, true);
9283
}
9284

    
9285

    
9286
RUNTIME_FUNCTION(ObjectPair, Runtime_LoadContextSlotNoReferenceError) {
9287
  return LoadContextSlotHelper(args, isolate, false);
9288
}
9289

    
9290

    
9291
RUNTIME_FUNCTION(MaybeObject*, Runtime_StoreContextSlot) {
9292
  HandleScope scope(isolate);
9293
  ASSERT(args.length() == 4);
9294

    
9295
  Handle<Object> value(args[0], isolate);
9296
  CONVERT_ARG_HANDLE_CHECKED(Context, context, 1);
9297
  CONVERT_ARG_HANDLE_CHECKED(String, name, 2);
9298
  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9299
  StrictModeFlag strict_mode = (language_mode == CLASSIC_MODE)
9300
      ? kNonStrictMode : kStrictMode;
9301

    
9302
  int index;
9303
  PropertyAttributes attributes;
9304
  ContextLookupFlags flags = FOLLOW_CHAINS;
9305
  BindingFlags binding_flags;
9306
  Handle<Object> holder = context->Lookup(name,
9307
                                          flags,
9308
                                          &index,
9309
                                          &attributes,
9310
                                          &binding_flags);
9311
  if (isolate->has_pending_exception()) return Failure::Exception();
9312

    
9313
  if (index >= 0) {
9314
    // The property was found in a context slot.
9315
    Handle<Context> context = Handle<Context>::cast(holder);
9316
    if (binding_flags == MUTABLE_CHECK_INITIALIZED &&
9317
        context->get(index)->IsTheHole()) {
9318
      Handle<Object> error =
9319
          isolate->factory()->NewReferenceError("not_defined",
9320
                                                HandleVector(&name, 1));
9321
      return isolate->Throw(*error);
9322
    }
9323
    // Ignore if read_only variable.
9324
    if ((attributes & READ_ONLY) == 0) {
9325
      // Context is a fixed array and set cannot fail.
9326
      context->set(index, *value);
9327
    } else if (strict_mode == kStrictMode) {
9328
      // Setting read only property in strict mode.
9329
      Handle<Object> error =
9330
          isolate->factory()->NewTypeError("strict_cannot_assign",
9331
                                           HandleVector(&name, 1));
9332
      return isolate->Throw(*error);
9333
    }
9334
    return *value;
9335
  }
9336

    
9337
  // Slow case: The property is not in a context slot.  It is either in a
9338
  // context extension object, a property of the subject of a with, or a
9339
  // property of the global object.
9340
  Handle<JSReceiver> object;
9341

    
9342
  if (!holder.is_null()) {
9343
    // The property exists on the holder.
9344
    object = Handle<JSReceiver>::cast(holder);
9345
  } else {
9346
    // The property was not found.
9347
    ASSERT(attributes == ABSENT);
9348

    
9349
    if (strict_mode == kStrictMode) {
9350
      // Throw in strict mode (assignment to undefined variable).
9351
      Handle<Object> error =
9352
          isolate->factory()->NewReferenceError(
9353
              "not_defined", HandleVector(&name, 1));
9354
      return isolate->Throw(*error);
9355
    }
9356
    // In non-strict mode, the property is added to the global object.
9357
    attributes = NONE;
9358
    object = Handle<JSReceiver>(isolate->context()->global_object());
9359
  }
9360

    
9361
  // Set the property if it's not read only or doesn't yet exist.
9362
  if ((attributes & READ_ONLY) == 0 ||
9363
      (object->GetLocalPropertyAttribute(*name) == ABSENT)) {
9364
    RETURN_IF_EMPTY_HANDLE(
9365
        isolate,
9366
        JSReceiver::SetProperty(object, name, value, NONE, strict_mode));
9367
  } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) {
9368
    // Setting read only property in strict mode.
9369
    Handle<Object> error =
9370
      isolate->factory()->NewTypeError(
9371
          "strict_cannot_assign", HandleVector(&name, 1));
9372
    return isolate->Throw(*error);
9373
  }
9374
  return *value;
9375
}
9376

    
9377

    
9378
RUNTIME_FUNCTION(MaybeObject*, Runtime_Throw) {
9379
  HandleScope scope(isolate);
9380
  ASSERT(args.length() == 1);
9381

    
9382
  return isolate->Throw(args[0]);
9383
}
9384

    
9385

    
9386
RUNTIME_FUNCTION(MaybeObject*, Runtime_ReThrow) {
9387
  HandleScope scope(isolate);
9388
  ASSERT(args.length() == 1);
9389

    
9390
  return isolate->ReThrow(args[0]);
9391
}
9392

    
9393

    
9394
RUNTIME_FUNCTION(MaybeObject*, Runtime_PromoteScheduledException) {
9395
  SealHandleScope shs(isolate);
9396
  ASSERT_EQ(0, args.length());
9397
  return isolate->PromoteScheduledException();
9398
}
9399

    
9400

    
9401
RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
9402
  HandleScope scope(isolate);
9403
  ASSERT(args.length() == 1);
9404

    
9405
  Handle<Object> name(args[0], isolate);
9406
  Handle<Object> reference_error =
9407
    isolate->factory()->NewReferenceError("not_defined",
9408
                                          HandleVector(&name, 1));
9409
  return isolate->Throw(*reference_error);
9410
}
9411

    
9412

    
9413
RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
9414
  HandleScope scope(isolate);
9415
  ASSERT(args.length() == 0);
9416
  return isolate->Throw(*isolate->factory()->NewTypeError(
9417
      "not_date_object", HandleVector<Object>(NULL, 0)));
9418
}
9419

    
9420

    
9421

    
9422
RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
9423
  SealHandleScope shs(isolate);
9424
  ASSERT(args.length() == 0);
9425

    
9426
  // First check if this is a real stack overflow.
9427
  if (isolate->stack_guard()->IsStackOverflow()) {
9428
    return isolate->StackOverflow();
9429
  }
9430

    
9431
  return Execution::HandleStackGuardInterrupt(isolate);
9432
}
9433

    
9434

    
9435
RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) {
9436
  HandleScope scope(isolate);
9437
  ASSERT(args.length() == 1);
9438
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
9439

    
9440
  // First check if this is a real stack overflow.
9441
  if (isolate->stack_guard()->IsStackOverflow()) {
9442
    SealHandleScope shs(isolate);
9443
    return isolate->StackOverflow();
9444
  }
9445

    
9446
  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
9447
  return (function->IsOptimized()) ? function->code()
9448
                                   : function->shared()->code();
9449
}
9450

    
9451

    
9452
RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
9453
  SealHandleScope shs(isolate);
9454
  ASSERT(args.length() == 0);
9455
  return Execution::HandleStackGuardInterrupt(isolate);
9456
}
9457

    
9458

    
9459
static int StackSize(Isolate* isolate) {
9460
  int n = 0;
9461
  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) n++;
9462
  return n;
9463
}
9464

    
9465

    
9466
static void PrintTransition(Isolate* isolate, Object* result) {
9467
  // indentation
9468
  { const int nmax = 80;
9469
    int n = StackSize(isolate);
9470
    if (n <= nmax)
9471
      PrintF("%4d:%*s", n, n, "");
9472
    else
9473
      PrintF("%4d:%*s", n, nmax, "...");
9474
  }
9475

    
9476
  if (result == NULL) {
9477
    JavaScriptFrame::PrintTop(isolate, stdout, true, false);
9478
    PrintF(" {\n");
9479
  } else {
9480
    // function result
9481
    PrintF("} -> ");
9482
    result->ShortPrint();
9483
    PrintF("\n");
9484
  }
9485
}
9486

    
9487

    
9488
RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceEnter) {
9489
  SealHandleScope shs(isolate);
9490
  ASSERT(args.length() == 0);
9491
  PrintTransition(isolate, NULL);
9492
  return isolate->heap()->undefined_value();
9493
}
9494

    
9495

    
9496
RUNTIME_FUNCTION(MaybeObject*, Runtime_TraceExit) {
9497
  SealHandleScope shs(isolate);
9498
  PrintTransition(isolate, args[0]);
9499
  return args[0];  // return TOS
9500
}
9501

    
9502

    
9503
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrint) {
9504
  SealHandleScope shs(isolate);
9505
  ASSERT(args.length() == 1);
9506

    
9507
#ifdef DEBUG
9508
  if (args[0]->IsString()) {
9509
    // If we have a string, assume it's a code "marker"
9510
    // and print some interesting cpu debugging info.
9511
    JavaScriptFrameIterator it(isolate);
9512
    JavaScriptFrame* frame = it.frame();
9513
    PrintF("fp = %p, sp = %p, caller_sp = %p: ",
9514
           frame->fp(), frame->sp(), frame->caller_sp());
9515
  } else {
9516
    PrintF("DebugPrint: ");
9517
  }
9518
  args[0]->Print();
9519
  if (args[0]->IsHeapObject()) {
9520
    PrintF("\n");
9521
    HeapObject::cast(args[0])->map()->Print();
9522
  }
9523
#else
9524
  // ShortPrint is available in release mode. Print is not.
9525
  args[0]->ShortPrint();
9526
#endif
9527
  PrintF("\n");
9528
  Flush();
9529

    
9530
  return args[0];  // return TOS
9531
}
9532

    
9533

    
9534
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugTrace) {
9535
  SealHandleScope shs(isolate);
9536
  ASSERT(args.length() == 0);
9537
  isolate->PrintStack(stdout);
9538
  return isolate->heap()->undefined_value();
9539
}
9540

    
9541

    
9542
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateCurrentTime) {
9543
  SealHandleScope shs(isolate);
9544
  ASSERT(args.length() == 0);
9545

    
9546
  // According to ECMA-262, section 15.9.1, page 117, the precision of
9547
  // the number in a Date object representing a particular instant in
9548
  // time is milliseconds. Therefore, we floor the result of getting
9549
  // the OS time.
9550
  double millis = floor(OS::TimeCurrentMillis());
9551
  return isolate->heap()->NumberFromDouble(millis);
9552
}
9553

    
9554

    
9555
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateParseString) {
9556
  HandleScope scope(isolate);
9557
  ASSERT(args.length() == 2);
9558

    
9559
  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
9560
  FlattenString(str);
9561

    
9562
  CONVERT_ARG_HANDLE_CHECKED(JSArray, output, 1);
9563

    
9564
  JSObject::EnsureCanContainHeapObjectElements(output);
9565
  RUNTIME_ASSERT(output->HasFastObjectElements());
9566

    
9567
  DisallowHeapAllocation no_gc;
9568

    
9569
  FixedArray* output_array = FixedArray::cast(output->elements());
9570
  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
9571
  bool result;
9572
  String::FlatContent str_content = str->GetFlatContent();
9573
  if (str_content.IsAscii()) {
9574
    result = DateParser::Parse(str_content.ToOneByteVector(),
9575
                               output_array,
9576
                               isolate->unicode_cache());
9577
  } else {
9578
    ASSERT(str_content.IsTwoByte());
9579
    result = DateParser::Parse(str_content.ToUC16Vector(),
9580
                               output_array,
9581
                               isolate->unicode_cache());
9582
  }
9583

    
9584
  if (result) {
9585
    return *output;
9586
  } else {
9587
    return isolate->heap()->null_value();
9588
  }
9589
}
9590

    
9591

    
9592
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
9593
  SealHandleScope shs(isolate);
9594
  ASSERT(args.length() == 1);
9595

    
9596
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9597
  int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x));
9598
  const char* zone = OS::LocalTimezone(static_cast<double>(time));
9599
  return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
9600
}
9601

    
9602

    
9603
RUNTIME_FUNCTION(MaybeObject*, Runtime_DateToUTC) {
9604
  SealHandleScope shs(isolate);
9605
  ASSERT(args.length() == 1);
9606

    
9607
  CONVERT_DOUBLE_ARG_CHECKED(x, 0);
9608
  int64_t time = isolate->date_cache()->ToUTC(static_cast<int64_t>(x));
9609

    
9610
  return isolate->heap()->NumberFromDouble(static_cast<double>(time));
9611
}
9612

    
9613

    
9614
RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalReceiver) {
9615
  SealHandleScope shs(isolate);
9616
  ASSERT(args.length() == 1);
9617
  Object* global = args[0];
9618
  if (!global->IsJSGlobalObject()) return isolate->heap()->null_value();
9619
  return JSGlobalObject::cast(global)->global_receiver();
9620
}
9621

    
9622

    
9623
RUNTIME_FUNCTION(MaybeObject*, Runtime_ParseJson) {
9624
  HandleScope scope(isolate);
9625
  ASSERT_EQ(1, args.length());
9626
  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9627

    
9628
  source = Handle<String>(FlattenGetString(source));
9629
  // Optimized fast case where we only have ASCII characters.
9630
  Handle<Object> result;
9631
  if (source->IsSeqOneByteString()) {
9632
    result = JsonParser<true>::Parse(source);
9633
  } else {
9634
    result = JsonParser<false>::Parse(source);
9635
  }
9636
  if (result.is_null()) {
9637
    // Syntax error or stack overflow in scanner.
9638
    ASSERT(isolate->has_pending_exception());
9639
    return Failure::Exception();
9640
  }
9641
  return *result;
9642
}
9643

    
9644

    
9645
bool CodeGenerationFromStringsAllowed(Isolate* isolate,
9646
                                      Handle<Context> context) {
9647
  ASSERT(context->allow_code_gen_from_strings()->IsFalse());
9648
  // Check with callback if set.
9649
  AllowCodeGenerationFromStringsCallback callback =
9650
      isolate->allow_code_gen_callback();
9651
  if (callback == NULL) {
9652
    // No callback set and code generation disallowed.
9653
    return false;
9654
  } else {
9655
    // Callback set. Let it decide if code generation is allowed.
9656
    VMState<EXTERNAL> state(isolate);
9657
    return callback(v8::Utils::ToLocal(context));
9658
  }
9659
}
9660

    
9661

    
9662
RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
9663
  HandleScope scope(isolate);
9664
  ASSERT_EQ(2, args.length());
9665
  CONVERT_ARG_HANDLE_CHECKED(String, source, 0);
9666
  CONVERT_BOOLEAN_ARG_CHECKED(function_literal_only, 1);
9667

    
9668
  // Extract native context.
9669
  Handle<Context> context(isolate->context()->native_context());
9670

    
9671
  // Check if native context allows code generation from
9672
  // strings. Throw an exception if it doesn't.
9673
  if (context->allow_code_gen_from_strings()->IsFalse() &&
9674
      !CodeGenerationFromStringsAllowed(isolate, context)) {
9675
    Handle<Object> error_message =
9676
        context->ErrorMessageForCodeGenerationFromStrings();
9677
    return isolate->Throw(*isolate->factory()->NewEvalError(
9678
        "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9679
  }
9680

    
9681
  // Compile source string in the native context.
9682
  ParseRestriction restriction = function_literal_only
9683
      ? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
9684
  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9685
      source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
9686
  RETURN_IF_EMPTY_HANDLE(isolate, shared);
9687
  Handle<JSFunction> fun =
9688
      isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
9689
                                                            context,
9690
                                                            NOT_TENURED);
9691
  return *fun;
9692
}
9693

    
9694

    
9695
static ObjectPair CompileGlobalEval(Isolate* isolate,
9696
                                    Handle<String> source,
9697
                                    Handle<Object> receiver,
9698
                                    LanguageMode language_mode,
9699
                                    int scope_position) {
9700
  Handle<Context> context = Handle<Context>(isolate->context());
9701
  Handle<Context> native_context = Handle<Context>(context->native_context());
9702

    
9703
  // Check if native context allows code generation from
9704
  // strings. Throw an exception if it doesn't.
9705
  if (native_context->allow_code_gen_from_strings()->IsFalse() &&
9706
      !CodeGenerationFromStringsAllowed(isolate, native_context)) {
9707
    Handle<Object> error_message =
9708
        native_context->ErrorMessageForCodeGenerationFromStrings();
9709
    isolate->Throw(*isolate->factory()->NewEvalError(
9710
        "code_gen_from_strings", HandleVector<Object>(&error_message, 1)));
9711
    return MakePair(Failure::Exception(), NULL);
9712
  }
9713

    
9714
  // Deal with a normal eval call with a string argument. Compile it
9715
  // and return the compiled function bound in the local context.
9716
  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
9717
      source,
9718
      context,
9719
      context->IsNativeContext(),
9720
      language_mode,
9721
      NO_PARSE_RESTRICTION,
9722
      scope_position);
9723
  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
9724
                               MakePair(Failure::Exception(), NULL));
9725
  Handle<JSFunction> compiled =
9726
      isolate->factory()->NewFunctionFromSharedFunctionInfo(
9727
          shared, context, NOT_TENURED);
9728
  return MakePair(*compiled, *receiver);
9729
}
9730

    
9731

    
9732
RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) {
9733
  HandleScope scope(isolate);
9734
  ASSERT(args.length() == 5);
9735

    
9736
  Handle<Object> callee = args.at<Object>(0);
9737

    
9738
  // If "eval" didn't refer to the original GlobalEval, it's not a
9739
  // direct call to eval.
9740
  // (And even if it is, but the first argument isn't a string, just let
9741
  // execution default to an indirect call to eval, which will also return
9742
  // the first argument without doing anything).
9743
  if (*callee != isolate->native_context()->global_eval_fun() ||
9744
      !args[1]->IsString()) {
9745
    return MakePair(*callee, isolate->heap()->the_hole_value());
9746
  }
9747

    
9748
  CONVERT_LANGUAGE_MODE_ARG(language_mode, 3);
9749
  ASSERT(args[4]->IsSmi());
9750
  return CompileGlobalEval(isolate,
9751
                           args.at<String>(1),
9752
                           args.at<Object>(2),
9753
                           language_mode,
9754
                           args.smi_at(4));
9755
}
9756

    
9757

    
9758
static MaybeObject* Allocate(Isolate* isolate,
9759
                             int size,
9760
                             AllocationSpace space) {
9761
  // Allocate a block of memory in the given space (filled with a filler).
9762
  // Use as fallback for allocation in generated code when the space
9763
  // is full.
9764
  SealHandleScope shs(isolate);
9765
  RUNTIME_ASSERT(IsAligned(size, kPointerSize));
9766
  RUNTIME_ASSERT(size > 0);
9767
  Heap* heap = isolate->heap();
9768
  RUNTIME_ASSERT(size <= heap->MaxRegularSpaceAllocationSize());
9769
  Object* allocation;
9770
  { MaybeObject* maybe_allocation;
9771
    if (space == NEW_SPACE) {
9772
      maybe_allocation = heap->new_space()->AllocateRaw(size);
9773
    } else {
9774
      ASSERT(space == OLD_POINTER_SPACE || space == OLD_DATA_SPACE);
9775
      maybe_allocation = heap->paged_space(space)->AllocateRaw(size);
9776
    }
9777
    if (maybe_allocation->ToObject(&allocation)) {
9778
      heap->CreateFillerObjectAt(HeapObject::cast(allocation)->address(), size);
9779
    }
9780
    return maybe_allocation;
9781
  }
9782
}
9783

    
9784

    
9785
RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInNewSpace) {
9786
  SealHandleScope shs(isolate);
9787
  ASSERT(args.length() == 1);
9788
  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9789
  return Allocate(isolate, size_smi->value(), NEW_SPACE);
9790
}
9791

    
9792

    
9793
RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldPointerSpace) {
9794
  SealHandleScope shs(isolate);
9795
  ASSERT(args.length() == 1);
9796
  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9797
  return Allocate(isolate, size_smi->value(), OLD_POINTER_SPACE);
9798
}
9799

    
9800

    
9801
RUNTIME_FUNCTION(MaybeObject*, Runtime_AllocateInOldDataSpace) {
9802
  SealHandleScope shs(isolate);
9803
  ASSERT(args.length() == 1);
9804
  CONVERT_ARG_HANDLE_CHECKED(Smi, size_smi, 0);
9805
  return Allocate(isolate, size_smi->value(), OLD_DATA_SPACE);
9806
}
9807

    
9808

    
9809
// Push an object unto an array of objects if it is not already in the
9810
// array.  Returns true if the element was pushed on the stack and
9811
// false otherwise.
9812
RUNTIME_FUNCTION(MaybeObject*, Runtime_PushIfAbsent) {
9813
  SealHandleScope shs(isolate);
9814
  ASSERT(args.length() == 2);
9815
  CONVERT_ARG_CHECKED(JSArray, array, 0);
9816
  CONVERT_ARG_CHECKED(JSReceiver, element, 1);
9817
  RUNTIME_ASSERT(array->HasFastSmiOrObjectElements());
9818
  int length = Smi::cast(array->length())->value();
9819
  FixedArray* elements = FixedArray::cast(array->elements());
9820
  for (int i = 0; i < length; i++) {
9821
    if (elements->get(i) == element) return isolate->heap()->false_value();
9822
  }
9823
  Object* obj;
9824
  // Strict not needed. Used for cycle detection in Array join implementation.
9825
  { MaybeObject* maybe_obj =
9826
        array->SetFastElement(length, element, kNonStrictMode, true);
9827
    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
9828
  }
9829
  return isolate->heap()->true_value();
9830
}
9831

    
9832

    
9833
/**
9834
 * A simple visitor visits every element of Array's.
9835
 * The backend storage can be a fixed array for fast elements case,
9836
 * or a dictionary for sparse array. Since Dictionary is a subtype
9837
 * of FixedArray, the class can be used by both fast and slow cases.
9838
 * The second parameter of the constructor, fast_elements, specifies
9839
 * whether the storage is a FixedArray or Dictionary.
9840
 *
9841
 * An index limit is used to deal with the situation that a result array
9842
 * length overflows 32-bit non-negative integer.
9843
 */
9844
class ArrayConcatVisitor {
9845
 public:
9846
  ArrayConcatVisitor(Isolate* isolate,
9847
                     Handle<FixedArray> storage,
9848
                     bool fast_elements) :
9849
      isolate_(isolate),
9850
      storage_(Handle<FixedArray>::cast(
9851
          isolate->global_handles()->Create(*storage))),
9852
      index_offset_(0u),
9853
      fast_elements_(fast_elements),
9854
      exceeds_array_limit_(false) { }
9855

    
9856
  ~ArrayConcatVisitor() {
9857
    clear_storage();
9858
  }
9859

    
9860
  void visit(uint32_t i, Handle<Object> elm) {
9861
    if (i > JSObject::kMaxElementCount - index_offset_) {
9862
      exceeds_array_limit_ = true;
9863
      return;
9864
    }
9865
    uint32_t index = index_offset_ + i;
9866

    
9867
    if (fast_elements_) {
9868
      if (index < static_cast<uint32_t>(storage_->length())) {
9869
        storage_->set(index, *elm);
9870
        return;
9871
      }
9872
      // Our initial estimate of length was foiled, possibly by
9873
      // getters on the arrays increasing the length of later arrays
9874
      // during iteration.
9875
      // This shouldn't happen in anything but pathological cases.
9876
      SetDictionaryMode(index);
9877
      // Fall-through to dictionary mode.
9878
    }
9879
    ASSERT(!fast_elements_);
9880
    Handle<SeededNumberDictionary> dict(
9881
        SeededNumberDictionary::cast(*storage_));
9882
    Handle<SeededNumberDictionary> result =
9883
        isolate_->factory()->DictionaryAtNumberPut(dict, index, elm);
9884
    if (!result.is_identical_to(dict)) {
9885
      // Dictionary needed to grow.
9886
      clear_storage();
9887
      set_storage(*result);
9888
    }
9889
  }
9890

    
9891
  void increase_index_offset(uint32_t delta) {
9892
    if (JSObject::kMaxElementCount - index_offset_ < delta) {
9893
      index_offset_ = JSObject::kMaxElementCount;
9894
    } else {
9895
      index_offset_ += delta;
9896
    }
9897
  }
9898

    
9899
  bool exceeds_array_limit() {
9900
    return exceeds_array_limit_;
9901
  }
9902

    
9903
  Handle<JSArray> ToArray() {
9904
    Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
9905
    Handle<Object> length =
9906
        isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
9907
    Handle<Map> map;
9908
    if (fast_elements_) {
9909
      map = isolate_->factory()->GetElementsTransitionMap(array,
9910
                                                          FAST_HOLEY_ELEMENTS);
9911
    } else {
9912
      map = isolate_->factory()->GetElementsTransitionMap(array,
9913
                                                          DICTIONARY_ELEMENTS);
9914
    }
9915
    array->set_map(*map);
9916
    array->set_length(*length);
9917
    array->set_elements(*storage_);
9918
    return array;
9919
  }
9920

    
9921
 private:
9922
  // Convert storage to dictionary mode.
9923
  void SetDictionaryMode(uint32_t index) {
9924
    ASSERT(fast_elements_);
9925
    Handle<FixedArray> current_storage(*storage_);
9926
    Handle<SeededNumberDictionary> slow_storage(
9927
        isolate_->factory()->NewSeededNumberDictionary(
9928
            current_storage->length()));
9929
    uint32_t current_length = static_cast<uint32_t>(current_storage->length());
9930
    for (uint32_t i = 0; i < current_length; i++) {
9931
      HandleScope loop_scope(isolate_);
9932
      Handle<Object> element(current_storage->get(i), isolate_);
9933
      if (!element->IsTheHole()) {
9934
        Handle<SeededNumberDictionary> new_storage =
9935
          isolate_->factory()->DictionaryAtNumberPut(slow_storage, i, element);
9936
        if (!new_storage.is_identical_to(slow_storage)) {
9937
          slow_storage = loop_scope.CloseAndEscape(new_storage);
9938
        }
9939
      }
9940
    }
9941
    clear_storage();
9942
    set_storage(*slow_storage);
9943
    fast_elements_ = false;
9944
  }
9945

    
9946
  inline void clear_storage() {
9947
    isolate_->global_handles()->Destroy(
9948
        Handle<Object>::cast(storage_).location());
9949
  }
9950

    
9951
  inline void set_storage(FixedArray* storage) {
9952
    storage_ = Handle<FixedArray>::cast(
9953
        isolate_->global_handles()->Create(storage));
9954
  }
9955

    
9956
  Isolate* isolate_;
9957
  Handle<FixedArray> storage_;  // Always a global handle.
9958
  // Index after last seen index. Always less than or equal to
9959
  // JSObject::kMaxElementCount.
9960
  uint32_t index_offset_;
9961
  bool fast_elements_ : 1;
9962
  bool exceeds_array_limit_ : 1;
9963
};
9964

    
9965

    
9966
static uint32_t EstimateElementCount(Handle<JSArray> array) {
9967
  uint32_t length = static_cast<uint32_t>(array->length()->Number());
9968
  int element_count = 0;
9969
  switch (array->GetElementsKind()) {
9970
    case FAST_SMI_ELEMENTS:
9971
    case FAST_HOLEY_SMI_ELEMENTS:
9972
    case FAST_ELEMENTS:
9973
    case FAST_HOLEY_ELEMENTS: {
9974
      // Fast elements can't have lengths that are not representable by
9975
      // a 32-bit signed integer.
9976
      ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
9977
      int fast_length = static_cast<int>(length);
9978
      Handle<FixedArray> elements(FixedArray::cast(array->elements()));
9979
      for (int i = 0; i < fast_length; i++) {
9980
        if (!elements->get(i)->IsTheHole()) element_count++;
9981
      }
9982
      break;
9983
    }
9984
    case FAST_DOUBLE_ELEMENTS:
9985
    case FAST_HOLEY_DOUBLE_ELEMENTS: {
9986
      // Fast elements can't have lengths that are not representable by
9987
      // a 32-bit signed integer.
9988
      ASSERT(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
9989
      int fast_length = static_cast<int>(length);
9990
      if (array->elements()->IsFixedArray()) {
9991
        ASSERT(FixedArray::cast(array->elements())->length() == 0);
9992
        break;
9993
      }
9994
      Handle<FixedDoubleArray> elements(
9995
          FixedDoubleArray::cast(array->elements()));
9996
      for (int i = 0; i < fast_length; i++) {
9997
        if (!elements->is_the_hole(i)) element_count++;
9998
      }
9999
      break;
10000
    }
10001
    case DICTIONARY_ELEMENTS: {
10002
      Handle<SeededNumberDictionary> dictionary(
10003
          SeededNumberDictionary::cast(array->elements()));
10004
      int capacity = dictionary->Capacity();
10005
      for (int i = 0; i < capacity; i++) {
10006
        Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
10007
        if (dictionary->IsKey(*key)) {
10008
          element_count++;
10009
        }
10010
      }
10011
      break;
10012
    }
10013
    case NON_STRICT_ARGUMENTS_ELEMENTS:
10014
    case EXTERNAL_BYTE_ELEMENTS:
10015
    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
10016
    case EXTERNAL_SHORT_ELEMENTS:
10017
    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
10018
    case EXTERNAL_INT_ELEMENTS:
10019
    case EXTERNAL_UNSIGNED_INT_ELEMENTS:
10020
    case EXTERNAL_FLOAT_ELEMENTS:
10021
    case EXTERNAL_DOUBLE_ELEMENTS:
10022
    case EXTERNAL_PIXEL_ELEMENTS:
10023
      // External arrays are always dense.
10024
      return length;
10025
  }
10026
  // As an estimate, we assume that the prototype doesn't contain any
10027
  // inherited elements.
10028
  return element_count;
10029
}
10030

    
10031

    
10032

    
10033
template<class ExternalArrayClass, class ElementType>
10034
static void IterateExternalArrayElements(Isolate* isolate,
10035
                                         Handle<JSObject> receiver,
10036
                                         bool elements_are_ints,
10037
                                         bool elements_are_guaranteed_smis,
10038
                                         ArrayConcatVisitor* visitor) {
10039
  Handle<ExternalArrayClass> array(
10040
      ExternalArrayClass::cast(receiver->elements()));
10041
  uint32_t len = static_cast<uint32_t>(array->length());
10042

    
10043
  ASSERT(visitor != NULL);
10044
  if (elements_are_ints) {
10045
    if (elements_are_guaranteed_smis) {
10046
      for (uint32_t j = 0; j < len; j++) {
10047
        HandleScope loop_scope(isolate);
10048
        Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
10049
                      isolate);
10050
        visitor->visit(j, e);
10051
      }
10052
    } else {
10053
      for (uint32_t j = 0; j < len; j++) {
10054
        HandleScope loop_scope(isolate);
10055
        int64_t val = static_cast<int64_t>(array->get_scalar(j));
10056
        if (Smi::IsValid(static_cast<intptr_t>(val))) {
10057
          Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
10058
          visitor->visit(j, e);
10059
        } else {
10060
          Handle<Object> e =
10061
              isolate->factory()->NewNumber(static_cast<ElementType>(val));
10062
          visitor->visit(j, e);
10063
        }
10064
      }
10065
    }
10066
  } else {
10067
    for (uint32_t j = 0; j < len; j++) {
10068
      HandleScope loop_scope(isolate);
10069
      Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
10070
      visitor->visit(j, e);
10071
    }
10072
  }
10073
}
10074

    
10075

    
10076
// Used for sorting indices in a List<uint32_t>.
10077
static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
10078
  uint32_t a = *ap;
10079
  uint32_t b = *bp;
10080
  return (a == b) ? 0 : (a < b) ? -1 : 1;
10081
}
10082

    
10083

    
10084
static void CollectElementIndices(Handle<JSObject> object,
10085
                                  uint32_t range,
10086
                                  List<uint32_t>* indices) {
10087
  Isolate* isolate = object->GetIsolate();
10088
  ElementsKind kind = object->GetElementsKind();
10089
  switch (kind) {
10090
    case FAST_SMI_ELEMENTS:
10091
    case FAST_ELEMENTS:
10092
    case FAST_HOLEY_SMI_ELEMENTS:
10093
    case FAST_HOLEY_ELEMENTS: {
10094
      Handle<FixedArray> elements(FixedArray::cast(object->elements()));
10095
      uint32_t length = static_cast<uint32_t>(elements->length());
10096
      if (range < length) length = range;
10097
      for (uint32_t i = 0; i < length; i++) {
10098
        if (!elements->get(i)->IsTheHole()) {
10099
          indices->Add(i);
10100
        }
10101
      }
10102
      break;
10103
    }
10104
    case FAST_HOLEY_DOUBLE_ELEMENTS:
10105
    case FAST_DOUBLE_ELEMENTS: {
10106
      // TODO(1810): Decide if it's worthwhile to implement this.
10107
      UNREACHABLE();
10108
      break;
10109
    }
10110
    case DICTIONARY_ELEMENTS: {
10111
      Handle<SeededNumberDictionary> dict(
10112
          SeededNumberDictionary::cast(object->elements()));
10113
      uint32_t capacity = dict->Capacity();
10114
      for (uint32_t j = 0; j < capacity; j++) {
10115
        HandleScope loop_scope(isolate);
10116
        Handle<Object> k(dict->KeyAt(j), isolate);
10117
        if (dict->IsKey(*k)) {
10118
          ASSERT(k->IsNumber());
10119
          uint32_t index = static_cast<uint32_t>(k->Number());
10120
          if (index < range) {
10121
            indices->Add(index);
10122
          }
10123
        }
10124
      }
10125
      break;
10126
    }
10127
    default: {
10128
      int dense_elements_length;
10129
      switch (kind) {
10130
        case EXTERNAL_PIXEL_ELEMENTS: {
10131
          dense_elements_length =
10132
              ExternalPixelArray::cast(object->elements())->length();
10133
          break;
10134
        }
10135
        case EXTERNAL_BYTE_ELEMENTS: {
10136
          dense_elements_length =
10137
              ExternalByteArray::cast(object->elements())->length();
10138
          break;
10139
        }
10140
        case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10141
          dense_elements_length =
10142
              ExternalUnsignedByteArray::cast(object->elements())->length();
10143
          break;
10144
        }
10145
        case EXTERNAL_SHORT_ELEMENTS: {
10146
          dense_elements_length =
10147
              ExternalShortArray::cast(object->elements())->length();
10148
          break;
10149
        }
10150
        case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10151
          dense_elements_length =
10152
              ExternalUnsignedShortArray::cast(object->elements())->length();
10153
          break;
10154
        }
10155
        case EXTERNAL_INT_ELEMENTS: {
10156
          dense_elements_length =
10157
              ExternalIntArray::cast(object->elements())->length();
10158
          break;
10159
        }
10160
        case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10161
          dense_elements_length =
10162
              ExternalUnsignedIntArray::cast(object->elements())->length();
10163
          break;
10164
        }
10165
        case EXTERNAL_FLOAT_ELEMENTS: {
10166
          dense_elements_length =
10167
              ExternalFloatArray::cast(object->elements())->length();
10168
          break;
10169
        }
10170
        case EXTERNAL_DOUBLE_ELEMENTS: {
10171
          dense_elements_length =
10172
              ExternalDoubleArray::cast(object->elements())->length();
10173
          break;
10174
        }
10175
        default:
10176
          UNREACHABLE();
10177
          dense_elements_length = 0;
10178
          break;
10179
      }
10180
      uint32_t length = static_cast<uint32_t>(dense_elements_length);
10181
      if (range <= length) {
10182
        length = range;
10183
        // We will add all indices, so we might as well clear it first
10184
        // and avoid duplicates.
10185
        indices->Clear();
10186
      }
10187
      for (uint32_t i = 0; i < length; i++) {
10188
        indices->Add(i);
10189
      }
10190
      if (length == range) return;  // All indices accounted for already.
10191
      break;
10192
    }
10193
  }
10194

    
10195
  Handle<Object> prototype(object->GetPrototype(), isolate);
10196
  if (prototype->IsJSObject()) {
10197
    // The prototype will usually have no inherited element indices,
10198
    // but we have to check.
10199
    CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices);
10200
  }
10201
}
10202

    
10203

    
10204
/**
10205
 * A helper function that visits elements of a JSArray in numerical
10206
 * order.
10207
 *
10208
 * The visitor argument called for each existing element in the array
10209
 * with the element index and the element's value.
10210
 * Afterwards it increments the base-index of the visitor by the array
10211
 * length.
10212
 * Returns false if any access threw an exception, otherwise true.
10213
 */
10214
static bool IterateElements(Isolate* isolate,
10215
                            Handle<JSArray> receiver,
10216
                            ArrayConcatVisitor* visitor) {
10217
  uint32_t length = static_cast<uint32_t>(receiver->length()->Number());
10218
  switch (receiver->GetElementsKind()) {
10219
    case FAST_SMI_ELEMENTS:
10220
    case FAST_ELEMENTS:
10221
    case FAST_HOLEY_SMI_ELEMENTS:
10222
    case FAST_HOLEY_ELEMENTS: {
10223
      // Run through the elements FixedArray and use HasElement and GetElement
10224
      // to check the prototype for missing elements.
10225
      Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
10226
      int fast_length = static_cast<int>(length);
10227
      ASSERT(fast_length <= elements->length());
10228
      for (int j = 0; j < fast_length; j++) {
10229
        HandleScope loop_scope(isolate);
10230
        Handle<Object> element_value(elements->get(j), isolate);
10231
        if (!element_value->IsTheHole()) {
10232
          visitor->visit(j, element_value);
10233
        } else if (JSReceiver::HasElement(receiver, j)) {
10234
          // Call GetElement on receiver, not its prototype, or getters won't
10235
          // have the correct receiver.
10236
          element_value = Object::GetElement(isolate, receiver, j);
10237
          RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10238
          visitor->visit(j, element_value);
10239
        }
10240
      }
10241
      break;
10242
    }
10243
    case FAST_HOLEY_DOUBLE_ELEMENTS:
10244
    case FAST_DOUBLE_ELEMENTS: {
10245
      // Run through the elements FixedArray and use HasElement and GetElement
10246
      // to check the prototype for missing elements.
10247
      Handle<FixedDoubleArray> elements(
10248
          FixedDoubleArray::cast(receiver->elements()));
10249
      int fast_length = static_cast<int>(length);
10250
      ASSERT(fast_length <= elements->length());
10251
      for (int j = 0; j < fast_length; j++) {
10252
        HandleScope loop_scope(isolate);
10253
        if (!elements->is_the_hole(j)) {
10254
          double double_value = elements->get_scalar(j);
10255
          Handle<Object> element_value =
10256
              isolate->factory()->NewNumber(double_value);
10257
          visitor->visit(j, element_value);
10258
        } else if (JSReceiver::HasElement(receiver, j)) {
10259
          // Call GetElement on receiver, not its prototype, or getters won't
10260
          // have the correct receiver.
10261
          Handle<Object> element_value =
10262
              Object::GetElement(isolate, receiver, j);
10263
          RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element_value, false);
10264
          visitor->visit(j, element_value);
10265
        }
10266
      }
10267
      break;
10268
    }
10269
    case DICTIONARY_ELEMENTS: {
10270
      Handle<SeededNumberDictionary> dict(receiver->element_dictionary());
10271
      List<uint32_t> indices(dict->Capacity() / 2);
10272
      // Collect all indices in the object and the prototypes less
10273
      // than length. This might introduce duplicates in the indices list.
10274
      CollectElementIndices(receiver, length, &indices);
10275
      indices.Sort(&compareUInt32);
10276
      int j = 0;
10277
      int n = indices.length();
10278
      while (j < n) {
10279
        HandleScope loop_scope(isolate);
10280
        uint32_t index = indices[j];
10281
        Handle<Object> element = Object::GetElement(isolate, receiver, index);
10282
        RETURN_IF_EMPTY_HANDLE_VALUE(isolate, element, false);
10283
        visitor->visit(index, element);
10284
        // Skip to next different index (i.e., omit duplicates).
10285
        do {
10286
          j++;
10287
        } while (j < n && indices[j] == index);
10288
      }
10289
      break;
10290
    }
10291
    case EXTERNAL_PIXEL_ELEMENTS: {
10292
      Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast(
10293
          receiver->elements()));
10294
      for (uint32_t j = 0; j < length; j++) {
10295
        Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
10296
        visitor->visit(j, e);
10297
      }
10298
      break;
10299
    }
10300
    case EXTERNAL_BYTE_ELEMENTS: {
10301
      IterateExternalArrayElements<ExternalByteArray, int8_t>(
10302
          isolate, receiver, true, true, visitor);
10303
      break;
10304
    }
10305
    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
10306
      IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>(
10307
          isolate, receiver, true, true, visitor);
10308
      break;
10309
    }
10310
    case EXTERNAL_SHORT_ELEMENTS: {
10311
      IterateExternalArrayElements<ExternalShortArray, int16_t>(
10312
          isolate, receiver, true, true, visitor);
10313
      break;
10314
    }
10315
    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
10316
      IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>(
10317
          isolate, receiver, true, true, visitor);
10318
      break;
10319
    }
10320
    case EXTERNAL_INT_ELEMENTS: {
10321
      IterateExternalArrayElements<ExternalIntArray, int32_t>(
10322
          isolate, receiver, true, false, visitor);
10323
      break;
10324
    }
10325
    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
10326
      IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>(
10327
          isolate, receiver, true, false, visitor);
10328
      break;
10329
    }
10330
    case EXTERNAL_FLOAT_ELEMENTS: {
10331
      IterateExternalArrayElements<ExternalFloatArray, float>(
10332
          isolate, receiver, false, false, visitor);
10333
      break;
10334
    }
10335
    case EXTERNAL_DOUBLE_ELEMENTS: {
10336
      IterateExternalArrayElements<ExternalDoubleArray, double>(
10337
          isolate, receiver, false, false, visitor);
10338
      break;
10339
    }
10340
    default:
10341
      UNREACHABLE();
10342
      break;
10343
  }
10344
  visitor->increase_index_offset(length);
10345
  return true;
10346
}
10347

    
10348

    
10349
/**
10350
 * Array::concat implementation.
10351
 * See ECMAScript 262, 15.4.4.4.
10352
 * TODO(581): Fix non-compliance for very large concatenations and update to
10353
 * following the ECMAScript 5 specification.
10354
 */
10355
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
10356
  HandleScope handle_scope(isolate);
10357
  ASSERT(args.length() == 1);
10358

    
10359
  CONVERT_ARG_HANDLE_CHECKED(JSArray, arguments, 0);
10360
  int argument_count = static_cast<int>(arguments->length()->Number());
10361
  RUNTIME_ASSERT(arguments->HasFastObjectElements());
10362
  Handle<FixedArray> elements(FixedArray::cast(arguments->elements()));
10363

    
10364
  // Pass 1: estimate the length and number of elements of the result.
10365
  // The actual length can be larger if any of the arguments have getters
10366
  // that mutate other arguments (but will otherwise be precise).
10367
  // The number of elements is precise if there are no inherited elements.
10368

    
10369
  ElementsKind kind = FAST_SMI_ELEMENTS;
10370

    
10371
  uint32_t estimate_result_length = 0;
10372
  uint32_t estimate_nof_elements = 0;
10373
  for (int i = 0; i < argument_count; i++) {
10374
    HandleScope loop_scope(isolate);
10375
    Handle<Object> obj(elements->get(i), isolate);
10376
    uint32_t length_estimate;
10377
    uint32_t element_estimate;
10378
    if (obj->IsJSArray()) {
10379
      Handle<JSArray> array(Handle<JSArray>::cast(obj));
10380
      length_estimate = static_cast<uint32_t>(array->length()->Number());
10381
      if (length_estimate != 0) {
10382
        ElementsKind array_kind =
10383
            GetPackedElementsKind(array->map()->elements_kind());
10384
        if (IsMoreGeneralElementsKindTransition(kind, array_kind)) {
10385
          kind = array_kind;
10386
        }
10387
      }
10388
      element_estimate = EstimateElementCount(array);
10389
    } else {
10390
      if (obj->IsHeapObject()) {
10391
        if (obj->IsNumber()) {
10392
          if (IsMoreGeneralElementsKindTransition(kind, FAST_DOUBLE_ELEMENTS)) {
10393
            kind = FAST_DOUBLE_ELEMENTS;
10394
          }
10395
        } else if (IsMoreGeneralElementsKindTransition(kind, FAST_ELEMENTS)) {
10396
          kind = FAST_ELEMENTS;
10397
        }
10398
      }
10399
      length_estimate = 1;
10400
      element_estimate = 1;
10401
    }
10402
    // Avoid overflows by capping at kMaxElementCount.
10403
    if (JSObject::kMaxElementCount - estimate_result_length <
10404
        length_estimate) {
10405
      estimate_result_length = JSObject::kMaxElementCount;
10406
    } else {
10407
      estimate_result_length += length_estimate;
10408
    }
10409
    if (JSObject::kMaxElementCount - estimate_nof_elements <
10410
        element_estimate) {
10411
      estimate_nof_elements = JSObject::kMaxElementCount;
10412
    } else {
10413
      estimate_nof_elements += element_estimate;
10414
    }
10415
  }
10416

    
10417
  // If estimated number of elements is more than half of length, a
10418
  // fixed array (fast case) is more time and space-efficient than a
10419
  // dictionary.
10420
  bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
10421

    
10422
  Handle<FixedArray> storage;
10423
  if (fast_case) {
10424
    if (kind == FAST_DOUBLE_ELEMENTS) {
10425
      Handle<FixedDoubleArray> double_storage =
10426
          isolate->factory()->NewFixedDoubleArray(estimate_result_length);
10427
      int j = 0;
10428
      bool failure = false;
10429
      for (int i = 0; i < argument_count; i++) {
10430
        Handle<Object> obj(elements->get(i), isolate);
10431
        if (obj->IsSmi()) {
10432
          double_storage->set(j, Smi::cast(*obj)->value());
10433
          j++;
10434
        } else if (obj->IsNumber()) {
10435
          double_storage->set(j, obj->Number());
10436
          j++;
10437
        } else {
10438
          JSArray* array = JSArray::cast(*obj);
10439
          uint32_t length = static_cast<uint32_t>(array->length()->Number());
10440
          switch (array->map()->elements_kind()) {
10441
            case FAST_HOLEY_DOUBLE_ELEMENTS:
10442
            case FAST_DOUBLE_ELEMENTS: {
10443
              // Empty fixed array indicates that there are no elements.
10444
              if (array->elements()->IsFixedArray()) break;
10445
              FixedDoubleArray* elements =
10446
                  FixedDoubleArray::cast(array->elements());
10447
              for (uint32_t i = 0; i < length; i++) {
10448
                if (elements->is_the_hole(i)) {
10449
                  failure = true;
10450
                  break;
10451
                }
10452
                double double_value = elements->get_scalar(i);
10453
                double_storage->set(j, double_value);
10454
                j++;
10455
              }
10456
              break;
10457
            }
10458
            case FAST_HOLEY_SMI_ELEMENTS:
10459
            case FAST_SMI_ELEMENTS: {
10460
              FixedArray* elements(
10461
                  FixedArray::cast(array->elements()));
10462
              for (uint32_t i = 0; i < length; i++) {
10463
                Object* element = elements->get(i);
10464
                if (element->IsTheHole()) {
10465
                  failure = true;
10466
                  break;
10467
                }
10468
                int32_t int_value = Smi::cast(element)->value();
10469
                double_storage->set(j, int_value);
10470
                j++;
10471
              }
10472
              break;
10473
            }
10474
            case FAST_HOLEY_ELEMENTS:
10475
              ASSERT_EQ(0, length);
10476
              break;
10477
            default:
10478
              UNREACHABLE();
10479
          }
10480
        }
10481
        if (failure) break;
10482
      }
10483
      Handle<JSArray> array = isolate->factory()->NewJSArray(0);
10484
      Smi* length = Smi::FromInt(j);
10485
      Handle<Map> map;
10486
      map = isolate->factory()->GetElementsTransitionMap(array, kind);
10487
      array->set_map(*map);
10488
      array->set_length(length);
10489
      array->set_elements(*double_storage);
10490
      return *array;
10491
    }
10492
    // The backing storage array must have non-existing elements to preserve
10493
    // holes across concat operations.
10494
    storage = isolate->factory()->NewFixedArrayWithHoles(
10495
        estimate_result_length);
10496
  } else {
10497
    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
10498
    uint32_t at_least_space_for = estimate_nof_elements +
10499
                                  (estimate_nof_elements >> 2);
10500
    storage = Handle<FixedArray>::cast(
10501
        isolate->factory()->NewSeededNumberDictionary(at_least_space_for));
10502
  }
10503

    
10504
  ArrayConcatVisitor visitor(isolate, storage, fast_case);
10505

    
10506
  for (int i = 0; i < argument_count; i++) {
10507
    Handle<Object> obj(elements->get(i), isolate);
10508
    if (obj->IsJSArray()) {
10509
      Handle<JSArray> array = Handle<JSArray>::cast(obj);
10510
      if (!IterateElements(isolate, array, &visitor)) {
10511
        return Failure::Exception();
10512
      }
10513
    } else {
10514
      visitor.visit(0, obj);
10515
      visitor.increase_index_offset(1);
10516
    }
10517
  }
10518

    
10519
  if (visitor.exceeds_array_limit()) {
10520
    return isolate->Throw(
10521
        *isolate->factory()->NewRangeError("invalid_array_length",
10522
                                           HandleVector<Object>(NULL, 0)));
10523
  }
10524
  return *visitor.ToArray();
10525
}
10526

    
10527

    
10528
// This will not allocate (flatten the string), but it may run
10529
// very slowly for very deeply nested ConsStrings.  For debugging use only.
10530
RUNTIME_FUNCTION(MaybeObject*, Runtime_GlobalPrint) {
10531
  SealHandleScope shs(isolate);
10532
  ASSERT(args.length() == 1);
10533

    
10534
  CONVERT_ARG_CHECKED(String, string, 0);
10535
  ConsStringIteratorOp op;
10536
  StringCharacterStream stream(string, &op);
10537
  while (stream.HasMore()) {
10538
    uint16_t character = stream.GetNext();
10539
    PrintF("%c", character);
10540
  }
10541
  return string;
10542
}
10543

    
10544

    
10545
// Moves all own elements of an object, that are below a limit, to positions
10546
// starting at zero. All undefined values are placed after non-undefined values,
10547
// and are followed by non-existing element. Does not change the length
10548
// property.
10549
// Returns the number of non-undefined elements collected.
10550
RUNTIME_FUNCTION(MaybeObject*, Runtime_RemoveArrayHoles) {
10551
  HandleScope scope(isolate);
10552
  ASSERT(args.length() == 2);
10553
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
10554
  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[1]);
10555
  return *JSObject::PrepareElementsForSort(object, limit);
10556
}
10557

    
10558

    
10559
// Move contents of argument 0 (an array) to argument 1 (an array)
10560
RUNTIME_FUNCTION(MaybeObject*, Runtime_MoveArrayContents) {
10561
  SealHandleScope shs(isolate);
10562
  ASSERT(args.length() == 2);
10563
  CONVERT_ARG_CHECKED(JSArray, from, 0);
10564
  CONVERT_ARG_CHECKED(JSArray, to, 1);
10565
  from->ValidateElements();
10566
  to->ValidateElements();
10567
  FixedArrayBase* new_elements = from->elements();
10568
  ElementsKind from_kind = from->GetElementsKind();
10569
  MaybeObject* maybe_new_map;
10570
  maybe_new_map = to->GetElementsTransitionMap(isolate, from_kind);
10571
  Object* new_map;
10572
  if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map;
10573
  to->set_map_and_elements(Map::cast(new_map), new_elements);
10574
  to->set_length(from->length());
10575
  Object* obj;
10576
  { MaybeObject* maybe_obj = from->ResetElements();
10577
    if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10578
  }
10579
  from->set_length(Smi::FromInt(0));
10580
  to->ValidateElements();
10581
  return to;
10582
}
10583

    
10584

    
10585
// How many elements does this object/array have?
10586
RUNTIME_FUNCTION(MaybeObject*, Runtime_EstimateNumberOfElements) {
10587
  SealHandleScope shs(isolate);
10588
  ASSERT(args.length() == 1);
10589
  CONVERT_ARG_CHECKED(JSObject, object, 0);
10590
  HeapObject* elements = object->elements();
10591
  if (elements->IsDictionary()) {
10592
    int result = SeededNumberDictionary::cast(elements)->NumberOfElements();
10593
    return Smi::FromInt(result);
10594
  } else if (object->IsJSArray()) {
10595
    return JSArray::cast(object)->length();
10596
  } else {
10597
    return Smi::FromInt(FixedArray::cast(elements)->length());
10598
  }
10599
}
10600

    
10601

    
10602
// Returns an array that tells you where in the [0, length) interval an array
10603
// might have elements.  Can either return an array of keys (positive integers
10604
// or undefined) or a number representing the positive length of an interval
10605
// starting at index 0.
10606
// Intervals can span over some keys that are not in the object.
10607
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArrayKeys) {
10608
  HandleScope scope(isolate);
10609
  ASSERT(args.length() == 2);
10610
  CONVERT_ARG_HANDLE_CHECKED(JSObject, array, 0);
10611
  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
10612
  if (array->elements()->IsDictionary()) {
10613
    Handle<FixedArray> keys = isolate->factory()->empty_fixed_array();
10614
    for (Handle<Object> p = array;
10615
         !p->IsNull();
10616
         p = Handle<Object>(p->GetPrototype(isolate), isolate)) {
10617
      if (p->IsJSProxy() || JSObject::cast(*p)->HasIndexedInterceptor()) {
10618
        // Bail out if we find a proxy or interceptor, likely not worth
10619
        // collecting keys in that case.
10620
        return *isolate->factory()->NewNumberFromUint(length);
10621
      }
10622
      Handle<JSObject> current = Handle<JSObject>::cast(p);
10623
      Handle<FixedArray> current_keys =
10624
          isolate->factory()->NewFixedArray(
10625
              current->NumberOfLocalElements(NONE));
10626
      current->GetLocalElementKeys(*current_keys, NONE);
10627
      keys = UnionOfKeys(keys, current_keys);
10628
    }
10629
    // Erase any keys >= length.
10630
    // TODO(adamk): Remove this step when the contract of %GetArrayKeys
10631
    // is changed to let this happen on the JS side.
10632
    for (int i = 0; i < keys->length(); i++) {
10633
      if (NumberToUint32(keys->get(i)) >= length) keys->set_undefined(i);
10634
    }
10635
    return *isolate->factory()->NewJSArrayWithElements(keys);
10636
  } else {
10637
    ASSERT(array->HasFastSmiOrObjectElements() ||
10638
           array->HasFastDoubleElements());
10639
    uint32_t actual_length = static_cast<uint32_t>(array->elements()->length());
10640
    return *isolate->factory()->NewNumberFromUint(Min(actual_length, length));
10641
  }
10642
}
10643

    
10644

    
10645
RUNTIME_FUNCTION(MaybeObject*, Runtime_LookupAccessor) {
10646
  HandleScope scope(isolate);
10647
  ASSERT(args.length() == 3);
10648
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, receiver, 0);
10649
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10650
  CONVERT_SMI_ARG_CHECKED(flag, 2);
10651
  AccessorComponent component = flag == 0 ? ACCESSOR_GETTER : ACCESSOR_SETTER;
10652
  if (!receiver->IsJSObject()) return isolate->heap()->undefined_value();
10653
  Handle<Object> result =
10654
      JSObject::GetAccessor(Handle<JSObject>::cast(receiver), name, component);
10655
  RETURN_IF_EMPTY_HANDLE(isolate, result);
10656
  return *result;
10657
}
10658

    
10659

    
10660
#ifdef ENABLE_DEBUGGER_SUPPORT
10661
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugBreak) {
10662
  SealHandleScope shs(isolate);
10663
  ASSERT(args.length() == 0);
10664
  return Execution::DebugBreakHelper(isolate);
10665
}
10666

    
10667

    
10668
// Helper functions for wrapping and unwrapping stack frame ids.
10669
static Smi* WrapFrameId(StackFrame::Id id) {
10670
  ASSERT(IsAligned(OffsetFrom(id), static_cast<intptr_t>(4)));
10671
  return Smi::FromInt(id >> 2);
10672
}
10673

    
10674

    
10675
static StackFrame::Id UnwrapFrameId(int wrapped) {
10676
  return static_cast<StackFrame::Id>(wrapped << 2);
10677
}
10678

    
10679

    
10680
// Adds a JavaScript function as a debug event listener.
10681
// args[0]: debug event listener function to set or null or undefined for
10682
//          clearing the event listener function
10683
// args[1]: object supplied during callback
10684
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDebugEventListener) {
10685
  SealHandleScope shs(isolate);
10686
  ASSERT(args.length() == 2);
10687
  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
10688
                 args[0]->IsUndefined() ||
10689
                 args[0]->IsNull());
10690
  Handle<Object> callback = args.at<Object>(0);
10691
  Handle<Object> data = args.at<Object>(1);
10692
  isolate->debugger()->SetEventListener(callback, data);
10693

    
10694
  return isolate->heap()->undefined_value();
10695
}
10696

    
10697

    
10698
RUNTIME_FUNCTION(MaybeObject*, Runtime_Break) {
10699
  SealHandleScope shs(isolate);
10700
  ASSERT(args.length() == 0);
10701
  isolate->stack_guard()->DebugBreak();
10702
  return isolate->heap()->undefined_value();
10703
}
10704

    
10705

    
10706
static MaybeObject* DebugLookupResultValue(Heap* heap,
10707
                                           Object* receiver,
10708
                                           Name* name,
10709
                                           LookupResult* result,
10710
                                           bool* caught_exception) {
10711
  Object* value;
10712
  switch (result->type()) {
10713
    case NORMAL:
10714
      value = result->holder()->GetNormalizedProperty(result);
10715
      if (value->IsTheHole()) {
10716
        return heap->undefined_value();
10717
      }
10718
      return value;
10719
    case FIELD: {
10720
      Object* value;
10721
      MaybeObject* maybe_value =
10722
          JSObject::cast(result->holder())->FastPropertyAt(
10723
              result->representation(),
10724
              result->GetFieldIndex().field_index());
10725
      if (!maybe_value->To(&value)) return maybe_value;
10726
      if (value->IsTheHole()) {
10727
        return heap->undefined_value();
10728
      }
10729
      return value;
10730
    }
10731
    case CONSTANT:
10732
      return result->GetConstant();
10733
    case CALLBACKS: {
10734
      Object* structure = result->GetCallbackObject();
10735
      if (structure->IsForeign() || structure->IsAccessorInfo()) {
10736
        Isolate* isolate = heap->isolate();
10737
        HandleScope scope(isolate);
10738
        Handle<Object> value = JSObject::GetPropertyWithCallback(
10739
            handle(result->holder(), isolate),
10740
            handle(receiver, isolate),
10741
            handle(structure, isolate),
10742
            handle(name, isolate));
10743
        if (value.is_null()) {
10744
          MaybeObject* exception = heap->isolate()->pending_exception();
10745
          heap->isolate()->clear_pending_exception();
10746
          if (caught_exception != NULL) *caught_exception = true;
10747
          return exception;
10748
        }
10749
        return *value;
10750
      } else {
10751
        return heap->undefined_value();
10752
      }
10753
    }
10754
    case INTERCEPTOR:
10755
    case TRANSITION:
10756
      return heap->undefined_value();
10757
    case HANDLER:
10758
    case NONEXISTENT:
10759
      UNREACHABLE();
10760
      return heap->undefined_value();
10761
  }
10762
  UNREACHABLE();  // keep the compiler happy
10763
  return heap->undefined_value();
10764
}
10765

    
10766

    
10767
// Get debugger related details for an object property.
10768
// args[0]: object holding property
10769
// args[1]: name of the property
10770
//
10771
// The array returned contains the following information:
10772
// 0: Property value
10773
// 1: Property details
10774
// 2: Property value is exception
10775
// 3: Getter function if defined
10776
// 4: Setter function if defined
10777
// Items 2-4 are only filled if the property has either a getter or a setter
10778
// defined through __defineGetter__ and/or __defineSetter__.
10779
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPropertyDetails) {
10780
  HandleScope scope(isolate);
10781

    
10782
  ASSERT(args.length() == 2);
10783

    
10784
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10785
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10786

    
10787
  // Make sure to set the current context to the context before the debugger was
10788
  // entered (if the debugger is entered). The reason for switching context here
10789
  // is that for some property lookups (accessors and interceptors) callbacks
10790
  // into the embedding application can occour, and the embedding application
10791
  // could have the assumption that its own native context is the current
10792
  // context and not some internal debugger context.
10793
  SaveContext save(isolate);
10794
  if (isolate->debug()->InDebugger()) {
10795
    isolate->set_context(*isolate->debug()->debugger_entry()->GetContext());
10796
  }
10797

    
10798
  // Skip the global proxy as it has no properties and always delegates to the
10799
  // real global object.
10800
  if (obj->IsJSGlobalProxy()) {
10801
    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
10802
  }
10803

    
10804

    
10805
  // Check if the name is trivially convertible to an index and get the element
10806
  // if so.
10807
  uint32_t index;
10808
  if (name->AsArrayIndex(&index)) {
10809
    Handle<FixedArray> details = isolate->factory()->NewFixedArray(2);
10810
    Object* element_or_char;
10811
    { MaybeObject* maybe_element_or_char =
10812
          Runtime::GetElementOrCharAt(isolate, obj, index);
10813
      if (!maybe_element_or_char->ToObject(&element_or_char)) {
10814
        return maybe_element_or_char;
10815
      }
10816
    }
10817
    details->set(0, element_or_char);
10818
    details->set(
10819
        1, PropertyDetails(NONE, NORMAL, Representation::None()).AsSmi());
10820
    return *isolate->factory()->NewJSArrayWithElements(details);
10821
  }
10822

    
10823
  // Find the number of objects making up this.
10824
  int length = LocalPrototypeChainLength(*obj);
10825

    
10826
  // Try local lookup on each of the objects.
10827
  Handle<JSObject> jsproto = obj;
10828
  for (int i = 0; i < length; i++) {
10829
    LookupResult result(isolate);
10830
    jsproto->LocalLookup(*name, &result);
10831
    if (result.IsFound()) {
10832
      // LookupResult is not GC safe as it holds raw object pointers.
10833
      // GC can happen later in this code so put the required fields into
10834
      // local variables using handles when required for later use.
10835
      Handle<Object> result_callback_obj;
10836
      if (result.IsPropertyCallbacks()) {
10837
        result_callback_obj = Handle<Object>(result.GetCallbackObject(),
10838
                                             isolate);
10839
      }
10840
      Smi* property_details = result.GetPropertyDetails().AsSmi();
10841
      // DebugLookupResultValue can cause GC so details from LookupResult needs
10842
      // to be copied to handles before this.
10843
      bool caught_exception = false;
10844
      Object* raw_value;
10845
      { MaybeObject* maybe_raw_value =
10846
            DebugLookupResultValue(isolate->heap(), *obj, *name,
10847
                                   &result, &caught_exception);
10848
        if (!maybe_raw_value->ToObject(&raw_value)) return maybe_raw_value;
10849
      }
10850
      Handle<Object> value(raw_value, isolate);
10851

    
10852
      // If the callback object is a fixed array then it contains JavaScript
10853
      // getter and/or setter.
10854
      bool hasJavaScriptAccessors = result.IsPropertyCallbacks() &&
10855
                                    result_callback_obj->IsAccessorPair();
10856
      Handle<FixedArray> details =
10857
          isolate->factory()->NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
10858
      details->set(0, *value);
10859
      details->set(1, property_details);
10860
      if (hasJavaScriptAccessors) {
10861
        AccessorPair* accessors = AccessorPair::cast(*result_callback_obj);
10862
        details->set(2, isolate->heap()->ToBoolean(caught_exception));
10863
        details->set(3, accessors->GetComponent(ACCESSOR_GETTER));
10864
        details->set(4, accessors->GetComponent(ACCESSOR_SETTER));
10865
      }
10866

    
10867
      return *isolate->factory()->NewJSArrayWithElements(details);
10868
    }
10869
    if (i < length - 1) {
10870
      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
10871
    }
10872
  }
10873

    
10874
  return isolate->heap()->undefined_value();
10875
}
10876

    
10877

    
10878
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetProperty) {
10879
  HandleScope scope(isolate);
10880

    
10881
  ASSERT(args.length() == 2);
10882

    
10883
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10884
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10885

    
10886
  LookupResult result(isolate);
10887
  obj->Lookup(*name, &result);
10888
  if (result.IsFound()) {
10889
    return DebugLookupResultValue(isolate->heap(), *obj, *name, &result, NULL);
10890
  }
10891
  return isolate->heap()->undefined_value();
10892
}
10893

    
10894

    
10895
// Return the property type calculated from the property details.
10896
// args[0]: smi with property details.
10897
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyTypeFromDetails) {
10898
  SealHandleScope shs(isolate);
10899
  ASSERT(args.length() == 1);
10900
  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10901
  return Smi::FromInt(static_cast<int>(details.type()));
10902
}
10903

    
10904

    
10905
// Return the property attribute calculated from the property details.
10906
// args[0]: smi with property details.
10907
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyAttributesFromDetails) {
10908
  SealHandleScope shs(isolate);
10909
  ASSERT(args.length() == 1);
10910
  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10911
  return Smi::FromInt(static_cast<int>(details.attributes()));
10912
}
10913

    
10914

    
10915
// Return the property insertion index calculated from the property details.
10916
// args[0]: smi with property details.
10917
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPropertyIndexFromDetails) {
10918
  SealHandleScope shs(isolate);
10919
  ASSERT(args.length() == 1);
10920
  CONVERT_PROPERTY_DETAILS_CHECKED(details, 0);
10921
  // TODO(verwaest): Depends on the type of details.
10922
  return Smi::FromInt(details.dictionary_index());
10923
}
10924

    
10925

    
10926
// Return property value from named interceptor.
10927
// args[0]: object
10928
// args[1]: property name
10929
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugNamedInterceptorPropertyValue) {
10930
  HandleScope scope(isolate);
10931
  ASSERT(args.length() == 2);
10932
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10933
  RUNTIME_ASSERT(obj->HasNamedInterceptor());
10934
  CONVERT_ARG_HANDLE_CHECKED(Name, name, 1);
10935

    
10936
  PropertyAttributes attributes;
10937
  Handle<Object> result =
10938
      JSObject::GetPropertyWithInterceptor(obj, obj, name, &attributes);
10939
  RETURN_IF_EMPTY_HANDLE(isolate, result);
10940
  return *result;
10941
}
10942

    
10943

    
10944
// Return element value from indexed interceptor.
10945
// args[0]: object
10946
// args[1]: index
10947
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugIndexedInterceptorElementValue) {
10948
  HandleScope scope(isolate);
10949
  ASSERT(args.length() == 2);
10950
  CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
10951
  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
10952
  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
10953

    
10954
  return obj->GetElementWithInterceptor(*obj, index);
10955
}
10956

    
10957

    
10958
RUNTIME_FUNCTION(MaybeObject*, Runtime_CheckExecutionState) {
10959
  SealHandleScope shs(isolate);
10960
  ASSERT(args.length() >= 1);
10961
  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
10962
  // Check that the break id is valid.
10963
  if (isolate->debug()->break_id() == 0 ||
10964
      break_id != isolate->debug()->break_id()) {
10965
    return isolate->Throw(
10966
        isolate->heap()->illegal_execution_state_string());
10967
  }
10968

    
10969
  return isolate->heap()->true_value();
10970
}
10971

    
10972

    
10973
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameCount) {
10974
  HandleScope scope(isolate);
10975
  ASSERT(args.length() == 1);
10976

    
10977
  // Check arguments.
10978
  Object* result;
10979
  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
10980
      RUNTIME_ARGUMENTS(isolate, args));
10981
    if (!maybe_result->ToObject(&result)) return maybe_result;
10982
  }
10983

    
10984
  // Count all frames which are relevant to debugging stack trace.
10985
  int n = 0;
10986
  StackFrame::Id id = isolate->debug()->break_frame_id();
10987
  if (id == StackFrame::NO_ID) {
10988
    // If there is no JavaScript stack frame count is 0.
10989
    return Smi::FromInt(0);
10990
  }
10991

    
10992
  for (JavaScriptFrameIterator it(isolate, id); !it.done(); it.Advance()) {
10993
    n += it.frame()->GetInlineCount();
10994
  }
10995
  return Smi::FromInt(n);
10996
}
10997

    
10998

    
10999
class FrameInspector {
11000
 public:
11001
  FrameInspector(JavaScriptFrame* frame,
11002
                 int inlined_jsframe_index,
11003
                 Isolate* isolate)
11004
      : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) {
11005
    // Calculate the deoptimized frame.
11006
    if (frame->is_optimized()) {
11007
      deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame(
11008
          frame, inlined_jsframe_index, isolate);
11009
    }
11010
    has_adapted_arguments_ = frame_->has_adapted_arguments();
11011
    is_bottommost_ = inlined_jsframe_index == 0;
11012
    is_optimized_ = frame_->is_optimized();
11013
  }
11014

    
11015
  ~FrameInspector() {
11016
    // Get rid of the calculated deoptimized frame if any.
11017
    if (deoptimized_frame_ != NULL) {
11018
      Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_,
11019
                                                  isolate_);
11020
    }
11021
  }
11022

    
11023
  int GetParametersCount() {
11024
    return is_optimized_
11025
        ? deoptimized_frame_->parameters_count()
11026
        : frame_->ComputeParametersCount();
11027
  }
11028
  int expression_count() { return deoptimized_frame_->expression_count(); }
11029
  Object* GetFunction() {
11030
    return is_optimized_
11031
        ? deoptimized_frame_->GetFunction()
11032
        : frame_->function();
11033
  }
11034
  Object* GetParameter(int index) {
11035
    return is_optimized_
11036
        ? deoptimized_frame_->GetParameter(index)
11037
        : frame_->GetParameter(index);
11038
  }
11039
  Object* GetExpression(int index) {
11040
    return is_optimized_
11041
        ? deoptimized_frame_->GetExpression(index)
11042
        : frame_->GetExpression(index);
11043
  }
11044
  int GetSourcePosition() {
11045
    return is_optimized_
11046
        ? deoptimized_frame_->GetSourcePosition()
11047
        : frame_->LookupCode()->SourcePosition(frame_->pc());
11048
  }
11049
  bool IsConstructor() {
11050
    return is_optimized_ && !is_bottommost_
11051
        ? deoptimized_frame_->HasConstructStub()
11052
        : frame_->IsConstructor();
11053
  }
11054

    
11055
  // To inspect all the provided arguments the frame might need to be
11056
  // replaced with the arguments frame.
11057
  void SetArgumentsFrame(JavaScriptFrame* frame) {
11058
    ASSERT(has_adapted_arguments_);
11059
    frame_ = frame;
11060
    is_optimized_ = frame_->is_optimized();
11061
    ASSERT(!is_optimized_);
11062
  }
11063

    
11064
 private:
11065
  JavaScriptFrame* frame_;
11066
  DeoptimizedFrameInfo* deoptimized_frame_;
11067
  Isolate* isolate_;
11068
  bool is_optimized_;
11069
  bool is_bottommost_;
11070
  bool has_adapted_arguments_;
11071

    
11072
  DISALLOW_COPY_AND_ASSIGN(FrameInspector);
11073
};
11074

    
11075

    
11076
static const int kFrameDetailsFrameIdIndex = 0;
11077
static const int kFrameDetailsReceiverIndex = 1;
11078
static const int kFrameDetailsFunctionIndex = 2;
11079
static const int kFrameDetailsArgumentCountIndex = 3;
11080
static const int kFrameDetailsLocalCountIndex = 4;
11081
static const int kFrameDetailsSourcePositionIndex = 5;
11082
static const int kFrameDetailsConstructCallIndex = 6;
11083
static const int kFrameDetailsAtReturnIndex = 7;
11084
static const int kFrameDetailsFlagsIndex = 8;
11085
static const int kFrameDetailsFirstDynamicIndex = 9;
11086

    
11087

    
11088
static SaveContext* FindSavedContextForFrame(Isolate* isolate,
11089
                                             JavaScriptFrame* frame) {
11090
  SaveContext* save = isolate->save_context();
11091
  while (save != NULL && !save->IsBelowFrame(frame)) {
11092
    save = save->prev();
11093
  }
11094
  ASSERT(save != NULL);
11095
  return save;
11096
}
11097

    
11098

    
11099
// Return an array with frame details
11100
// args[0]: number: break id
11101
// args[1]: number: frame index
11102
//
11103
// The array returned contains the following information:
11104
// 0: Frame id
11105
// 1: Receiver
11106
// 2: Function
11107
// 3: Argument count
11108
// 4: Local count
11109
// 5: Source position
11110
// 6: Constructor call
11111
// 7: Is at return
11112
// 8: Flags
11113
// Arguments name, value
11114
// Locals name, value
11115
// Return value if any
11116
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFrameDetails) {
11117
  HandleScope scope(isolate);
11118
  ASSERT(args.length() == 2);
11119

    
11120
  // Check arguments.
11121
  Object* check;
11122
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
11123
      RUNTIME_ARGUMENTS(isolate, args));
11124
    if (!maybe_check->ToObject(&check)) return maybe_check;
11125
  }
11126
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
11127
  Heap* heap = isolate->heap();
11128

    
11129
  // Find the relevant frame with the requested index.
11130
  StackFrame::Id id = isolate->debug()->break_frame_id();
11131
  if (id == StackFrame::NO_ID) {
11132
    // If there are no JavaScript stack frames return undefined.
11133
    return heap->undefined_value();
11134
  }
11135

    
11136
  int count = 0;
11137
  JavaScriptFrameIterator it(isolate, id);
11138
  for (; !it.done(); it.Advance()) {
11139
    if (index < count + it.frame()->GetInlineCount()) break;
11140
    count += it.frame()->GetInlineCount();
11141
  }
11142
  if (it.done()) return heap->undefined_value();
11143

    
11144
  bool is_optimized = it.frame()->is_optimized();
11145

    
11146
  int inlined_jsframe_index = 0;  // Inlined frame index in optimized frame.
11147
  if (is_optimized) {
11148
    inlined_jsframe_index =
11149
        it.frame()->GetInlineCount() - (index - count) - 1;
11150
  }
11151
  FrameInspector frame_inspector(it.frame(), inlined_jsframe_index, isolate);
11152

    
11153
  // Traverse the saved contexts chain to find the active context for the
11154
  // selected frame.
11155
  SaveContext* save = FindSavedContextForFrame(isolate, it.frame());
11156

    
11157
  // Get the frame id.
11158
  Handle<Object> frame_id(WrapFrameId(it.frame()->id()), isolate);
11159

    
11160
  // Find source position in unoptimized code.
11161
  int position = frame_inspector.GetSourcePosition();
11162

    
11163
  // Check for constructor frame.
11164
  bool constructor = frame_inspector.IsConstructor();
11165

    
11166
  // Get scope info and read from it for local variable information.
11167
  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11168
  Handle<SharedFunctionInfo> shared(function->shared());
11169
  Handle<ScopeInfo> scope_info(shared->scope_info());
11170
  ASSERT(*scope_info != ScopeInfo::Empty(isolate));
11171

    
11172
  // Get the locals names and values into a temporary array.
11173
  //
11174
  // TODO(1240907): Hide compiler-introduced stack variables
11175
  // (e.g. .result)?  For users of the debugger, they will probably be
11176
  // confusing.
11177
  Handle<FixedArray> locals =
11178
      isolate->factory()->NewFixedArray(scope_info->LocalCount() * 2);
11179

    
11180
  // Fill in the values of the locals.
11181
  int i = 0;
11182
  for (; i < scope_info->StackLocalCount(); ++i) {
11183
    // Use the value from the stack.
11184
    locals->set(i * 2, scope_info->LocalName(i));
11185
    locals->set(i * 2 + 1, frame_inspector.GetExpression(i));
11186
  }
11187
  if (i < scope_info->LocalCount()) {
11188
    // Get the context containing declarations.
11189
    Handle<Context> context(
11190
        Context::cast(it.frame()->context())->declaration_context());
11191
    for (; i < scope_info->LocalCount(); ++i) {
11192
      Handle<String> name(scope_info->LocalName(i));
11193
      VariableMode mode;
11194
      InitializationFlag init_flag;
11195
      locals->set(i * 2, *name);
11196
      locals->set(i * 2 + 1, context->get(
11197
          scope_info->ContextSlotIndex(*name, &mode, &init_flag)));
11198
    }
11199
  }
11200

    
11201
  // Check whether this frame is positioned at return. If not top
11202
  // frame or if the frame is optimized it cannot be at a return.
11203
  bool at_return = false;
11204
  if (!is_optimized && index == 0) {
11205
    at_return = isolate->debug()->IsBreakAtReturn(it.frame());
11206
  }
11207

    
11208
  // If positioned just before return find the value to be returned and add it
11209
  // to the frame information.
11210
  Handle<Object> return_value = isolate->factory()->undefined_value();
11211
  if (at_return) {
11212
    StackFrameIterator it2(isolate);
11213
    Address internal_frame_sp = NULL;
11214
    while (!it2.done()) {
11215
      if (it2.frame()->is_internal()) {
11216
        internal_frame_sp = it2.frame()->sp();
11217
      } else {
11218
        if (it2.frame()->is_java_script()) {
11219
          if (it2.frame()->id() == it.frame()->id()) {
11220
            // The internal frame just before the JavaScript frame contains the
11221
            // value to return on top. A debug break at return will create an
11222
            // internal frame to store the return value (eax/rax/r0) before
11223
            // entering the debug break exit frame.
11224
            if (internal_frame_sp != NULL) {
11225
              return_value =
11226
                  Handle<Object>(Memory::Object_at(internal_frame_sp),
11227
                                 isolate);
11228
              break;
11229
            }
11230
          }
11231
        }
11232

    
11233
        // Indicate that the previous frame was not an internal frame.
11234
        internal_frame_sp = NULL;
11235
      }
11236
      it2.Advance();
11237
    }
11238
  }
11239

    
11240
  // Now advance to the arguments adapter frame (if any). It contains all
11241
  // the provided parameters whereas the function frame always have the number
11242
  // of arguments matching the functions parameters. The rest of the
11243
  // information (except for what is collected above) is the same.
11244
  if ((inlined_jsframe_index == 0) && it.frame()->has_adapted_arguments()) {
11245
    it.AdvanceToArgumentsFrame();
11246
    frame_inspector.SetArgumentsFrame(it.frame());
11247
  }
11248

    
11249
  // Find the number of arguments to fill. At least fill the number of
11250
  // parameters for the function and fill more if more parameters are provided.
11251
  int argument_count = scope_info->ParameterCount();
11252
  if (argument_count < frame_inspector.GetParametersCount()) {
11253
    argument_count = frame_inspector.GetParametersCount();
11254
  }
11255

    
11256
  // Calculate the size of the result.
11257
  int details_size = kFrameDetailsFirstDynamicIndex +
11258
                     2 * (argument_count + scope_info->LocalCount()) +
11259
                     (at_return ? 1 : 0);
11260
  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
11261

    
11262
  // Add the frame id.
11263
  details->set(kFrameDetailsFrameIdIndex, *frame_id);
11264

    
11265
  // Add the function (same as in function frame).
11266
  details->set(kFrameDetailsFunctionIndex, frame_inspector.GetFunction());
11267

    
11268
  // Add the arguments count.
11269
  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
11270

    
11271
  // Add the locals count
11272
  details->set(kFrameDetailsLocalCountIndex,
11273
               Smi::FromInt(scope_info->LocalCount()));
11274

    
11275
  // Add the source position.
11276
  if (position != RelocInfo::kNoPosition) {
11277
    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
11278
  } else {
11279
    details->set(kFrameDetailsSourcePositionIndex, heap->undefined_value());
11280
  }
11281

    
11282
  // Add the constructor information.
11283
  details->set(kFrameDetailsConstructCallIndex, heap->ToBoolean(constructor));
11284

    
11285
  // Add the at return information.
11286
  details->set(kFrameDetailsAtReturnIndex, heap->ToBoolean(at_return));
11287

    
11288
  // Add flags to indicate information on whether this frame is
11289
  //   bit 0: invoked in the debugger context.
11290
  //   bit 1: optimized frame.
11291
  //   bit 2: inlined in optimized frame
11292
  int flags = 0;
11293
  if (*save->context() == *isolate->debug()->debug_context()) {
11294
    flags |= 1 << 0;
11295
  }
11296
  if (is_optimized) {
11297
    flags |= 1 << 1;
11298
    flags |= inlined_jsframe_index << 2;
11299
  }
11300
  details->set(kFrameDetailsFlagsIndex, Smi::FromInt(flags));
11301

    
11302
  // Fill the dynamic part.
11303
  int details_index = kFrameDetailsFirstDynamicIndex;
11304

    
11305
  // Add arguments name and value.
11306
  for (int i = 0; i < argument_count; i++) {
11307
    // Name of the argument.
11308
    if (i < scope_info->ParameterCount()) {
11309
      details->set(details_index++, scope_info->ParameterName(i));
11310
    } else {
11311
      details->set(details_index++, heap->undefined_value());
11312
    }
11313

    
11314
    // Parameter value.
11315
    if (i < frame_inspector.GetParametersCount()) {
11316
      // Get the value from the stack.
11317
      details->set(details_index++, frame_inspector.GetParameter(i));
11318
    } else {
11319
      details->set(details_index++, heap->undefined_value());
11320
    }
11321
  }
11322

    
11323
  // Add locals name and value from the temporary copy from the function frame.
11324
  for (int i = 0; i < scope_info->LocalCount() * 2; i++) {
11325
    details->set(details_index++, locals->get(i));
11326
  }
11327

    
11328
  // Add the value being returned.
11329
  if (at_return) {
11330
    details->set(details_index++, *return_value);
11331
  }
11332

    
11333
  // Add the receiver (same as in function frame).
11334
  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
11335
  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
11336
  Handle<Object> receiver(it.frame()->receiver(), isolate);
11337
  if (!receiver->IsJSObject() &&
11338
      shared->is_classic_mode() &&
11339
      !function->IsBuiltin()) {
11340
    // If the receiver is not a JSObject and the function is not a
11341
    // builtin or strict-mode we have hit an optimization where a
11342
    // value object is not converted into a wrapped JS objects. To
11343
    // hide this optimization from the debugger, we wrap the receiver
11344
    // by creating correct wrapper object based on the calling frame's
11345
    // native context.
11346
    it.Advance();
11347
    Handle<Context> calling_frames_native_context(
11348
        Context::cast(Context::cast(it.frame()->context())->native_context()));
11349
    ASSERT(!receiver->IsUndefined() && !receiver->IsNull());
11350
    receiver =
11351
        isolate->factory()->ToObject(receiver, calling_frames_native_context);
11352
  }
11353
  details->set(kFrameDetailsReceiverIndex, *receiver);
11354

    
11355
  ASSERT_EQ(details_size, details_index);
11356
  return *isolate->factory()->NewJSArrayWithElements(details);
11357
}
11358

    
11359

    
11360
// Create a plain JSObject which materializes the local scope for the specified
11361
// frame.
11362
static Handle<JSObject> MaterializeStackLocalsWithFrameInspector(
11363
    Isolate* isolate,
11364
    Handle<JSObject> target,
11365
    Handle<JSFunction> function,
11366
    FrameInspector* frame_inspector) {
11367
  Handle<SharedFunctionInfo> shared(function->shared());
11368
  Handle<ScopeInfo> scope_info(shared->scope_info());
11369

    
11370
  // First fill all parameters.
11371
  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11372
    Handle<Object> value(i < frame_inspector->GetParametersCount()
11373
                             ? frame_inspector->GetParameter(i)
11374
                             : isolate->heap()->undefined_value(),
11375
                         isolate);
11376
    ASSERT(!value->IsTheHole());
11377

    
11378
    RETURN_IF_EMPTY_HANDLE_VALUE(
11379
        isolate,
11380
        SetProperty(isolate,
11381
                    target,
11382
                    Handle<String>(scope_info->ParameterName(i)),
11383
                    value,
11384
                    NONE,
11385
                    kNonStrictMode),
11386
        Handle<JSObject>());
11387
  }
11388

    
11389
  // Second fill all stack locals.
11390
  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11391
    Handle<Object> value(frame_inspector->GetExpression(i), isolate);
11392
    if (value->IsTheHole()) continue;
11393

    
11394
    RETURN_IF_EMPTY_HANDLE_VALUE(
11395
        isolate,
11396
        SetProperty(isolate,
11397
                    target,
11398
                    Handle<String>(scope_info->StackLocalName(i)),
11399
                    value,
11400
                    NONE,
11401
                    kNonStrictMode),
11402
        Handle<JSObject>());
11403
  }
11404

    
11405
  return target;
11406
}
11407

    
11408

    
11409
static void UpdateStackLocalsFromMaterializedObject(Isolate* isolate,
11410
                                                    Handle<JSObject> target,
11411
                                                    Handle<JSFunction> function,
11412
                                                    JavaScriptFrame* frame,
11413
                                                    int inlined_jsframe_index) {
11414
  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11415
    // Optimized frames are not supported.
11416
    // TODO(yangguo): make sure all code deoptimized when debugger is active
11417
    //                and assert that this cannot happen.
11418
    return;
11419
  }
11420

    
11421
  Handle<SharedFunctionInfo> shared(function->shared());
11422
  Handle<ScopeInfo> scope_info(shared->scope_info());
11423

    
11424
  // Parameters.
11425
  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11426
    ASSERT(!frame->GetParameter(i)->IsTheHole());
11427
    HandleScope scope(isolate);
11428
    Handle<Object> value = GetProperty(
11429
        isolate, target, Handle<String>(scope_info->ParameterName(i)));
11430
    frame->SetParameterValue(i, *value);
11431
  }
11432

    
11433
  // Stack locals.
11434
  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11435
    if (frame->GetExpression(i)->IsTheHole()) continue;
11436
    HandleScope scope(isolate);
11437
    Handle<Object> value = GetProperty(
11438
        isolate, target, Handle<String>(scope_info->StackLocalName(i)));
11439
    frame->SetExpression(i, *value);
11440
  }
11441
}
11442

    
11443

    
11444
static Handle<JSObject> MaterializeLocalContext(Isolate* isolate,
11445
                                                Handle<JSObject> target,
11446
                                                Handle<JSFunction> function,
11447
                                                JavaScriptFrame* frame) {
11448
  HandleScope scope(isolate);
11449
  Handle<SharedFunctionInfo> shared(function->shared());
11450
  Handle<ScopeInfo> scope_info(shared->scope_info());
11451

    
11452
  if (!scope_info->HasContext()) return target;
11453

    
11454
  // Third fill all context locals.
11455
  Handle<Context> frame_context(Context::cast(frame->context()));
11456
  Handle<Context> function_context(frame_context->declaration_context());
11457
  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11458
          scope_info, function_context, target)) {
11459
    return Handle<JSObject>();
11460
  }
11461

    
11462
  // Finally copy any properties from the function context extension.
11463
  // These will be variables introduced by eval.
11464
  if (function_context->closure() == *function) {
11465
    if (function_context->has_extension() &&
11466
        !function_context->IsNativeContext()) {
11467
      Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11468
      bool threw = false;
11469
      Handle<FixedArray> keys =
11470
          GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11471
      if (threw) return Handle<JSObject>();
11472

    
11473
      for (int i = 0; i < keys->length(); i++) {
11474
        // Names of variables introduced by eval are strings.
11475
        ASSERT(keys->get(i)->IsString());
11476
        Handle<String> key(String::cast(keys->get(i)));
11477
        RETURN_IF_EMPTY_HANDLE_VALUE(
11478
            isolate,
11479
            SetProperty(isolate,
11480
                        target,
11481
                        key,
11482
                        GetProperty(isolate, ext, key),
11483
                        NONE,
11484
                        kNonStrictMode),
11485
            Handle<JSObject>());
11486
      }
11487
    }
11488
  }
11489

    
11490
  return target;
11491
}
11492

    
11493

    
11494
static Handle<JSObject> MaterializeLocalScope(
11495
    Isolate* isolate,
11496
    JavaScriptFrame* frame,
11497
    int inlined_jsframe_index) {
11498
  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
11499
  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
11500

    
11501
  Handle<JSObject> local_scope =
11502
      isolate->factory()->NewJSObject(isolate->object_function());
11503
  local_scope = MaterializeStackLocalsWithFrameInspector(
11504
                    isolate, local_scope, function, &frame_inspector);
11505
  RETURN_IF_EMPTY_HANDLE_VALUE(isolate, local_scope, Handle<JSObject>());
11506

    
11507
  return MaterializeLocalContext(isolate, local_scope, function, frame);
11508
}
11509

    
11510

    
11511
// Set the context local variable value.
11512
static bool SetContextLocalValue(Isolate* isolate,
11513
                                 Handle<ScopeInfo> scope_info,
11514
                                 Handle<Context> context,
11515
                                 Handle<String> variable_name,
11516
                                 Handle<Object> new_value) {
11517
  for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
11518
    Handle<String> next_name(scope_info->ContextLocalName(i));
11519
    if (variable_name->Equals(*next_name)) {
11520
      VariableMode mode;
11521
      InitializationFlag init_flag;
11522
      int context_index =
11523
          scope_info->ContextSlotIndex(*next_name, &mode, &init_flag);
11524
      context->set(context_index, *new_value);
11525
      return true;
11526
    }
11527
  }
11528

    
11529
  return false;
11530
}
11531

    
11532

    
11533
static bool SetLocalVariableValue(Isolate* isolate,
11534
                                  JavaScriptFrame* frame,
11535
                                  int inlined_jsframe_index,
11536
                                  Handle<String> variable_name,
11537
                                  Handle<Object> new_value) {
11538
  if (inlined_jsframe_index != 0 || frame->is_optimized()) {
11539
    // Optimized frames are not supported.
11540
    return false;
11541
  }
11542

    
11543
  Handle<JSFunction> function(frame->function());
11544
  Handle<SharedFunctionInfo> shared(function->shared());
11545
  Handle<ScopeInfo> scope_info(shared->scope_info());
11546

    
11547
  bool default_result = false;
11548

    
11549
  // Parameters.
11550
  for (int i = 0; i < scope_info->ParameterCount(); ++i) {
11551
    if (scope_info->ParameterName(i)->Equals(*variable_name)) {
11552
      frame->SetParameterValue(i, *new_value);
11553
      // Argument might be shadowed in heap context, don't stop here.
11554
      default_result = true;
11555
    }
11556
  }
11557

    
11558
  // Stack locals.
11559
  for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
11560
    if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
11561
      frame->SetExpression(i, *new_value);
11562
      return true;
11563
    }
11564
  }
11565

    
11566
  if (scope_info->HasContext()) {
11567
    // Context locals.
11568
    Handle<Context> frame_context(Context::cast(frame->context()));
11569
    Handle<Context> function_context(frame_context->declaration_context());
11570
    if (SetContextLocalValue(
11571
        isolate, scope_info, function_context, variable_name, new_value)) {
11572
      return true;
11573
    }
11574

    
11575
    // Function context extension. These are variables introduced by eval.
11576
    if (function_context->closure() == *function) {
11577
      if (function_context->has_extension() &&
11578
          !function_context->IsNativeContext()) {
11579
        Handle<JSObject> ext(JSObject::cast(function_context->extension()));
11580

    
11581
        if (JSReceiver::HasProperty(ext, variable_name)) {
11582
          // We don't expect this to do anything except replacing
11583
          // property value.
11584
          SetProperty(isolate,
11585
                      ext,
11586
                      variable_name,
11587
                      new_value,
11588
                      NONE,
11589
                      kNonStrictMode);
11590
          return true;
11591
        }
11592
      }
11593
    }
11594
  }
11595

    
11596
  return default_result;
11597
}
11598

    
11599

    
11600
// Create a plain JSObject which materializes the closure content for the
11601
// context.
11602
static Handle<JSObject> MaterializeClosure(Isolate* isolate,
11603
                                           Handle<Context> context) {
11604
  ASSERT(context->IsFunctionContext());
11605

    
11606
  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11607
  Handle<ScopeInfo> scope_info(shared->scope_info());
11608

    
11609
  // Allocate and initialize a JSObject with all the content of this function
11610
  // closure.
11611
  Handle<JSObject> closure_scope =
11612
      isolate->factory()->NewJSObject(isolate->object_function());
11613

    
11614
  // Fill all context locals to the context extension.
11615
  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11616
          scope_info, context, closure_scope)) {
11617
    return Handle<JSObject>();
11618
  }
11619

    
11620
  // Finally copy any properties from the function context extension. This will
11621
  // be variables introduced by eval.
11622
  if (context->has_extension()) {
11623
    Handle<JSObject> ext(JSObject::cast(context->extension()));
11624
    bool threw = false;
11625
    Handle<FixedArray> keys =
11626
        GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS, &threw);
11627
    if (threw) return Handle<JSObject>();
11628

    
11629
    for (int i = 0; i < keys->length(); i++) {
11630
      // Names of variables introduced by eval are strings.
11631
      ASSERT(keys->get(i)->IsString());
11632
      Handle<String> key(String::cast(keys->get(i)));
11633
       RETURN_IF_EMPTY_HANDLE_VALUE(
11634
          isolate,
11635
          SetProperty(isolate,
11636
                      closure_scope,
11637
                      key,
11638
                      GetProperty(isolate, ext, key),
11639
                      NONE,
11640
                      kNonStrictMode),
11641
          Handle<JSObject>());
11642
    }
11643
  }
11644

    
11645
  return closure_scope;
11646
}
11647

    
11648

    
11649
// This method copies structure of MaterializeClosure method above.
11650
static bool SetClosureVariableValue(Isolate* isolate,
11651
                                    Handle<Context> context,
11652
                                    Handle<String> variable_name,
11653
                                    Handle<Object> new_value) {
11654
  ASSERT(context->IsFunctionContext());
11655

    
11656
  Handle<SharedFunctionInfo> shared(context->closure()->shared());
11657
  Handle<ScopeInfo> scope_info(shared->scope_info());
11658

    
11659
  // Context locals to the context extension.
11660
  if (SetContextLocalValue(
11661
          isolate, scope_info, context, variable_name, new_value)) {
11662
    return true;
11663
  }
11664

    
11665
  // Properties from the function context extension. This will
11666
  // be variables introduced by eval.
11667
  if (context->has_extension()) {
11668
    Handle<JSObject> ext(JSObject::cast(context->extension()));
11669
    if (JSReceiver::HasProperty(ext, variable_name)) {
11670
      // We don't expect this to do anything except replacing property value.
11671
      SetProperty(isolate,
11672
                  ext,
11673
                  variable_name,
11674
                  new_value,
11675
                  NONE,
11676
                  kNonStrictMode);
11677
      return true;
11678
    }
11679
  }
11680

    
11681
  return false;
11682
}
11683

    
11684

    
11685
// Create a plain JSObject which materializes the scope for the specified
11686
// catch context.
11687
static Handle<JSObject> MaterializeCatchScope(Isolate* isolate,
11688
                                              Handle<Context> context) {
11689
  ASSERT(context->IsCatchContext());
11690
  Handle<String> name(String::cast(context->extension()));
11691
  Handle<Object> thrown_object(context->get(Context::THROWN_OBJECT_INDEX),
11692
                               isolate);
11693
  Handle<JSObject> catch_scope =
11694
      isolate->factory()->NewJSObject(isolate->object_function());
11695
  RETURN_IF_EMPTY_HANDLE_VALUE(
11696
      isolate,
11697
      SetProperty(isolate,
11698
                  catch_scope,
11699
                  name,
11700
                  thrown_object,
11701
                  NONE,
11702
                  kNonStrictMode),
11703
      Handle<JSObject>());
11704
  return catch_scope;
11705
}
11706

    
11707

    
11708
static bool SetCatchVariableValue(Isolate* isolate,
11709
                                  Handle<Context> context,
11710
                                  Handle<String> variable_name,
11711
                                  Handle<Object> new_value) {
11712
  ASSERT(context->IsCatchContext());
11713
  Handle<String> name(String::cast(context->extension()));
11714
  if (!name->Equals(*variable_name)) {
11715
    return false;
11716
  }
11717
  context->set(Context::THROWN_OBJECT_INDEX, *new_value);
11718
  return true;
11719
}
11720

    
11721

    
11722
// Create a plain JSObject which materializes the block scope for the specified
11723
// block context.
11724
static Handle<JSObject> MaterializeBlockScope(
11725
    Isolate* isolate,
11726
    Handle<Context> context) {
11727
  ASSERT(context->IsBlockContext());
11728
  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11729

    
11730
  // Allocate and initialize a JSObject with all the arguments, stack locals
11731
  // heap locals and extension properties of the debugged function.
11732
  Handle<JSObject> block_scope =
11733
      isolate->factory()->NewJSObject(isolate->object_function());
11734

    
11735
  // Fill all context locals.
11736
  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11737
          scope_info, context, block_scope)) {
11738
    return Handle<JSObject>();
11739
  }
11740

    
11741
  return block_scope;
11742
}
11743

    
11744

    
11745
// Create a plain JSObject which materializes the module scope for the specified
11746
// module context.
11747
static Handle<JSObject> MaterializeModuleScope(
11748
    Isolate* isolate,
11749
    Handle<Context> context) {
11750
  ASSERT(context->IsModuleContext());
11751
  Handle<ScopeInfo> scope_info(ScopeInfo::cast(context->extension()));
11752

    
11753
  // Allocate and initialize a JSObject with all the members of the debugged
11754
  // module.
11755
  Handle<JSObject> module_scope =
11756
      isolate->factory()->NewJSObject(isolate->object_function());
11757

    
11758
  // Fill all context locals.
11759
  if (!ScopeInfo::CopyContextLocalsToScopeObject(
11760
          scope_info, context, module_scope)) {
11761
    return Handle<JSObject>();
11762
  }
11763

    
11764
  return module_scope;
11765
}
11766

    
11767

    
11768
// Iterate over the actual scopes visible from a stack frame or from a closure.
11769
// The iteration proceeds from the innermost visible nested scope outwards.
11770
// All scopes are backed by an actual context except the local scope,
11771
// which is inserted "artificially" in the context chain.
11772
class ScopeIterator {
11773
 public:
11774
  enum ScopeType {
11775
    ScopeTypeGlobal = 0,
11776
    ScopeTypeLocal,
11777
    ScopeTypeWith,
11778
    ScopeTypeClosure,
11779
    ScopeTypeCatch,
11780
    ScopeTypeBlock,
11781
    ScopeTypeModule
11782
  };
11783

    
11784
  ScopeIterator(Isolate* isolate,
11785
                JavaScriptFrame* frame,
11786
                int inlined_jsframe_index)
11787
    : isolate_(isolate),
11788
      frame_(frame),
11789
      inlined_jsframe_index_(inlined_jsframe_index),
11790
      function_(frame->function()),
11791
      context_(Context::cast(frame->context())),
11792
      nested_scope_chain_(4),
11793
      failed_(false) {
11794

    
11795
    // Catch the case when the debugger stops in an internal function.
11796
    Handle<SharedFunctionInfo> shared_info(function_->shared());
11797
    Handle<ScopeInfo> scope_info(shared_info->scope_info());
11798
    if (shared_info->script() == isolate->heap()->undefined_value()) {
11799
      while (context_->closure() == *function_) {
11800
        context_ = Handle<Context>(context_->previous(), isolate_);
11801
      }
11802
      return;
11803
    }
11804

    
11805
    // Get the debug info (create it if it does not exist).
11806
    if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
11807
      // Return if ensuring debug info failed.
11808
      return;
11809
    }
11810
    Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared_info);
11811

    
11812
    // Find the break point where execution has stopped.
11813
    BreakLocationIterator break_location_iterator(debug_info,
11814
                                                  ALL_BREAK_LOCATIONS);
11815
    // pc points to the instruction after the current one, possibly a break
11816
    // location as well. So the "- 1" to exclude it from the search.
11817
    break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
11818
    if (break_location_iterator.IsExit()) {
11819
      // We are within the return sequence. At the momemt it is not possible to
11820
      // get a source position which is consistent with the current scope chain.
11821
      // Thus all nested with, catch and block contexts are skipped and we only
11822
      // provide the function scope.
11823
      if (scope_info->HasContext()) {
11824
        context_ = Handle<Context>(context_->declaration_context(), isolate_);
11825
      } else {
11826
        while (context_->closure() == *function_) {
11827
          context_ = Handle<Context>(context_->previous(), isolate_);
11828
        }
11829
      }
11830
      if (scope_info->scope_type() != EVAL_SCOPE) {
11831
        nested_scope_chain_.Add(scope_info);
11832
      }
11833
    } else {
11834
      // Reparse the code and analyze the scopes.
11835
      Handle<Script> script(Script::cast(shared_info->script()));
11836
      Scope* scope = NULL;
11837

    
11838
      // Check whether we are in global, eval or function code.
11839
      Handle<ScopeInfo> scope_info(shared_info->scope_info());
11840
      if (scope_info->scope_type() != FUNCTION_SCOPE) {
11841
        // Global or eval code.
11842
        CompilationInfoWithZone info(script);
11843
        if (scope_info->scope_type() == GLOBAL_SCOPE) {
11844
          info.MarkAsGlobal();
11845
        } else {
11846
          ASSERT(scope_info->scope_type() == EVAL_SCOPE);
11847
          info.MarkAsEval();
11848
          info.SetContext(Handle<Context>(function_->context()));
11849
        }
11850
        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11851
          scope = info.function()->scope();
11852
        }
11853
        RetrieveScopeChain(scope, shared_info);
11854
      } else {
11855
        // Function code
11856
        CompilationInfoWithZone info(shared_info);
11857
        if (Parser::Parse(&info) && Scope::Analyze(&info)) {
11858
          scope = info.function()->scope();
11859
        }
11860
        RetrieveScopeChain(scope, shared_info);
11861
      }
11862
    }
11863
  }
11864

    
11865
  ScopeIterator(Isolate* isolate,
11866
                Handle<JSFunction> function)
11867
    : isolate_(isolate),
11868
      frame_(NULL),
11869
      inlined_jsframe_index_(0),
11870
      function_(function),
11871
      context_(function->context()),
11872
      failed_(false) {
11873
    if (function->IsBuiltin()) {
11874
      context_ = Handle<Context>();
11875
    }
11876
  }
11877

    
11878
  // More scopes?
11879
  bool Done() {
11880
    ASSERT(!failed_);
11881
    return context_.is_null();
11882
  }
11883

    
11884
  bool Failed() { return failed_; }
11885

    
11886
  // Move to the next scope.
11887
  void Next() {
11888
    ASSERT(!failed_);
11889
    ScopeType scope_type = Type();
11890
    if (scope_type == ScopeTypeGlobal) {
11891
      // The global scope is always the last in the chain.
11892
      ASSERT(context_->IsNativeContext());
11893
      context_ = Handle<Context>();
11894
      return;
11895
    }
11896
    if (nested_scope_chain_.is_empty()) {
11897
      context_ = Handle<Context>(context_->previous(), isolate_);
11898
    } else {
11899
      if (nested_scope_chain_.last()->HasContext()) {
11900
        ASSERT(context_->previous() != NULL);
11901
        context_ = Handle<Context>(context_->previous(), isolate_);
11902
      }
11903
      nested_scope_chain_.RemoveLast();
11904
    }
11905
  }
11906

    
11907
  // Return the type of the current scope.
11908
  ScopeType Type() {
11909
    ASSERT(!failed_);
11910
    if (!nested_scope_chain_.is_empty()) {
11911
      Handle<ScopeInfo> scope_info = nested_scope_chain_.last();
11912
      switch (scope_info->scope_type()) {
11913
        case FUNCTION_SCOPE:
11914
          ASSERT(context_->IsFunctionContext() ||
11915
                 !scope_info->HasContext());
11916
          return ScopeTypeLocal;
11917
        case MODULE_SCOPE:
11918
          ASSERT(context_->IsModuleContext());
11919
          return ScopeTypeModule;
11920
        case GLOBAL_SCOPE:
11921
          ASSERT(context_->IsNativeContext());
11922
          return ScopeTypeGlobal;
11923
        case WITH_SCOPE:
11924
          ASSERT(context_->IsWithContext());
11925
          return ScopeTypeWith;
11926
        case CATCH_SCOPE:
11927
          ASSERT(context_->IsCatchContext());
11928
          return ScopeTypeCatch;
11929
        case BLOCK_SCOPE:
11930
          ASSERT(!scope_info->HasContext() ||
11931
                 context_->IsBlockContext());
11932
          return ScopeTypeBlock;
11933
        case EVAL_SCOPE:
11934
          UNREACHABLE();
11935
      }
11936
    }
11937
    if (context_->IsNativeContext()) {
11938
      ASSERT(context_->global_object()->IsGlobalObject());
11939
      return ScopeTypeGlobal;
11940
    }
11941
    if (context_->IsFunctionContext()) {
11942
      return ScopeTypeClosure;
11943
    }
11944
    if (context_->IsCatchContext()) {
11945
      return ScopeTypeCatch;
11946
    }
11947
    if (context_->IsBlockContext()) {
11948
      return ScopeTypeBlock;
11949
    }
11950
    if (context_->IsModuleContext()) {
11951
      return ScopeTypeModule;
11952
    }
11953
    ASSERT(context_->IsWithContext());
11954
    return ScopeTypeWith;
11955
  }
11956

    
11957
  // Return the JavaScript object with the content of the current scope.
11958
  Handle<JSObject> ScopeObject() {
11959
    ASSERT(!failed_);
11960
    switch (Type()) {
11961
      case ScopeIterator::ScopeTypeGlobal:
11962
        return Handle<JSObject>(CurrentContext()->global_object());
11963
      case ScopeIterator::ScopeTypeLocal:
11964
        // Materialize the content of the local scope into a JSObject.
11965
        ASSERT(nested_scope_chain_.length() == 1);
11966
        return MaterializeLocalScope(isolate_, frame_, inlined_jsframe_index_);
11967
      case ScopeIterator::ScopeTypeWith:
11968
        // Return the with object.
11969
        return Handle<JSObject>(JSObject::cast(CurrentContext()->extension()));
11970
      case ScopeIterator::ScopeTypeCatch:
11971
        return MaterializeCatchScope(isolate_, CurrentContext());
11972
      case ScopeIterator::ScopeTypeClosure:
11973
        // Materialize the content of the closure scope into a JSObject.
11974
        return MaterializeClosure(isolate_, CurrentContext());
11975
      case ScopeIterator::ScopeTypeBlock:
11976
        return MaterializeBlockScope(isolate_, CurrentContext());
11977
      case ScopeIterator::ScopeTypeModule:
11978
        return MaterializeModuleScope(isolate_, CurrentContext());
11979
    }
11980
    UNREACHABLE();
11981
    return Handle<JSObject>();
11982
  }
11983

    
11984
  bool SetVariableValue(Handle<String> variable_name,
11985
                        Handle<Object> new_value) {
11986
    ASSERT(!failed_);
11987
    switch (Type()) {
11988
      case ScopeIterator::ScopeTypeGlobal:
11989
        break;
11990
      case ScopeIterator::ScopeTypeLocal:
11991
        return SetLocalVariableValue(isolate_, frame_, inlined_jsframe_index_,
11992
            variable_name, new_value);
11993
      case ScopeIterator::ScopeTypeWith:
11994
        break;
11995
      case ScopeIterator::ScopeTypeCatch:
11996
        return SetCatchVariableValue(isolate_, CurrentContext(),
11997
            variable_name, new_value);
11998
      case ScopeIterator::ScopeTypeClosure:
11999
        return SetClosureVariableValue(isolate_, CurrentContext(),
12000
            variable_name, new_value);
12001
      case ScopeIterator::ScopeTypeBlock:
12002
        // TODO(2399): should we implement it?
12003
        break;
12004
      case ScopeIterator::ScopeTypeModule:
12005
        // TODO(2399): should we implement it?
12006
        break;
12007
    }
12008
    return false;
12009
  }
12010

    
12011
  Handle<ScopeInfo> CurrentScopeInfo() {
12012
    ASSERT(!failed_);
12013
    if (!nested_scope_chain_.is_empty()) {
12014
      return nested_scope_chain_.last();
12015
    } else if (context_->IsBlockContext()) {
12016
      return Handle<ScopeInfo>(ScopeInfo::cast(context_->extension()));
12017
    } else if (context_->IsFunctionContext()) {
12018
      return Handle<ScopeInfo>(context_->closure()->shared()->scope_info());
12019
    }
12020
    return Handle<ScopeInfo>::null();
12021
  }
12022

    
12023
  // Return the context for this scope. For the local context there might not
12024
  // be an actual context.
12025
  Handle<Context> CurrentContext() {
12026
    ASSERT(!failed_);
12027
    if (Type() == ScopeTypeGlobal ||
12028
        nested_scope_chain_.is_empty()) {
12029
      return context_;
12030
    } else if (nested_scope_chain_.last()->HasContext()) {
12031
      return context_;
12032
    } else {
12033
      return Handle<Context>();
12034
    }
12035
  }
12036

    
12037
#ifdef DEBUG
12038
  // Debug print of the content of the current scope.
12039
  void DebugPrint() {
12040
    ASSERT(!failed_);
12041
    switch (Type()) {
12042
      case ScopeIterator::ScopeTypeGlobal:
12043
        PrintF("Global:\n");
12044
        CurrentContext()->Print();
12045
        break;
12046

    
12047
      case ScopeIterator::ScopeTypeLocal: {
12048
        PrintF("Local:\n");
12049
        function_->shared()->scope_info()->Print();
12050
        if (!CurrentContext().is_null()) {
12051
          CurrentContext()->Print();
12052
          if (CurrentContext()->has_extension()) {
12053
            Handle<Object> extension(CurrentContext()->extension(), isolate_);
12054
            if (extension->IsJSContextExtensionObject()) {
12055
              extension->Print();
12056
            }
12057
          }
12058
        }
12059
        break;
12060
      }
12061

    
12062
      case ScopeIterator::ScopeTypeWith:
12063
        PrintF("With:\n");
12064
        CurrentContext()->extension()->Print();
12065
        break;
12066

    
12067
      case ScopeIterator::ScopeTypeCatch:
12068
        PrintF("Catch:\n");
12069
        CurrentContext()->extension()->Print();
12070
        CurrentContext()->get(Context::THROWN_OBJECT_INDEX)->Print();
12071
        break;
12072

    
12073
      case ScopeIterator::ScopeTypeClosure:
12074
        PrintF("Closure:\n");
12075
        CurrentContext()->Print();
12076
        if (CurrentContext()->has_extension()) {
12077
          Handle<Object> extension(CurrentContext()->extension(), isolate_);
12078
          if (extension->IsJSContextExtensionObject()) {
12079
            extension->Print();
12080
          }
12081
        }
12082
        break;
12083

    
12084
      default:
12085
        UNREACHABLE();
12086
    }
12087
    PrintF("\n");
12088
  }
12089
#endif
12090

    
12091
 private:
12092
  Isolate* isolate_;
12093
  JavaScriptFrame* frame_;
12094
  int inlined_jsframe_index_;
12095
  Handle<JSFunction> function_;
12096
  Handle<Context> context_;
12097
  List<Handle<ScopeInfo> > nested_scope_chain_;
12098
  bool failed_;
12099

    
12100
  void RetrieveScopeChain(Scope* scope,
12101
                          Handle<SharedFunctionInfo> shared_info) {
12102
    if (scope != NULL) {
12103
      int source_position = shared_info->code()->SourcePosition(frame_->pc());
12104
      scope->GetNestedScopeChain(&nested_scope_chain_, source_position);
12105
    } else {
12106
      // A failed reparse indicates that the preparser has diverged from the
12107
      // parser or that the preparse data given to the initial parse has been
12108
      // faulty. We fail in debug mode but in release mode we only provide the
12109
      // information we get from the context chain but nothing about
12110
      // completely stack allocated scopes or stack allocated locals.
12111
      // Or it could be due to stack overflow.
12112
      ASSERT(isolate_->has_pending_exception());
12113
      failed_ = true;
12114
    }
12115
  }
12116

    
12117
  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeIterator);
12118
};
12119

    
12120

    
12121
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeCount) {
12122
  HandleScope scope(isolate);
12123
  ASSERT(args.length() == 2);
12124

    
12125
  // Check arguments.
12126
  Object* check;
12127
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12128
      RUNTIME_ARGUMENTS(isolate, args));
12129
    if (!maybe_check->ToObject(&check)) return maybe_check;
12130
  }
12131
  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12132

    
12133
  // Get the frame where the debugging is performed.
12134
  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12135
  JavaScriptFrameIterator it(isolate, id);
12136
  JavaScriptFrame* frame = it.frame();
12137

    
12138
  // Count the visible scopes.
12139
  int n = 0;
12140
  for (ScopeIterator it(isolate, frame, 0);
12141
       !it.Done();
12142
       it.Next()) {
12143
    n++;
12144
  }
12145

    
12146
  return Smi::FromInt(n);
12147
}
12148

    
12149

    
12150
// Returns the list of step-in positions (text offset) in a function of the
12151
// stack frame in a range from the current debug break position to the end
12152
// of the corresponding statement.
12153
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetStepInPositions) {
12154
  HandleScope scope(isolate);
12155
  ASSERT(args.length() == 2);
12156

    
12157
  // Check arguments.
12158
  Object* check;
12159
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12160
      RUNTIME_ARGUMENTS(isolate, args));
12161
    if (!maybe_check->ToObject(&check)) return maybe_check;
12162
  }
12163
  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12164

    
12165
  // Get the frame where the debugging is performed.
12166
  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12167
  JavaScriptFrameIterator frame_it(isolate, id);
12168
  RUNTIME_ASSERT(!frame_it.done());
12169

    
12170
  JavaScriptFrame* frame = frame_it.frame();
12171

    
12172
  Handle<JSFunction> fun =
12173
      Handle<JSFunction>(frame->function());
12174
  Handle<SharedFunctionInfo> shared =
12175
      Handle<SharedFunctionInfo>(fun->shared());
12176

    
12177
  if (!isolate->debug()->EnsureDebugInfo(shared, fun)) {
12178
    return isolate->heap()->undefined_value();
12179
  }
12180

    
12181
  Handle<DebugInfo> debug_info = Debug::GetDebugInfo(shared);
12182

    
12183
  int len = 0;
12184
  Handle<JSArray> array(isolate->factory()->NewJSArray(10));
12185
  // Find the break point where execution has stopped.
12186
  BreakLocationIterator break_location_iterator(debug_info,
12187
                                                ALL_BREAK_LOCATIONS);
12188

    
12189
  break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
12190
  int current_statement_pos = break_location_iterator.statement_position();
12191

    
12192
  while (!break_location_iterator.Done()) {
12193
    bool accept;
12194
    if (break_location_iterator.pc() > frame->pc()) {
12195
      accept = true;
12196
    } else {
12197
      StackFrame::Id break_frame_id = isolate->debug()->break_frame_id();
12198
      // The break point is near our pc. Could be a step-in possibility,
12199
      // that is currently taken by active debugger call.
12200
      if (break_frame_id == StackFrame::NO_ID) {
12201
        // We are not stepping.
12202
        accept = false;
12203
      } else {
12204
        JavaScriptFrameIterator additional_frame_it(isolate, break_frame_id);
12205
        // If our frame is a top frame and we are stepping, we can do step-in
12206
        // at this place.
12207
        accept = additional_frame_it.frame()->id() == id;
12208
      }
12209
    }
12210
    if (accept) {
12211
      if (break_location_iterator.IsStepInLocation(isolate)) {
12212
        Smi* position_value = Smi::FromInt(break_location_iterator.position());
12213
        JSObject::SetElement(array, len,
12214
            Handle<Object>(position_value, isolate),
12215
            NONE, kNonStrictMode);
12216
        len++;
12217
      }
12218
    }
12219
    // Advance iterator.
12220
    break_location_iterator.Next();
12221
    if (current_statement_pos !=
12222
        break_location_iterator.statement_position()) {
12223
      break;
12224
    }
12225
  }
12226
  return *array;
12227
}
12228

    
12229

    
12230
static const int kScopeDetailsTypeIndex = 0;
12231
static const int kScopeDetailsObjectIndex = 1;
12232
static const int kScopeDetailsSize = 2;
12233

    
12234

    
12235
static MaybeObject* MaterializeScopeDetails(Isolate* isolate,
12236
    ScopeIterator* it) {
12237
  // Calculate the size of the result.
12238
  int details_size = kScopeDetailsSize;
12239
  Handle<FixedArray> details = isolate->factory()->NewFixedArray(details_size);
12240

    
12241
  // Fill in scope details.
12242
  details->set(kScopeDetailsTypeIndex, Smi::FromInt(it->Type()));
12243
  Handle<JSObject> scope_object = it->ScopeObject();
12244
  RETURN_IF_EMPTY_HANDLE(isolate, scope_object);
12245
  details->set(kScopeDetailsObjectIndex, *scope_object);
12246

    
12247
  return *isolate->factory()->NewJSArrayWithElements(details);
12248
}
12249

    
12250

    
12251
// Return an array with scope details
12252
// args[0]: number: break id
12253
// args[1]: number: frame index
12254
// args[2]: number: inlined frame index
12255
// args[3]: number: scope index
12256
//
12257
// The array returned contains the following information:
12258
// 0: Scope type
12259
// 1: Scope object
12260
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScopeDetails) {
12261
  HandleScope scope(isolate);
12262
  ASSERT(args.length() == 4);
12263

    
12264
  // Check arguments.
12265
  Object* check;
12266
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12267
      RUNTIME_ARGUMENTS(isolate, args));
12268
    if (!maybe_check->ToObject(&check)) return maybe_check;
12269
  }
12270
  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12271
  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12272
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12273

    
12274
  // Get the frame where the debugging is performed.
12275
  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12276
  JavaScriptFrameIterator frame_it(isolate, id);
12277
  JavaScriptFrame* frame = frame_it.frame();
12278

    
12279
  // Find the requested scope.
12280
  int n = 0;
12281
  ScopeIterator it(isolate, frame, inlined_jsframe_index);
12282
  for (; !it.Done() && n < index; it.Next()) {
12283
    n++;
12284
  }
12285
  if (it.Done()) {
12286
    return isolate->heap()->undefined_value();
12287
  }
12288
  return MaterializeScopeDetails(isolate, &it);
12289
}
12290

    
12291

    
12292
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeCount) {
12293
  HandleScope scope(isolate);
12294
  ASSERT(args.length() == 1);
12295

    
12296
  // Check arguments.
12297
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12298

    
12299
  // Count the visible scopes.
12300
  int n = 0;
12301
  for (ScopeIterator it(isolate, fun); !it.Done(); it.Next()) {
12302
    n++;
12303
  }
12304

    
12305
  return Smi::FromInt(n);
12306
}
12307

    
12308

    
12309
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionScopeDetails) {
12310
  HandleScope scope(isolate);
12311
  ASSERT(args.length() == 2);
12312

    
12313
  // Check arguments.
12314
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12315
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12316

    
12317
  // Find the requested scope.
12318
  int n = 0;
12319
  ScopeIterator it(isolate, fun);
12320
  for (; !it.Done() && n < index; it.Next()) {
12321
    n++;
12322
  }
12323
  if (it.Done()) {
12324
    return isolate->heap()->undefined_value();
12325
  }
12326

    
12327
  return MaterializeScopeDetails(isolate, &it);
12328
}
12329

    
12330

    
12331
static bool SetScopeVariableValue(ScopeIterator* it, int index,
12332
                                  Handle<String> variable_name,
12333
                                  Handle<Object> new_value) {
12334
  for (int n = 0; !it->Done() && n < index; it->Next()) {
12335
    n++;
12336
  }
12337
  if (it->Done()) {
12338
    return false;
12339
  }
12340
  return it->SetVariableValue(variable_name, new_value);
12341
}
12342

    
12343

    
12344
// Change variable value in closure or local scope
12345
// args[0]: number or JsFunction: break id or function
12346
// args[1]: number: frame index (when arg[0] is break id)
12347
// args[2]: number: inlined frame index (when arg[0] is break id)
12348
// args[3]: number: scope index
12349
// args[4]: string: variable name
12350
// args[5]: object: new value
12351
//
12352
// Return true if success and false otherwise
12353
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScopeVariableValue) {
12354
  HandleScope scope(isolate);
12355
  ASSERT(args.length() == 6);
12356

    
12357
  // Check arguments.
12358
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[3]);
12359
  CONVERT_ARG_HANDLE_CHECKED(String, variable_name, 4);
12360
  Handle<Object> new_value = args.at<Object>(5);
12361

    
12362
  bool res;
12363
  if (args[0]->IsNumber()) {
12364
    Object* check;
12365
    { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12366
        RUNTIME_ARGUMENTS(isolate, args));
12367
      if (!maybe_check->ToObject(&check)) return maybe_check;
12368
    }
12369
    CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12370
    CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12371

    
12372
    // Get the frame where the debugging is performed.
12373
    StackFrame::Id id = UnwrapFrameId(wrapped_id);
12374
    JavaScriptFrameIterator frame_it(isolate, id);
12375
    JavaScriptFrame* frame = frame_it.frame();
12376

    
12377
    ScopeIterator it(isolate, frame, inlined_jsframe_index);
12378
    res = SetScopeVariableValue(&it, index, variable_name, new_value);
12379
  } else {
12380
    CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12381
    ScopeIterator it(isolate, fun);
12382
    res = SetScopeVariableValue(&it, index, variable_name, new_value);
12383
  }
12384

    
12385
  return isolate->heap()->ToBoolean(res);
12386
}
12387

    
12388

    
12389
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrintScopes) {
12390
  HandleScope scope(isolate);
12391
  ASSERT(args.length() == 0);
12392

    
12393
#ifdef DEBUG
12394
  // Print the scopes for the top frame.
12395
  StackFrameLocator locator(isolate);
12396
  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
12397
  for (ScopeIterator it(isolate, frame, 0);
12398
       !it.Done();
12399
       it.Next()) {
12400
    it.DebugPrint();
12401
  }
12402
#endif
12403
  return isolate->heap()->undefined_value();
12404
}
12405

    
12406

    
12407
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadCount) {
12408
  HandleScope scope(isolate);
12409
  ASSERT(args.length() == 1);
12410

    
12411
  // Check arguments.
12412
  Object* result;
12413
  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12414
      RUNTIME_ARGUMENTS(isolate, args));
12415
    if (!maybe_result->ToObject(&result)) return maybe_result;
12416
  }
12417

    
12418
  // Count all archived V8 threads.
12419
  int n = 0;
12420
  for (ThreadState* thread =
12421
          isolate->thread_manager()->FirstThreadStateInUse();
12422
       thread != NULL;
12423
       thread = thread->Next()) {
12424
    n++;
12425
  }
12426

    
12427
  // Total number of threads is current thread and archived threads.
12428
  return Smi::FromInt(n + 1);
12429
}
12430

    
12431

    
12432
static const int kThreadDetailsCurrentThreadIndex = 0;
12433
static const int kThreadDetailsThreadIdIndex = 1;
12434
static const int kThreadDetailsSize = 2;
12435

    
12436
// Return an array with thread details
12437
// args[0]: number: break id
12438
// args[1]: number: thread index
12439
//
12440
// The array returned contains the following information:
12441
// 0: Is current thread?
12442
// 1: Thread id
12443
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetThreadDetails) {
12444
  HandleScope scope(isolate);
12445
  ASSERT(args.length() == 2);
12446

    
12447
  // Check arguments.
12448
  Object* check;
12449
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12450
      RUNTIME_ARGUMENTS(isolate, args));
12451
    if (!maybe_check->ToObject(&check)) return maybe_check;
12452
  }
12453
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
12454

    
12455
  // Allocate array for result.
12456
  Handle<FixedArray> details =
12457
      isolate->factory()->NewFixedArray(kThreadDetailsSize);
12458

    
12459
  // Thread index 0 is current thread.
12460
  if (index == 0) {
12461
    // Fill the details.
12462
    details->set(kThreadDetailsCurrentThreadIndex,
12463
                 isolate->heap()->true_value());
12464
    details->set(kThreadDetailsThreadIdIndex,
12465
                 Smi::FromInt(ThreadId::Current().ToInteger()));
12466
  } else {
12467
    // Find the thread with the requested index.
12468
    int n = 1;
12469
    ThreadState* thread =
12470
        isolate->thread_manager()->FirstThreadStateInUse();
12471
    while (index != n && thread != NULL) {
12472
      thread = thread->Next();
12473
      n++;
12474
    }
12475
    if (thread == NULL) {
12476
      return isolate->heap()->undefined_value();
12477
    }
12478

    
12479
    // Fill the details.
12480
    details->set(kThreadDetailsCurrentThreadIndex,
12481
                 isolate->heap()->false_value());
12482
    details->set(kThreadDetailsThreadIdIndex,
12483
                 Smi::FromInt(thread->id().ToInteger()));
12484
  }
12485

    
12486
  // Convert to JS array and return.
12487
  return *isolate->factory()->NewJSArrayWithElements(details);
12488
}
12489

    
12490

    
12491
// Sets the disable break state
12492
// args[0]: disable break state
12493
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDisableBreak) {
12494
  HandleScope scope(isolate);
12495
  ASSERT(args.length() == 1);
12496
  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 0);
12497
  isolate->debug()->set_disable_break(disable_break);
12498
  return  isolate->heap()->undefined_value();
12499
}
12500

    
12501

    
12502
static bool IsPositionAlignmentCodeCorrect(int alignment) {
12503
  return alignment == STATEMENT_ALIGNED || alignment == BREAK_POSITION_ALIGNED;
12504
}
12505

    
12506

    
12507
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
12508
  HandleScope scope(isolate);
12509
  ASSERT(args.length() == 2);
12510

    
12511
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
12512
  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[1]);
12513

    
12514
  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12515
    return isolate->ThrowIllegalOperation();
12516
  }
12517
  BreakPositionAlignment alignment =
12518
      static_cast<BreakPositionAlignment>(statement_aligned_code);
12519

    
12520
  Handle<SharedFunctionInfo> shared(fun->shared());
12521
  // Find the number of break points
12522
  Handle<Object> break_locations =
12523
      Debug::GetSourceBreakLocations(shared, alignment);
12524
  if (break_locations->IsUndefined()) return isolate->heap()->undefined_value();
12525
  // Return array as JS array
12526
  return *isolate->factory()->NewJSArrayWithElements(
12527
      Handle<FixedArray>::cast(break_locations));
12528
}
12529

    
12530

    
12531
// Set a break point in a function.
12532
// args[0]: function
12533
// args[1]: number: break source position (within the function source)
12534
// args[2]: number: break point object
12535
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
12536
  HandleScope scope(isolate);
12537
  ASSERT(args.length() == 3);
12538
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
12539
  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12540
  RUNTIME_ASSERT(source_position >= 0);
12541
  Handle<Object> break_point_object_arg = args.at<Object>(2);
12542

    
12543
  // Set break point.
12544
  isolate->debug()->SetBreakPoint(function, break_point_object_arg,
12545
                                  &source_position);
12546

    
12547
  return Smi::FromInt(source_position);
12548
}
12549

    
12550

    
12551
// Changes the state of a break point in a script and returns source position
12552
// where break point was set. NOTE: Regarding performance see the NOTE for
12553
// GetScriptFromScriptData.
12554
// args[0]: script to set break point in
12555
// args[1]: number: break source position (within the script source)
12556
// args[2]: number, breakpoint position alignment
12557
// args[3]: number: break point object
12558
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
12559
  HandleScope scope(isolate);
12560
  ASSERT(args.length() == 4);
12561
  CONVERT_ARG_HANDLE_CHECKED(JSValue, wrapper, 0);
12562
  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
12563
  RUNTIME_ASSERT(source_position >= 0);
12564
  CONVERT_NUMBER_CHECKED(int32_t, statement_aligned_code, Int32, args[2]);
12565
  Handle<Object> break_point_object_arg = args.at<Object>(3);
12566

    
12567
  if (!IsPositionAlignmentCodeCorrect(statement_aligned_code)) {
12568
    return isolate->ThrowIllegalOperation();
12569
  }
12570
  BreakPositionAlignment alignment =
12571
      static_cast<BreakPositionAlignment>(statement_aligned_code);
12572

    
12573
  // Get the script from the script wrapper.
12574
  RUNTIME_ASSERT(wrapper->value()->IsScript());
12575
  Handle<Script> script(Script::cast(wrapper->value()));
12576

    
12577
  // Set break point.
12578
  if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
12579
                                                &source_position,
12580
                                                alignment)) {
12581
    return  isolate->heap()->undefined_value();
12582
  }
12583

    
12584
  return Smi::FromInt(source_position);
12585
}
12586

    
12587

    
12588
// Clear a break point
12589
// args[0]: number: break point object
12590
RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearBreakPoint) {
12591
  HandleScope scope(isolate);
12592
  ASSERT(args.length() == 1);
12593
  Handle<Object> break_point_object_arg = args.at<Object>(0);
12594

    
12595
  // Clear break point.
12596
  isolate->debug()->ClearBreakPoint(break_point_object_arg);
12597

    
12598
  return isolate->heap()->undefined_value();
12599
}
12600

    
12601

    
12602
// Change the state of break on exceptions.
12603
// args[0]: Enum value indicating whether to affect caught/uncaught exceptions.
12604
// args[1]: Boolean indicating on/off.
12605
RUNTIME_FUNCTION(MaybeObject*, Runtime_ChangeBreakOnException) {
12606
  HandleScope scope(isolate);
12607
  ASSERT(args.length() == 2);
12608
  RUNTIME_ASSERT(args[0]->IsNumber());
12609
  CONVERT_BOOLEAN_ARG_CHECKED(enable, 1);
12610

    
12611
  // If the number doesn't match an enum value, the ChangeBreakOnException
12612
  // function will default to affecting caught exceptions.
12613
  ExceptionBreakType type =
12614
      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12615
  // Update break point state.
12616
  isolate->debug()->ChangeBreakOnException(type, enable);
12617
  return isolate->heap()->undefined_value();
12618
}
12619

    
12620

    
12621
// Returns the state of break on exceptions
12622
// args[0]: boolean indicating uncaught exceptions
12623
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsBreakOnException) {
12624
  HandleScope scope(isolate);
12625
  ASSERT(args.length() == 1);
12626
  RUNTIME_ASSERT(args[0]->IsNumber());
12627

    
12628
  ExceptionBreakType type =
12629
      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
12630
  bool result = isolate->debug()->IsBreakOnException(type);
12631
  return Smi::FromInt(result);
12632
}
12633

    
12634

    
12635
// Prepare for stepping
12636
// args[0]: break id for checking execution state
12637
// args[1]: step action from the enumeration StepAction
12638
// args[2]: number of times to perform the step, for step out it is the number
12639
//          of frames to step down.
12640
RUNTIME_FUNCTION(MaybeObject*, Runtime_PrepareStep) {
12641
  HandleScope scope(isolate);
12642
  ASSERT(args.length() == 4);
12643
  // Check arguments.
12644
  Object* check;
12645
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
12646
      RUNTIME_ARGUMENTS(isolate, args));
12647
    if (!maybe_check->ToObject(&check)) return maybe_check;
12648
  }
12649
  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
12650
    return isolate->Throw(isolate->heap()->illegal_argument_string());
12651
  }
12652

    
12653
  CONVERT_NUMBER_CHECKED(int, wrapped_frame_id, Int32, args[3]);
12654

    
12655
  StackFrame::Id frame_id;
12656
  if (wrapped_frame_id == 0) {
12657
    frame_id = StackFrame::NO_ID;
12658
  } else {
12659
    frame_id = UnwrapFrameId(wrapped_frame_id);
12660
  }
12661

    
12662
  // Get the step action and check validity.
12663
  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
12664
  if (step_action != StepIn &&
12665
      step_action != StepNext &&
12666
      step_action != StepOut &&
12667
      step_action != StepInMin &&
12668
      step_action != StepMin) {
12669
    return isolate->Throw(isolate->heap()->illegal_argument_string());
12670
  }
12671

    
12672
  if (frame_id != StackFrame::NO_ID && step_action != StepNext &&
12673
      step_action != StepMin && step_action != StepOut) {
12674
    return isolate->ThrowIllegalOperation();
12675
  }
12676

    
12677
  // Get the number of steps.
12678
  int step_count = NumberToInt32(args[2]);
12679
  if (step_count < 1) {
12680
    return isolate->Throw(isolate->heap()->illegal_argument_string());
12681
  }
12682

    
12683
  // Clear all current stepping setup.
12684
  isolate->debug()->ClearStepping();
12685

    
12686
  // Prepare step.
12687
  isolate->debug()->PrepareStep(static_cast<StepAction>(step_action),
12688
                                step_count,
12689
                                frame_id);
12690
  return isolate->heap()->undefined_value();
12691
}
12692

    
12693

    
12694
// Clear all stepping set by PrepareStep.
12695
RUNTIME_FUNCTION(MaybeObject*, Runtime_ClearStepping) {
12696
  HandleScope scope(isolate);
12697
  ASSERT(args.length() == 0);
12698
  isolate->debug()->ClearStepping();
12699
  return isolate->heap()->undefined_value();
12700
}
12701

    
12702

    
12703
// Helper function to find or create the arguments object for
12704
// Runtime_DebugEvaluate.
12705
static Handle<JSObject> MaterializeArgumentsObject(
12706
    Isolate* isolate,
12707
    Handle<JSObject> target,
12708
    Handle<JSFunction> function) {
12709
  // Do not materialize the arguments object for eval or top-level code.
12710
  // Skip if "arguments" is already taken.
12711
  if (!function->shared()->is_function() ||
12712
      JSReceiver::HasLocalProperty(target,
12713
                                   isolate->factory()->arguments_string())) {
12714
    return target;
12715
  }
12716

    
12717
  // FunctionGetArguments can't throw an exception.
12718
  Handle<JSObject> arguments = Handle<JSObject>::cast(
12719
      Accessors::FunctionGetArguments(function));
12720
  SetProperty(isolate,
12721
              target,
12722
              isolate->factory()->arguments_string(),
12723
              arguments,
12724
              ::NONE,
12725
              kNonStrictMode);
12726
  return target;
12727
}
12728

    
12729

    
12730
// Compile and evaluate source for the given context.
12731
static MaybeObject* DebugEvaluate(Isolate* isolate,
12732
                                  Handle<Context> context,
12733
                                  Handle<Object> context_extension,
12734
                                  Handle<Object> receiver,
12735
                                  Handle<String> source) {
12736
  if (context_extension->IsJSObject()) {
12737
    Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
12738
    Handle<JSFunction> closure(context->closure(), isolate);
12739
    context = isolate->factory()->NewWithContext(closure, context, extension);
12740
  }
12741

    
12742
  Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
12743
      source,
12744
      context,
12745
      context->IsNativeContext(),
12746
      CLASSIC_MODE,
12747
      NO_PARSE_RESTRICTION,
12748
      RelocInfo::kNoPosition);
12749
  RETURN_IF_EMPTY_HANDLE(isolate, shared);
12750

    
12751
  Handle<JSFunction> eval_fun =
12752
      isolate->factory()->NewFunctionFromSharedFunctionInfo(
12753
          shared, context, NOT_TENURED);
12754
  bool pending_exception;
12755
  Handle<Object> result = Execution::Call(
12756
      isolate, eval_fun, receiver, 0, NULL, &pending_exception);
12757

    
12758
  if (pending_exception) return Failure::Exception();
12759

    
12760
  // Skip the global proxy as it has no properties and always delegates to the
12761
  // real global object.
12762
  if (result->IsJSGlobalProxy()) {
12763
    result = Handle<JSObject>(JSObject::cast(result->GetPrototype(isolate)));
12764
  }
12765

    
12766
  // Clear the oneshot breakpoints so that the debugger does not step further.
12767
  isolate->debug()->ClearStepping();
12768
  return *result;
12769
}
12770

    
12771

    
12772
// Evaluate a piece of JavaScript in the context of a stack frame for
12773
// debugging.  Things that need special attention are:
12774
// - Parameters and stack-allocated locals need to be materialized.  Altered
12775
//   values need to be written back to the stack afterwards.
12776
// - The arguments object needs to materialized.
12777
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
12778
  HandleScope scope(isolate);
12779

    
12780
  // Check the execution state and decode arguments frame and source to be
12781
  // evaluated.
12782
  ASSERT(args.length() == 6);
12783
  Object* check_result;
12784
  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12785
      RUNTIME_ARGUMENTS(isolate, args));
12786
    if (!maybe_result->ToObject(&check_result)) return maybe_result;
12787
  }
12788
  CONVERT_SMI_ARG_CHECKED(wrapped_id, 1);
12789
  CONVERT_NUMBER_CHECKED(int, inlined_jsframe_index, Int32, args[2]);
12790
  CONVERT_ARG_HANDLE_CHECKED(String, source, 3);
12791
  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 4);
12792
  Handle<Object> context_extension(args[5], isolate);
12793

    
12794
  // Handle the processing of break.
12795
  DisableBreak disable_break_save(isolate, disable_break);
12796

    
12797
  // Get the frame where the debugging is performed.
12798
  StackFrame::Id id = UnwrapFrameId(wrapped_id);
12799
  JavaScriptFrameIterator it(isolate, id);
12800
  JavaScriptFrame* frame = it.frame();
12801
  FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
12802
  Handle<JSFunction> function(JSFunction::cast(frame_inspector.GetFunction()));
12803

    
12804
  // Traverse the saved contexts chain to find the active context for the
12805
  // selected frame.
12806
  SaveContext* save = FindSavedContextForFrame(isolate, frame);
12807

    
12808
  SaveContext savex(isolate);
12809
  isolate->set_context(*(save->context()));
12810

    
12811
  // Evaluate on the context of the frame.
12812
  Handle<Context> context(Context::cast(frame->context()));
12813
  ASSERT(!context.is_null());
12814

    
12815
  // Materialize stack locals and the arguments object.
12816
  Handle<JSObject> materialized =
12817
      isolate->factory()->NewJSObject(isolate->object_function());
12818

    
12819
  materialized = MaterializeStackLocalsWithFrameInspector(
12820
      isolate, materialized, function, &frame_inspector);
12821
  RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12822

    
12823
  materialized = MaterializeArgumentsObject(isolate, materialized, function);
12824
  RETURN_IF_EMPTY_HANDLE(isolate, materialized);
12825

    
12826
  // Add the materialized object in a with-scope to shadow the stack locals.
12827
  context = isolate->factory()->NewWithContext(function, context, materialized);
12828

    
12829
  Handle<Object> receiver(frame->receiver(), isolate);
12830
  Object* evaluate_result_object;
12831
  { MaybeObject* maybe_result =
12832
    DebugEvaluate(isolate, context, context_extension, receiver, source);
12833
    if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
12834
  }
12835

    
12836
  Handle<Object> result(evaluate_result_object, isolate);
12837

    
12838
  // Write back potential changes to materialized stack locals to the stack.
12839
  UpdateStackLocalsFromMaterializedObject(
12840
      isolate, materialized, function, frame, inlined_jsframe_index);
12841

    
12842
  return *result;
12843
}
12844

    
12845

    
12846
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) {
12847
  HandleScope scope(isolate);
12848

    
12849
  // Check the execution state and decode arguments frame and source to be
12850
  // evaluated.
12851
  ASSERT(args.length() == 4);
12852
  Object* check_result;
12853
  { MaybeObject* maybe_result = Runtime_CheckExecutionState(
12854
      RUNTIME_ARGUMENTS(isolate, args));
12855
    if (!maybe_result->ToObject(&check_result)) return maybe_result;
12856
  }
12857
  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
12858
  CONVERT_BOOLEAN_ARG_CHECKED(disable_break, 2);
12859
  Handle<Object> context_extension(args[3], isolate);
12860

    
12861
  // Handle the processing of break.
12862
  DisableBreak disable_break_save(isolate, disable_break);
12863

    
12864
  // Enter the top context from before the debugger was invoked.
12865
  SaveContext save(isolate);
12866
  SaveContext* top = &save;
12867
  while (top != NULL && *top->context() == *isolate->debug()->debug_context()) {
12868
    top = top->prev();
12869
  }
12870
  if (top != NULL) {
12871
    isolate->set_context(*top->context());
12872
  }
12873

    
12874
  // Get the native context now set to the top context from before the
12875
  // debugger was invoked.
12876
  Handle<Context> context = isolate->native_context();
12877
  Handle<Object> receiver = isolate->global_object();
12878
  return DebugEvaluate(isolate, context, context_extension, receiver, source);
12879
}
12880

    
12881

    
12882
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetLoadedScripts) {
12883
  HandleScope scope(isolate);
12884
  ASSERT(args.length() == 0);
12885

    
12886
  // Fill the script objects.
12887
  Handle<FixedArray> instances = isolate->debug()->GetLoadedScripts();
12888

    
12889
  // Convert the script objects to proper JS objects.
12890
  for (int i = 0; i < instances->length(); i++) {
12891
    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
12892
    // Get the script wrapper in a local handle before calling GetScriptWrapper,
12893
    // because using
12894
    //   instances->set(i, *GetScriptWrapper(script))
12895
    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
12896
    // already have dereferenced the instances handle.
12897
    Handle<JSValue> wrapper = GetScriptWrapper(script);
12898
    instances->set(i, *wrapper);
12899
  }
12900

    
12901
  // Return result as a JS array.
12902
  Handle<JSObject> result =
12903
      isolate->factory()->NewJSObject(isolate->array_function());
12904
  isolate->factory()->SetContent(Handle<JSArray>::cast(result), instances);
12905
  return *result;
12906
}
12907

    
12908

    
12909
// Helper function used by Runtime_DebugReferencedBy below.
12910
static int DebugReferencedBy(HeapIterator* iterator,
12911
                             JSObject* target,
12912
                             Object* instance_filter, int max_references,
12913
                             FixedArray* instances, int instances_size,
12914
                             JSFunction* arguments_function) {
12915
  Isolate* isolate = target->GetIsolate();
12916
  SealHandleScope shs(isolate);
12917
  DisallowHeapAllocation no_allocation;
12918

    
12919
  // Iterate the heap.
12920
  int count = 0;
12921
  JSObject* last = NULL;
12922
  HeapObject* heap_obj = NULL;
12923
  while (((heap_obj = iterator->next()) != NULL) &&
12924
         (max_references == 0 || count < max_references)) {
12925
    // Only look at all JSObjects.
12926
    if (heap_obj->IsJSObject()) {
12927
      // Skip context extension objects and argument arrays as these are
12928
      // checked in the context of functions using them.
12929
      JSObject* obj = JSObject::cast(heap_obj);
12930
      if (obj->IsJSContextExtensionObject() ||
12931
          obj->map()->constructor() == arguments_function) {
12932
        continue;
12933
      }
12934

    
12935
      // Check if the JS object has a reference to the object looked for.
12936
      if (obj->ReferencesObject(target)) {
12937
        // Check instance filter if supplied. This is normally used to avoid
12938
        // references from mirror objects (see Runtime_IsInPrototypeChain).
12939
        if (!instance_filter->IsUndefined()) {
12940
          Object* V = obj;
12941
          while (true) {
12942
            Object* prototype = V->GetPrototype(isolate);
12943
            if (prototype->IsNull()) {
12944
              break;
12945
            }
12946
            if (instance_filter == prototype) {
12947
              obj = NULL;  // Don't add this object.
12948
              break;
12949
            }
12950
            V = prototype;
12951
          }
12952
        }
12953

    
12954
        if (obj != NULL) {
12955
          // Valid reference found add to instance array if supplied an update
12956
          // count.
12957
          if (instances != NULL && count < instances_size) {
12958
            instances->set(count, obj);
12959
          }
12960
          last = obj;
12961
          count++;
12962
        }
12963
      }
12964
    }
12965
  }
12966

    
12967
  // Check for circular reference only. This can happen when the object is only
12968
  // referenced from mirrors and has a circular reference in which case the
12969
  // object is not really alive and would have been garbage collected if not
12970
  // referenced from the mirror.
12971
  if (count == 1 && last == target) {
12972
    count = 0;
12973
  }
12974

    
12975
  // Return the number of referencing objects found.
12976
  return count;
12977
}
12978

    
12979

    
12980
// Scan the heap for objects with direct references to an object
12981
// args[0]: the object to find references to
12982
// args[1]: constructor function for instances to exclude (Mirror)
12983
// args[2]: the the maximum number of objects to return
12984
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugReferencedBy) {
12985
  SealHandleScope shs(isolate);
12986
  ASSERT(args.length() == 3);
12987

    
12988
  // First perform a full GC in order to avoid references from dead objects.
12989
  isolate->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
12990
                                     "%DebugReferencedBy");
12991
  // The heap iterator reserves the right to do a GC to make the heap iterable.
12992
  // Due to the GC above we know it won't need to do that, but it seems cleaner
12993
  // to get the heap iterator constructed before we start having unprotected
12994
  // Object* locals that are not protected by handles.
12995

    
12996
  // Check parameters.
12997
  CONVERT_ARG_CHECKED(JSObject, target, 0);
12998
  Object* instance_filter = args[1];
12999
  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
13000
                 instance_filter->IsJSObject());
13001
  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
13002
  RUNTIME_ASSERT(max_references >= 0);
13003

    
13004

    
13005
  // Get the constructor function for context extension and arguments array.
13006
  JSObject* arguments_boilerplate =
13007
      isolate->context()->native_context()->arguments_boilerplate();
13008
  JSFunction* arguments_function =
13009
      JSFunction::cast(arguments_boilerplate->map()->constructor());
13010

    
13011
  // Get the number of referencing objects.
13012
  int count;
13013
  Heap* heap = isolate->heap();
13014
  HeapIterator heap_iterator(heap);
13015
  count = DebugReferencedBy(&heap_iterator,
13016
                            target, instance_filter, max_references,
13017
                            NULL, 0, arguments_function);
13018

    
13019
  // Allocate an array to hold the result.
13020
  Object* object;
13021
  { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
13022
    if (!maybe_object->ToObject(&object)) return maybe_object;
13023
  }
13024
  FixedArray* instances = FixedArray::cast(object);
13025

    
13026
  // Fill the referencing objects.
13027
  // AllocateFixedArray above does not make the heap non-iterable.
13028
  ASSERT(heap->IsHeapIterable());
13029
  HeapIterator heap_iterator2(heap);
13030
  count = DebugReferencedBy(&heap_iterator2,
13031
                            target, instance_filter, max_references,
13032
                            instances, count, arguments_function);
13033

    
13034
  // Return result as JS array.
13035
  Object* result;
13036
  MaybeObject* maybe_result = heap->AllocateJSObject(
13037
      isolate->context()->native_context()->array_function());
13038
  if (!maybe_result->ToObject(&result)) return maybe_result;
13039
  return JSArray::cast(result)->SetContent(instances);
13040
}
13041

    
13042

    
13043
// Helper function used by Runtime_DebugConstructedBy below.
13044
static int DebugConstructedBy(HeapIterator* iterator,
13045
                              JSFunction* constructor,
13046
                              int max_references,
13047
                              FixedArray* instances,
13048
                              int instances_size) {
13049
  DisallowHeapAllocation no_allocation;
13050

    
13051
  // Iterate the heap.
13052
  int count = 0;
13053
  HeapObject* heap_obj = NULL;
13054
  while (((heap_obj = iterator->next()) != NULL) &&
13055
         (max_references == 0 || count < max_references)) {
13056
    // Only look at all JSObjects.
13057
    if (heap_obj->IsJSObject()) {
13058
      JSObject* obj = JSObject::cast(heap_obj);
13059
      if (obj->map()->constructor() == constructor) {
13060
        // Valid reference found add to instance array if supplied an update
13061
        // count.
13062
        if (instances != NULL && count < instances_size) {
13063
          instances->set(count, obj);
13064
        }
13065
        count++;
13066
      }
13067
    }
13068
  }
13069

    
13070
  // Return the number of referencing objects found.
13071
  return count;
13072
}
13073

    
13074

    
13075
// Scan the heap for objects constructed by a specific function.
13076
// args[0]: the constructor to find instances of
13077
// args[1]: the the maximum number of objects to return
13078
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugConstructedBy) {
13079
  SealHandleScope shs(isolate);
13080
  ASSERT(args.length() == 2);
13081

    
13082
  // First perform a full GC in order to avoid dead objects.
13083
  Heap* heap = isolate->heap();
13084
  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "%DebugConstructedBy");
13085

    
13086
  // Check parameters.
13087
  CONVERT_ARG_CHECKED(JSFunction, constructor, 0);
13088
  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
13089
  RUNTIME_ASSERT(max_references >= 0);
13090

    
13091
  // Get the number of referencing objects.
13092
  int count;
13093
  HeapIterator heap_iterator(heap);
13094
  count = DebugConstructedBy(&heap_iterator,
13095
                             constructor,
13096
                             max_references,
13097
                             NULL,
13098
                             0);
13099

    
13100
  // Allocate an array to hold the result.
13101
  Object* object;
13102
  { MaybeObject* maybe_object = heap->AllocateFixedArray(count);
13103
    if (!maybe_object->ToObject(&object)) return maybe_object;
13104
  }
13105
  FixedArray* instances = FixedArray::cast(object);
13106

    
13107
  ASSERT(isolate->heap()->IsHeapIterable());
13108
  // Fill the referencing objects.
13109
  HeapIterator heap_iterator2(heap);
13110
  count = DebugConstructedBy(&heap_iterator2,
13111
                             constructor,
13112
                             max_references,
13113
                             instances,
13114
                             count);
13115

    
13116
  // Return result as JS array.
13117
  Object* result;
13118
  { MaybeObject* maybe_result = isolate->heap()->AllocateJSObject(
13119
      isolate->context()->native_context()->array_function());
13120
    if (!maybe_result->ToObject(&result)) return maybe_result;
13121
  }
13122
  return JSArray::cast(result)->SetContent(instances);
13123
}
13124

    
13125

    
13126
// Find the effective prototype object as returned by __proto__.
13127
// args[0]: the object to find the prototype for.
13128
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugGetPrototype) {
13129
  SealHandleScope shs(isolate);
13130
  ASSERT(args.length() == 1);
13131
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
13132
  return GetPrototypeSkipHiddenPrototypes(isolate, obj);
13133
}
13134

    
13135

    
13136
// Patches script source (should be called upon BeforeCompile event).
13137
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugSetScriptSource) {
13138
  HandleScope scope(isolate);
13139
  ASSERT(args.length() == 2);
13140

    
13141
  CONVERT_ARG_HANDLE_CHECKED(JSValue, script_wrapper, 0);
13142
  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13143

    
13144
  RUNTIME_ASSERT(script_wrapper->value()->IsScript());
13145
  Handle<Script> script(Script::cast(script_wrapper->value()));
13146

    
13147
  int compilation_state = script->compilation_state();
13148
  RUNTIME_ASSERT(compilation_state == Script::COMPILATION_STATE_INITIAL);
13149
  script->set_source(*source);
13150

    
13151
  return isolate->heap()->undefined_value();
13152
}
13153

    
13154

    
13155
RUNTIME_FUNCTION(MaybeObject*, Runtime_SystemBreak) {
13156
  SealHandleScope shs(isolate);
13157
  ASSERT(args.length() == 0);
13158
  OS::DebugBreak();
13159
  return isolate->heap()->undefined_value();
13160
}
13161

    
13162

    
13163
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
13164
  HandleScope scope(isolate);
13165
#ifdef DEBUG
13166
  ASSERT(args.length() == 1);
13167
  // Get the function and make sure it is compiled.
13168
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13169
  if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
13170
    return Failure::Exception();
13171
  }
13172
  func->code()->PrintLn();
13173
#endif  // DEBUG
13174
  return isolate->heap()->undefined_value();
13175
}
13176

    
13177

    
13178
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
13179
  HandleScope scope(isolate);
13180
#ifdef DEBUG
13181
  ASSERT(args.length() == 1);
13182
  // Get the function and make sure it is compiled.
13183
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
13184
  if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
13185
    return Failure::Exception();
13186
  }
13187
  func->shared()->construct_stub()->PrintLn();
13188
#endif  // DEBUG
13189
  return isolate->heap()->undefined_value();
13190
}
13191

    
13192

    
13193
RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetInferredName) {
13194
  SealHandleScope shs(isolate);
13195
  ASSERT(args.length() == 1);
13196

    
13197
  CONVERT_ARG_CHECKED(JSFunction, f, 0);
13198
  return f->shared()->inferred_name();
13199
}
13200

    
13201

    
13202
static int FindSharedFunctionInfosForScript(HeapIterator* iterator,
13203
                                            Script* script,
13204
                                            FixedArray* buffer) {
13205
  DisallowHeapAllocation no_allocation;
13206
  int counter = 0;
13207
  int buffer_size = buffer->length();
13208
  for (HeapObject* obj = iterator->next();
13209
       obj != NULL;
13210
       obj = iterator->next()) {
13211
    ASSERT(obj != NULL);
13212
    if (!obj->IsSharedFunctionInfo()) {
13213
      continue;
13214
    }
13215
    SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
13216
    if (shared->script() != script) {
13217
      continue;
13218
    }
13219
    if (counter < buffer_size) {
13220
      buffer->set(counter, shared);
13221
    }
13222
    counter++;
13223
  }
13224
  return counter;
13225
}
13226

    
13227

    
13228
// For a script finds all SharedFunctionInfo's in the heap that points
13229
// to this script. Returns JSArray of SharedFunctionInfo wrapped
13230
// in OpaqueReferences.
13231
RUNTIME_FUNCTION(MaybeObject*,
13232
                 Runtime_LiveEditFindSharedFunctionInfosForScript) {
13233
  HandleScope scope(isolate);
13234
  CHECK(isolate->debugger()->live_edit_enabled());
13235
  ASSERT(args.length() == 1);
13236
  CONVERT_ARG_CHECKED(JSValue, script_value, 0);
13237

    
13238
  RUNTIME_ASSERT(script_value->value()->IsScript());
13239
  Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
13240

    
13241
  const int kBufferSize = 32;
13242

    
13243
  Handle<FixedArray> array;
13244
  array = isolate->factory()->NewFixedArray(kBufferSize);
13245
  int number;
13246
  Heap* heap = isolate->heap();
13247
  {
13248
    heap->EnsureHeapIsIterable();
13249
    DisallowHeapAllocation no_allocation;
13250
    HeapIterator heap_iterator(heap);
13251
    Script* scr = *script;
13252
    FixedArray* arr = *array;
13253
    number = FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13254
  }
13255
  if (number > kBufferSize) {
13256
    array = isolate->factory()->NewFixedArray(number);
13257
    heap->EnsureHeapIsIterable();
13258
    DisallowHeapAllocation no_allocation;
13259
    HeapIterator heap_iterator(heap);
13260
    Script* scr = *script;
13261
    FixedArray* arr = *array;
13262
    FindSharedFunctionInfosForScript(&heap_iterator, scr, arr);
13263
  }
13264

    
13265
  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(array);
13266
  result->set_length(Smi::FromInt(number));
13267

    
13268
  LiveEdit::WrapSharedFunctionInfos(result);
13269

    
13270
  return *result;
13271
}
13272

    
13273

    
13274
// For a script calculates compilation information about all its functions.
13275
// The script source is explicitly specified by the second argument.
13276
// The source of the actual script is not used, however it is important that
13277
// all generated code keeps references to this particular instance of script.
13278
// Returns a JSArray of compilation infos. The array is ordered so that
13279
// each function with all its descendant is always stored in a continues range
13280
// with the function itself going first. The root function is a script function.
13281
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
13282
  HandleScope scope(isolate);
13283
  CHECK(isolate->debugger()->live_edit_enabled());
13284
  ASSERT(args.length() == 2);
13285
  CONVERT_ARG_CHECKED(JSValue, script, 0);
13286
  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
13287

    
13288
  RUNTIME_ASSERT(script->value()->IsScript());
13289
  Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
13290

    
13291
  JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
13292

    
13293
  if (isolate->has_pending_exception()) {
13294
    return Failure::Exception();
13295
  }
13296

    
13297
  return result;
13298
}
13299

    
13300

    
13301
// Changes the source of the script to a new_source.
13302
// If old_script_name is provided (i.e. is a String), also creates a copy of
13303
// the script with its original source and sends notification to debugger.
13304
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceScript) {
13305
  HandleScope scope(isolate);
13306
  CHECK(isolate->debugger()->live_edit_enabled());
13307
  ASSERT(args.length() == 3);
13308
  CONVERT_ARG_CHECKED(JSValue, original_script_value, 0);
13309
  CONVERT_ARG_HANDLE_CHECKED(String, new_source, 1);
13310
  Handle<Object> old_script_name(args[2], isolate);
13311

    
13312
  RUNTIME_ASSERT(original_script_value->value()->IsScript());
13313
  Handle<Script> original_script(Script::cast(original_script_value->value()));
13314

    
13315
  Object* old_script = LiveEdit::ChangeScriptSource(original_script,
13316
                                                    new_source,
13317
                                                    old_script_name);
13318

    
13319
  if (old_script->IsScript()) {
13320
    Handle<Script> script_handle(Script::cast(old_script));
13321
    return *(GetScriptWrapper(script_handle));
13322
  } else {
13323
    return isolate->heap()->null_value();
13324
  }
13325
}
13326

    
13327

    
13328
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSourceUpdated) {
13329
  HandleScope scope(isolate);
13330
  CHECK(isolate->debugger()->live_edit_enabled());
13331
  ASSERT(args.length() == 1);
13332
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 0);
13333
  return LiveEdit::FunctionSourceUpdated(shared_info);
13334
}
13335

    
13336

    
13337
// Replaces code of SharedFunctionInfo with a new one.
13338
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceFunctionCode) {
13339
  HandleScope scope(isolate);
13340
  CHECK(isolate->debugger()->live_edit_enabled());
13341
  ASSERT(args.length() == 2);
13342
  CONVERT_ARG_HANDLE_CHECKED(JSArray, new_compile_info, 0);
13343
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_info, 1);
13344

    
13345
  return LiveEdit::ReplaceFunctionCode(new_compile_info, shared_info);
13346
}
13347

    
13348

    
13349
// Connects SharedFunctionInfo to another script.
13350
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditFunctionSetScript) {
13351
  HandleScope scope(isolate);
13352
  CHECK(isolate->debugger()->live_edit_enabled());
13353
  ASSERT(args.length() == 2);
13354
  Handle<Object> function_object(args[0], isolate);
13355
  Handle<Object> script_object(args[1], isolate);
13356

    
13357
  if (function_object->IsJSValue()) {
13358
    Handle<JSValue> function_wrapper = Handle<JSValue>::cast(function_object);
13359
    if (script_object->IsJSValue()) {
13360
      RUNTIME_ASSERT(JSValue::cast(*script_object)->value()->IsScript());
13361
      Script* script = Script::cast(JSValue::cast(*script_object)->value());
13362
      script_object = Handle<Object>(script, isolate);
13363
    }
13364

    
13365
    LiveEdit::SetFunctionScript(function_wrapper, script_object);
13366
  } else {
13367
    // Just ignore this. We may not have a SharedFunctionInfo for some functions
13368
    // and we check it in this function.
13369
  }
13370

    
13371
  return isolate->heap()->undefined_value();
13372
}
13373

    
13374

    
13375
// In a code of a parent function replaces original function as embedded object
13376
// with a substitution one.
13377
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditReplaceRefToNestedFunction) {
13378
  HandleScope scope(isolate);
13379
  CHECK(isolate->debugger()->live_edit_enabled());
13380
  ASSERT(args.length() == 3);
13381

    
13382
  CONVERT_ARG_HANDLE_CHECKED(JSValue, parent_wrapper, 0);
13383
  CONVERT_ARG_HANDLE_CHECKED(JSValue, orig_wrapper, 1);
13384
  CONVERT_ARG_HANDLE_CHECKED(JSValue, subst_wrapper, 2);
13385

    
13386
  LiveEdit::ReplaceRefToNestedFunction(parent_wrapper, orig_wrapper,
13387
                                       subst_wrapper);
13388

    
13389
  return isolate->heap()->undefined_value();
13390
}
13391

    
13392

    
13393
// Updates positions of a shared function info (first parameter) according
13394
// to script source change. Text change is described in second parameter as
13395
// array of groups of 3 numbers:
13396
// (change_begin, change_end, change_end_new_position).
13397
// Each group describes a change in text; groups are sorted by change_begin.
13398
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditPatchFunctionPositions) {
13399
  HandleScope scope(isolate);
13400
  CHECK(isolate->debugger()->live_edit_enabled());
13401
  ASSERT(args.length() == 2);
13402
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13403
  CONVERT_ARG_HANDLE_CHECKED(JSArray, position_change_array, 1);
13404

    
13405
  return LiveEdit::PatchFunctionPositions(shared_array, position_change_array);
13406
}
13407

    
13408

    
13409
// For array of SharedFunctionInfo's (each wrapped in JSValue)
13410
// checks that none of them have activations on stacks (of any thread).
13411
// Returns array of the same length with corresponding results of
13412
// LiveEdit::FunctionPatchabilityStatus type.
13413
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCheckAndDropActivations) {
13414
  HandleScope scope(isolate);
13415
  CHECK(isolate->debugger()->live_edit_enabled());
13416
  ASSERT(args.length() == 2);
13417
  CONVERT_ARG_HANDLE_CHECKED(JSArray, shared_array, 0);
13418
  CONVERT_BOOLEAN_ARG_CHECKED(do_drop, 1);
13419

    
13420
  return *LiveEdit::CheckAndDropActivations(shared_array, do_drop);
13421
}
13422

    
13423

    
13424
// Compares 2 strings line-by-line, then token-wise and returns diff in form
13425
// of JSArray of triplets (pos1, pos1_end, pos2_end) describing list
13426
// of diff chunks.
13427
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditCompareStrings) {
13428
  HandleScope scope(isolate);
13429
  CHECK(isolate->debugger()->live_edit_enabled());
13430
  ASSERT(args.length() == 2);
13431
  CONVERT_ARG_HANDLE_CHECKED(String, s1, 0);
13432
  CONVERT_ARG_HANDLE_CHECKED(String, s2, 1);
13433

    
13434
  return *LiveEdit::CompareStrings(s1, s2);
13435
}
13436

    
13437

    
13438
// Restarts a call frame and completely drops all frames above.
13439
// Returns true if successful. Otherwise returns undefined or an error message.
13440
RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditRestartFrame) {
13441
  HandleScope scope(isolate);
13442
  CHECK(isolate->debugger()->live_edit_enabled());
13443
  ASSERT(args.length() == 2);
13444

    
13445
  // Check arguments.
13446
  Object* check;
13447
  { MaybeObject* maybe_check = Runtime_CheckExecutionState(
13448
      RUNTIME_ARGUMENTS(isolate, args));
13449
    if (!maybe_check->ToObject(&check)) return maybe_check;
13450
  }
13451
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
13452
  Heap* heap = isolate->heap();
13453

    
13454
  // Find the relevant frame with the requested index.
13455
  StackFrame::Id id = isolate->debug()->break_frame_id();
13456
  if (id == StackFrame::NO_ID) {
13457
    // If there are no JavaScript stack frames return undefined.
13458
    return heap->undefined_value();
13459
  }
13460

    
13461
  int count = 0;
13462
  JavaScriptFrameIterator it(isolate, id);
13463
  for (; !it.done(); it.Advance()) {
13464
    if (index < count + it.frame()->GetInlineCount()) break;
13465
    count += it.frame()->GetInlineCount();
13466
  }
13467
  if (it.done()) return heap->undefined_value();
13468

    
13469
  const char* error_message = LiveEdit::RestartFrame(it.frame());
13470
  if (error_message) {
13471
    return *(isolate->factory()->InternalizeUtf8String(error_message));
13472
  }
13473
  return heap->true_value();
13474
}
13475

    
13476

    
13477
// A testing entry. Returns statement position which is the closest to
13478
// source_position.
13479
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFunctionCodePositionFromSource) {
13480
  HandleScope scope(isolate);
13481
  CHECK(isolate->debugger()->live_edit_enabled());
13482
  ASSERT(args.length() == 2);
13483
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13484
  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
13485

    
13486
  Handle<Code> code(function->code(), isolate);
13487

    
13488
  if (code->kind() != Code::FUNCTION &&
13489
      code->kind() != Code::OPTIMIZED_FUNCTION) {
13490
    return isolate->heap()->undefined_value();
13491
  }
13492

    
13493
  RelocIterator it(*code, RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION));
13494
  int closest_pc = 0;
13495
  int distance = kMaxInt;
13496
  while (!it.done()) {
13497
    int statement_position = static_cast<int>(it.rinfo()->data());
13498
    // Check if this break point is closer that what was previously found.
13499
    if (source_position <= statement_position &&
13500
        statement_position - source_position < distance) {
13501
      closest_pc =
13502
          static_cast<int>(it.rinfo()->pc() - code->instruction_start());
13503
      distance = statement_position - source_position;
13504
      // Check whether we can't get any closer.
13505
      if (distance == 0) break;
13506
    }
13507
    it.next();
13508
  }
13509

    
13510
  return Smi::FromInt(closest_pc);
13511
}
13512

    
13513

    
13514
// Calls specified function with or without entering the debugger.
13515
// This is used in unit tests to run code as if debugger is entered or simply
13516
// to have a stack with C++ frame in the middle.
13517
RUNTIME_FUNCTION(MaybeObject*, Runtime_ExecuteInDebugContext) {
13518
  HandleScope scope(isolate);
13519
  ASSERT(args.length() == 2);
13520
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
13521
  CONVERT_BOOLEAN_ARG_CHECKED(without_debugger, 1);
13522

    
13523
  Handle<Object> result;
13524
  bool pending_exception;
13525
  {
13526
    if (without_debugger) {
13527
      result = Execution::Call(isolate,
13528
                               function,
13529
                               isolate->global_object(),
13530
                               0,
13531
                               NULL,
13532
                               &pending_exception);
13533
    } else {
13534
      EnterDebugger enter_debugger(isolate);
13535
      result = Execution::Call(isolate,
13536
                               function,
13537
                               isolate->global_object(),
13538
                               0,
13539
                               NULL,
13540
                               &pending_exception);
13541
    }
13542
  }
13543
  if (!pending_exception) {
13544
    return *result;
13545
  } else {
13546
    return Failure::Exception();
13547
  }
13548
}
13549

    
13550

    
13551
// Sets a v8 flag.
13552
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFlags) {
13553
  SealHandleScope shs(isolate);
13554
  CONVERT_ARG_CHECKED(String, arg, 0);
13555
  SmartArrayPointer<char> flags =
13556
      arg->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
13557
  FlagList::SetFlagsFromString(*flags, StrLength(*flags));
13558
  return isolate->heap()->undefined_value();
13559
}
13560

    
13561

    
13562
// Performs a GC.
13563
// Presently, it only does a full GC.
13564
RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectGarbage) {
13565
  SealHandleScope shs(isolate);
13566
  isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "%CollectGarbage");
13567
  return isolate->heap()->undefined_value();
13568
}
13569

    
13570

    
13571
// Gets the current heap usage.
13572
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHeapUsage) {
13573
  SealHandleScope shs(isolate);
13574
  int usage = static_cast<int>(isolate->heap()->SizeOfObjects());
13575
  if (!Smi::IsValid(usage)) {
13576
    return *isolate->factory()->NewNumberFromInt(usage);
13577
  }
13578
  return Smi::FromInt(usage);
13579
}
13580

    
13581
#endif  // ENABLE_DEBUGGER_SUPPORT
13582

    
13583

    
13584
#ifdef V8_I18N_SUPPORT
13585
RUNTIME_FUNCTION(MaybeObject*, Runtime_CanonicalizeLanguageTag) {
13586
  HandleScope scope(isolate);
13587

    
13588
  ASSERT(args.length() == 1);
13589
  CONVERT_ARG_HANDLE_CHECKED(String, locale_id_str, 0);
13590

    
13591
  v8::String::Utf8Value locale_id(v8::Utils::ToLocal(locale_id_str));
13592

    
13593
  // Return value which denotes invalid language tag.
13594
  const char* const kInvalidTag = "invalid-tag";
13595

    
13596
  UErrorCode error = U_ZERO_ERROR;
13597
  char icu_result[ULOC_FULLNAME_CAPACITY];
13598
  int icu_length = 0;
13599

    
13600
  uloc_forLanguageTag(*locale_id, icu_result, ULOC_FULLNAME_CAPACITY,
13601
                      &icu_length, &error);
13602
  if (U_FAILURE(error) || icu_length == 0) {
13603
    return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13604
  }
13605

    
13606
  char result[ULOC_FULLNAME_CAPACITY];
13607

    
13608
  // Force strict BCP47 rules.
13609
  uloc_toLanguageTag(icu_result, result, ULOC_FULLNAME_CAPACITY, TRUE, &error);
13610

    
13611
  if (U_FAILURE(error)) {
13612
    return isolate->heap()->AllocateStringFromOneByte(CStrVector(kInvalidTag));
13613
  }
13614

    
13615
  return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13616
}
13617

    
13618

    
13619
RUNTIME_FUNCTION(MaybeObject*, Runtime_AvailableLocalesOf) {
13620
  HandleScope scope(isolate);
13621

    
13622
  ASSERT(args.length() == 1);
13623
  CONVERT_ARG_HANDLE_CHECKED(String, service, 0);
13624

    
13625
  const icu::Locale* available_locales = NULL;
13626
  int32_t count = 0;
13627

    
13628
  if (service->IsUtf8EqualTo(CStrVector("collator"))) {
13629
    available_locales = icu::Collator::getAvailableLocales(count);
13630
  } else if (service->IsUtf8EqualTo(CStrVector("numberformat"))) {
13631
    available_locales = icu::NumberFormat::getAvailableLocales(count);
13632
  } else if (service->IsUtf8EqualTo(CStrVector("dateformat"))) {
13633
    available_locales = icu::DateFormat::getAvailableLocales(count);
13634
  } else if (service->IsUtf8EqualTo(CStrVector("breakiterator"))) {
13635
    available_locales = icu::BreakIterator::getAvailableLocales(count);
13636
  }
13637

    
13638
  UErrorCode error = U_ZERO_ERROR;
13639
  char result[ULOC_FULLNAME_CAPACITY];
13640
  Handle<JSObject> locales =
13641
      isolate->factory()->NewJSObject(isolate->object_function());
13642

    
13643
  for (int32_t i = 0; i < count; ++i) {
13644
    const char* icu_name = available_locales[i].getName();
13645

    
13646
    error = U_ZERO_ERROR;
13647
    // No need to force strict BCP47 rules.
13648
    uloc_toLanguageTag(icu_name, result, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13649
    if (U_FAILURE(error)) {
13650
      // This shouldn't happen, but lets not break the user.
13651
      continue;
13652
    }
13653

    
13654
    RETURN_IF_EMPTY_HANDLE(isolate,
13655
        JSObject::SetLocalPropertyIgnoreAttributes(
13656
            locales,
13657
            isolate->factory()->NewStringFromAscii(CStrVector(result)),
13658
            isolate->factory()->NewNumber(i),
13659
            NONE));
13660
  }
13661

    
13662
  return *locales;
13663
}
13664

    
13665

    
13666
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultICULocale) {
13667
  SealHandleScope shs(isolate);
13668

    
13669
  ASSERT(args.length() == 0);
13670

    
13671
  icu::Locale default_locale;
13672

    
13673
  // Set the locale
13674
  char result[ULOC_FULLNAME_CAPACITY];
13675
  UErrorCode status = U_ZERO_ERROR;
13676
  uloc_toLanguageTag(
13677
      default_locale.getName(), result, ULOC_FULLNAME_CAPACITY, FALSE, &status);
13678
  if (U_SUCCESS(status)) {
13679
    return isolate->heap()->AllocateStringFromOneByte(CStrVector(result));
13680
  }
13681

    
13682
  return isolate->heap()->AllocateStringFromOneByte(CStrVector("und"));
13683
}
13684

    
13685

    
13686
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLanguageTagVariants) {
13687
  HandleScope scope(isolate);
13688

    
13689
  ASSERT(args.length() == 1);
13690

    
13691
  CONVERT_ARG_HANDLE_CHECKED(JSArray, input, 0);
13692

    
13693
  uint32_t length = static_cast<uint32_t>(input->length()->Number());
13694
  Handle<FixedArray> output = isolate->factory()->NewFixedArray(length);
13695
  Handle<Name> maximized =
13696
      isolate->factory()->NewStringFromAscii(CStrVector("maximized"));
13697
  Handle<Name> base =
13698
      isolate->factory()->NewStringFromAscii(CStrVector("base"));
13699
  for (unsigned int i = 0; i < length; ++i) {
13700
    MaybeObject* maybe_string = input->GetElement(isolate, i);
13701
    Object* locale_id;
13702
    if (!maybe_string->ToObject(&locale_id) || !locale_id->IsString()) {
13703
      return isolate->Throw(isolate->heap()->illegal_argument_string());
13704
    }
13705

    
13706
    v8::String::Utf8Value utf8_locale_id(
13707
        v8::Utils::ToLocal(Handle<String>(String::cast(locale_id))));
13708

    
13709
    UErrorCode error = U_ZERO_ERROR;
13710

    
13711
    // Convert from BCP47 to ICU format.
13712
    // de-DE-u-co-phonebk -> de_DE@collation=phonebook
13713
    char icu_locale[ULOC_FULLNAME_CAPACITY];
13714
    int icu_locale_length = 0;
13715
    uloc_forLanguageTag(*utf8_locale_id, icu_locale, ULOC_FULLNAME_CAPACITY,
13716
                        &icu_locale_length, &error);
13717
    if (U_FAILURE(error) || icu_locale_length == 0) {
13718
      return isolate->Throw(isolate->heap()->illegal_argument_string());
13719
    }
13720

    
13721
    // Maximize the locale.
13722
    // de_DE@collation=phonebook -> de_Latn_DE@collation=phonebook
13723
    char icu_max_locale[ULOC_FULLNAME_CAPACITY];
13724
    uloc_addLikelySubtags(
13725
        icu_locale, icu_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13726

    
13727
    // Remove extensions from maximized locale.
13728
    // de_Latn_DE@collation=phonebook -> de_Latn_DE
13729
    char icu_base_max_locale[ULOC_FULLNAME_CAPACITY];
13730
    uloc_getBaseName(
13731
        icu_max_locale, icu_base_max_locale, ULOC_FULLNAME_CAPACITY, &error);
13732

    
13733
    // Get original name without extensions.
13734
    // de_DE@collation=phonebook -> de_DE
13735
    char icu_base_locale[ULOC_FULLNAME_CAPACITY];
13736
    uloc_getBaseName(
13737
        icu_locale, icu_base_locale, ULOC_FULLNAME_CAPACITY, &error);
13738

    
13739
    // Convert from ICU locale format to BCP47 format.
13740
    // de_Latn_DE -> de-Latn-DE
13741
    char base_max_locale[ULOC_FULLNAME_CAPACITY];
13742
    uloc_toLanguageTag(icu_base_max_locale, base_max_locale,
13743
                       ULOC_FULLNAME_CAPACITY, FALSE, &error);
13744

    
13745
    // de_DE -> de-DE
13746
    char base_locale[ULOC_FULLNAME_CAPACITY];
13747
    uloc_toLanguageTag(
13748
        icu_base_locale, base_locale, ULOC_FULLNAME_CAPACITY, FALSE, &error);
13749

    
13750
    if (U_FAILURE(error)) {
13751
      return isolate->Throw(isolate->heap()->illegal_argument_string());
13752
    }
13753

    
13754
    Handle<JSObject> result =
13755
        isolate->factory()->NewJSObject(isolate->object_function());
13756
    RETURN_IF_EMPTY_HANDLE(isolate,
13757
        JSObject::SetLocalPropertyIgnoreAttributes(
13758
            result,
13759
            maximized,
13760
            isolate->factory()->NewStringFromAscii(CStrVector(base_max_locale)),
13761
            NONE));
13762
    RETURN_IF_EMPTY_HANDLE(isolate,
13763
        JSObject::SetLocalPropertyIgnoreAttributes(
13764
            result,
13765
            base,
13766
            isolate->factory()->NewStringFromAscii(CStrVector(base_locale)),
13767
            NONE));
13768
    output->set(i, *result);
13769
  }
13770

    
13771
  Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(output);
13772
  result->set_length(Smi::FromInt(length));
13773
  return *result;
13774
}
13775

    
13776

    
13777
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateDateTimeFormat) {
13778
  HandleScope scope(isolate);
13779

    
13780
  ASSERT(args.length() == 3);
13781

    
13782
  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13783
  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13784
  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13785

    
13786
  Handle<ObjectTemplateInfo> date_format_template =
13787
      I18N::GetTemplate(isolate);
13788

    
13789
  // Create an empty object wrapper.
13790
  bool has_pending_exception = false;
13791
  Handle<JSObject> local_object = Execution::InstantiateObject(
13792
      date_format_template, &has_pending_exception);
13793
  if (has_pending_exception) {
13794
    ASSERT(isolate->has_pending_exception());
13795
    return Failure::Exception();
13796
  }
13797

    
13798
  // Set date time formatter as internal field of the resulting JS object.
13799
  icu::SimpleDateFormat* date_format = DateFormat::InitializeDateTimeFormat(
13800
      isolate, locale, options, resolved);
13801

    
13802
  if (!date_format) return isolate->ThrowIllegalOperation();
13803

    
13804
  local_object->SetInternalField(0, reinterpret_cast<Smi*>(date_format));
13805

    
13806
  RETURN_IF_EMPTY_HANDLE(isolate,
13807
      JSObject::SetLocalPropertyIgnoreAttributes(
13808
          local_object,
13809
          isolate->factory()->NewStringFromAscii(CStrVector("dateFormat")),
13810
          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13811
          NONE));
13812

    
13813
  // Make object handle weak so we can delete the data format once GC kicks in.
13814
  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
13815
  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
13816
                          NULL,
13817
                          DateFormat::DeleteDateFormat);
13818
  return *local_object;
13819
}
13820

    
13821

    
13822
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateFormat) {
13823
  HandleScope scope(isolate);
13824

    
13825
  ASSERT(args.length() == 2);
13826

    
13827
  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13828
  CONVERT_ARG_HANDLE_CHECKED(JSDate, date, 1);
13829

    
13830
  bool has_pending_exception = false;
13831
  Handle<Object> value =
13832
      Execution::ToNumber(isolate, date, &has_pending_exception);
13833
  if (has_pending_exception) {
13834
    ASSERT(isolate->has_pending_exception());
13835
    return Failure::Exception();
13836
  }
13837

    
13838
  icu::SimpleDateFormat* date_format =
13839
      DateFormat::UnpackDateFormat(isolate, date_format_holder);
13840
  if (!date_format) return isolate->ThrowIllegalOperation();
13841

    
13842
  icu::UnicodeString result;
13843
  date_format->format(value->Number(), result);
13844

    
13845
  return *isolate->factory()->NewStringFromTwoByte(
13846
      Vector<const uint16_t>(
13847
          reinterpret_cast<const uint16_t*>(result.getBuffer()),
13848
          result.length()));
13849
}
13850

    
13851

    
13852
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalDateParse) {
13853
  HandleScope scope(isolate);
13854

    
13855
  ASSERT(args.length() == 2);
13856

    
13857
  CONVERT_ARG_HANDLE_CHECKED(JSObject, date_format_holder, 0);
13858
  CONVERT_ARG_HANDLE_CHECKED(String, date_string, 1);
13859

    
13860
  v8::String::Utf8Value utf8_date(v8::Utils::ToLocal(date_string));
13861
  icu::UnicodeString u_date(icu::UnicodeString::fromUTF8(*utf8_date));
13862
  icu::SimpleDateFormat* date_format =
13863
      DateFormat::UnpackDateFormat(isolate, date_format_holder);
13864
  if (!date_format) return isolate->ThrowIllegalOperation();
13865

    
13866
  UErrorCode status = U_ZERO_ERROR;
13867
  UDate date = date_format->parse(u_date, status);
13868
  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13869

    
13870
  bool has_pending_exception = false;
13871
  Handle<JSDate> result = Handle<JSDate>::cast(
13872
      Execution::NewDate(
13873
          isolate, static_cast<double>(date), &has_pending_exception));
13874
  if (has_pending_exception) {
13875
    ASSERT(isolate->has_pending_exception());
13876
    return Failure::Exception();
13877
  }
13878
  return *result;
13879
}
13880

    
13881

    
13882
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateNumberFormat) {
13883
  HandleScope scope(isolate);
13884

    
13885
  ASSERT(args.length() == 3);
13886

    
13887
  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
13888
  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
13889
  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
13890

    
13891
  Handle<ObjectTemplateInfo> number_format_template =
13892
      I18N::GetTemplate(isolate);
13893

    
13894
  // Create an empty object wrapper.
13895
  bool has_pending_exception = false;
13896
  Handle<JSObject> local_object = Execution::InstantiateObject(
13897
      number_format_template, &has_pending_exception);
13898
  if (has_pending_exception) {
13899
    ASSERT(isolate->has_pending_exception());
13900
    return Failure::Exception();
13901
  }
13902

    
13903
  // Set number formatter as internal field of the resulting JS object.
13904
  icu::DecimalFormat* number_format = NumberFormat::InitializeNumberFormat(
13905
      isolate, locale, options, resolved);
13906

    
13907
  if (!number_format) return isolate->ThrowIllegalOperation();
13908

    
13909
  local_object->SetInternalField(0, reinterpret_cast<Smi*>(number_format));
13910

    
13911
  RETURN_IF_EMPTY_HANDLE(isolate,
13912
      JSObject::SetLocalPropertyIgnoreAttributes(
13913
          local_object,
13914
          isolate->factory()->NewStringFromAscii(CStrVector("numberFormat")),
13915
          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
13916
          NONE));
13917

    
13918
  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
13919
  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
13920
                          NULL,
13921
                          NumberFormat::DeleteNumberFormat);
13922
  return *local_object;
13923
}
13924

    
13925

    
13926
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberFormat) {
13927
  HandleScope scope(isolate);
13928

    
13929
  ASSERT(args.length() == 2);
13930

    
13931
  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13932
  CONVERT_ARG_HANDLE_CHECKED(Object, number, 1);
13933

    
13934
  bool has_pending_exception = false;
13935
  Handle<Object> value = Execution::ToNumber(
13936
      isolate, number, &has_pending_exception);
13937
  if (has_pending_exception) {
13938
    ASSERT(isolate->has_pending_exception());
13939
    return Failure::Exception();
13940
  }
13941

    
13942
  icu::DecimalFormat* number_format =
13943
      NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13944
  if (!number_format) return isolate->ThrowIllegalOperation();
13945

    
13946
  icu::UnicodeString result;
13947
  number_format->format(value->Number(), result);
13948

    
13949
  return *isolate->factory()->NewStringFromTwoByte(
13950
      Vector<const uint16_t>(
13951
          reinterpret_cast<const uint16_t*>(result.getBuffer()),
13952
          result.length()));
13953
}
13954

    
13955

    
13956
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalNumberParse) {
13957
  HandleScope scope(isolate);
13958

    
13959
  ASSERT(args.length() == 2);
13960

    
13961
  CONVERT_ARG_HANDLE_CHECKED(JSObject, number_format_holder, 0);
13962
  CONVERT_ARG_HANDLE_CHECKED(String, number_string, 1);
13963

    
13964
  v8::String::Utf8Value utf8_number(v8::Utils::ToLocal(number_string));
13965
  icu::UnicodeString u_number(icu::UnicodeString::fromUTF8(*utf8_number));
13966
  icu::DecimalFormat* number_format =
13967
      NumberFormat::UnpackNumberFormat(isolate, number_format_holder);
13968
  if (!number_format) return isolate->ThrowIllegalOperation();
13969

    
13970
  UErrorCode status = U_ZERO_ERROR;
13971
  icu::Formattable result;
13972
  // ICU 4.6 doesn't support parseCurrency call. We need to wait for ICU49
13973
  // to be part of Chrome.
13974
  // TODO(cira): Include currency parsing code using parseCurrency call.
13975
  // We need to check if the formatter parses all currencies or only the
13976
  // one it was constructed with (it will impact the API - how to return ISO
13977
  // code and the value).
13978
  number_format->parse(u_number, result, status);
13979
  if (U_FAILURE(status)) return isolate->heap()->undefined_value();
13980

    
13981
  switch (result.getType()) {
13982
  case icu::Formattable::kDouble:
13983
    return *isolate->factory()->NewNumber(result.getDouble());
13984
  case icu::Formattable::kLong:
13985
    return *isolate->factory()->NewNumberFromInt(result.getLong());
13986
  case icu::Formattable::kInt64:
13987
    return *isolate->factory()->NewNumber(
13988
        static_cast<double>(result.getInt64()));
13989
  default:
13990
    return isolate->heap()->undefined_value();
13991
  }
13992
}
13993

    
13994

    
13995
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateCollator) {
13996
  HandleScope scope(isolate);
13997

    
13998
  ASSERT(args.length() == 3);
13999

    
14000
  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14001
  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14002
  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14003

    
14004
  Handle<ObjectTemplateInfo> collator_template = I18N::GetTemplate(isolate);
14005

    
14006
  // Create an empty object wrapper.
14007
  bool has_pending_exception = false;
14008
  Handle<JSObject> local_object = Execution::InstantiateObject(
14009
      collator_template, &has_pending_exception);
14010
  if (has_pending_exception) {
14011
    ASSERT(isolate->has_pending_exception());
14012
    return Failure::Exception();
14013
  }
14014

    
14015
  // Set collator as internal field of the resulting JS object.
14016
  icu::Collator* collator = Collator::InitializeCollator(
14017
      isolate, locale, options, resolved);
14018

    
14019
  if (!collator) return isolate->ThrowIllegalOperation();
14020

    
14021
  local_object->SetInternalField(0, reinterpret_cast<Smi*>(collator));
14022

    
14023
  RETURN_IF_EMPTY_HANDLE(isolate,
14024
      JSObject::SetLocalPropertyIgnoreAttributes(
14025
          local_object,
14026
          isolate->factory()->NewStringFromAscii(CStrVector("collator")),
14027
          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14028
          NONE));
14029

    
14030
  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14031
  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
14032
                          NULL,
14033
                          Collator::DeleteCollator);
14034
  return *local_object;
14035
}
14036

    
14037

    
14038
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalCompare) {
14039
  HandleScope scope(isolate);
14040

    
14041
  ASSERT(args.length() == 3);
14042

    
14043
  CONVERT_ARG_HANDLE_CHECKED(JSObject, collator_holder, 0);
14044
  CONVERT_ARG_HANDLE_CHECKED(String, string1, 1);
14045
  CONVERT_ARG_HANDLE_CHECKED(String, string2, 2);
14046

    
14047
  icu::Collator* collator = Collator::UnpackCollator(isolate, collator_holder);
14048
  if (!collator) return isolate->ThrowIllegalOperation();
14049

    
14050
  v8::String::Value string_value1(v8::Utils::ToLocal(string1));
14051
  v8::String::Value string_value2(v8::Utils::ToLocal(string2));
14052
  const UChar* u_string1 = reinterpret_cast<const UChar*>(*string_value1);
14053
  const UChar* u_string2 = reinterpret_cast<const UChar*>(*string_value2);
14054
  UErrorCode status = U_ZERO_ERROR;
14055
  UCollationResult result = collator->compare(u_string1,
14056
                                              string_value1.length(),
14057
                                              u_string2,
14058
                                              string_value2.length(),
14059
                                              status);
14060
  if (U_FAILURE(status)) return isolate->ThrowIllegalOperation();
14061

    
14062
  return *isolate->factory()->NewNumberFromInt(result);
14063
}
14064

    
14065

    
14066
RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateBreakIterator) {
14067
  HandleScope scope(isolate);
14068

    
14069
  ASSERT(args.length() == 3);
14070

    
14071
  CONVERT_ARG_HANDLE_CHECKED(String, locale, 0);
14072
  CONVERT_ARG_HANDLE_CHECKED(JSObject, options, 1);
14073
  CONVERT_ARG_HANDLE_CHECKED(JSObject, resolved, 2);
14074

    
14075
  Handle<ObjectTemplateInfo> break_iterator_template =
14076
      I18N::GetTemplate2(isolate);
14077

    
14078
  // Create an empty object wrapper.
14079
  bool has_pending_exception = false;
14080
  Handle<JSObject> local_object = Execution::InstantiateObject(
14081
      break_iterator_template, &has_pending_exception);
14082
  if (has_pending_exception) {
14083
    ASSERT(isolate->has_pending_exception());
14084
    return Failure::Exception();
14085
  }
14086

    
14087
  // Set break iterator as internal field of the resulting JS object.
14088
  icu::BreakIterator* break_iterator = BreakIterator::InitializeBreakIterator(
14089
      isolate, locale, options, resolved);
14090

    
14091
  if (!break_iterator) return isolate->ThrowIllegalOperation();
14092

    
14093
  local_object->SetInternalField(0, reinterpret_cast<Smi*>(break_iterator));
14094
  // Make sure that the pointer to adopted text is NULL.
14095
  local_object->SetInternalField(1, reinterpret_cast<Smi*>(NULL));
14096

    
14097
  RETURN_IF_EMPTY_HANDLE(isolate,
14098
      JSObject::SetLocalPropertyIgnoreAttributes(
14099
          local_object,
14100
          isolate->factory()->NewStringFromAscii(CStrVector("breakIterator")),
14101
          isolate->factory()->NewStringFromAscii(CStrVector("valid")),
14102
          NONE));
14103

    
14104
  // Make object handle weak so we can delete the break iterator once GC kicks
14105
  // in.
14106
  Handle<Object> wrapper = isolate->global_handles()->Create(*local_object);
14107
  GlobalHandles::MakeWeak(reinterpret_cast<Object**>(wrapper.location()),
14108
                          NULL,
14109
                          BreakIterator::DeleteBreakIterator);
14110
  return *local_object;
14111
}
14112

    
14113

    
14114
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorAdoptText) {
14115
  HandleScope scope(isolate);
14116

    
14117
  ASSERT(args.length() == 2);
14118

    
14119
  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14120
  CONVERT_ARG_HANDLE_CHECKED(String, text, 1);
14121

    
14122
  icu::BreakIterator* break_iterator =
14123
      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14124
  if (!break_iterator) return isolate->ThrowIllegalOperation();
14125

    
14126
  icu::UnicodeString* u_text = reinterpret_cast<icu::UnicodeString*>(
14127
      break_iterator_holder->GetInternalField(1));
14128
  delete u_text;
14129

    
14130
  v8::String::Value text_value(v8::Utils::ToLocal(text));
14131
  u_text = new icu::UnicodeString(
14132
      reinterpret_cast<const UChar*>(*text_value), text_value.length());
14133
  break_iterator_holder->SetInternalField(1, reinterpret_cast<Smi*>(u_text));
14134

    
14135
  break_iterator->setText(*u_text);
14136

    
14137
  return isolate->heap()->undefined_value();
14138
}
14139

    
14140

    
14141
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorFirst) {
14142
  HandleScope scope(isolate);
14143

    
14144
  ASSERT(args.length() == 1);
14145

    
14146
  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14147

    
14148
  icu::BreakIterator* break_iterator =
14149
      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14150
  if (!break_iterator) return isolate->ThrowIllegalOperation();
14151

    
14152
  return *isolate->factory()->NewNumberFromInt(break_iterator->first());
14153
}
14154

    
14155

    
14156
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorNext) {
14157
  HandleScope scope(isolate);
14158

    
14159
  ASSERT(args.length() == 1);
14160

    
14161
  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14162

    
14163
  icu::BreakIterator* break_iterator =
14164
      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14165
  if (!break_iterator) return isolate->ThrowIllegalOperation();
14166

    
14167
  return *isolate->factory()->NewNumberFromInt(break_iterator->next());
14168
}
14169

    
14170

    
14171
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorCurrent) {
14172
  HandleScope scope(isolate);
14173

    
14174
  ASSERT(args.length() == 1);
14175

    
14176
  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14177

    
14178
  icu::BreakIterator* break_iterator =
14179
      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14180
  if (!break_iterator) return isolate->ThrowIllegalOperation();
14181

    
14182
  return *isolate->factory()->NewNumberFromInt(break_iterator->current());
14183
}
14184

    
14185

    
14186
RUNTIME_FUNCTION(MaybeObject*, Runtime_BreakIteratorBreakType) {
14187
  HandleScope scope(isolate);
14188

    
14189
  ASSERT(args.length() == 1);
14190

    
14191
  CONVERT_ARG_HANDLE_CHECKED(JSObject, break_iterator_holder, 0);
14192

    
14193
  icu::BreakIterator* break_iterator =
14194
      BreakIterator::UnpackBreakIterator(isolate, break_iterator_holder);
14195
  if (!break_iterator) return isolate->ThrowIllegalOperation();
14196

    
14197
  // TODO(cira): Remove cast once ICU fixes base BreakIterator class.
14198
  icu::RuleBasedBreakIterator* rule_based_iterator =
14199
      static_cast<icu::RuleBasedBreakIterator*>(break_iterator);
14200
  int32_t status = rule_based_iterator->getRuleStatus();
14201
  // Keep return values in sync with JavaScript BreakType enum.
14202
  if (status >= UBRK_WORD_NONE && status < UBRK_WORD_NONE_LIMIT) {
14203
    return *isolate->factory()->NewStringFromAscii(CStrVector("none"));
14204
  } else if (status >= UBRK_WORD_NUMBER && status < UBRK_WORD_NUMBER_LIMIT) {
14205
    return *isolate->factory()->NewStringFromAscii(CStrVector("number"));
14206
  } else if (status >= UBRK_WORD_LETTER && status < UBRK_WORD_LETTER_LIMIT) {
14207
    return *isolate->factory()->NewStringFromAscii(CStrVector("letter"));
14208
  } else if (status >= UBRK_WORD_KANA && status < UBRK_WORD_KANA_LIMIT) {
14209
    return *isolate->factory()->NewStringFromAscii(CStrVector("kana"));
14210
  } else if (status >= UBRK_WORD_IDEO && status < UBRK_WORD_IDEO_LIMIT) {
14211
    return *isolate->factory()->NewStringFromAscii(CStrVector("ideo"));
14212
  } else {
14213
    return *isolate->factory()->NewStringFromAscii(CStrVector("unknown"));
14214
  }
14215
}
14216
#endif  // V8_I18N_SUPPORT
14217

    
14218

    
14219
// Finds the script object from the script data. NOTE: This operation uses
14220
// heap traversal to find the function generated for the source position
14221
// for the requested break point. For lazily compiled functions several heap
14222
// traversals might be required rendering this operation as a rather slow
14223
// operation. However for setting break points which is normally done through
14224
// some kind of user interaction the performance is not crucial.
14225
static Handle<Object> Runtime_GetScriptFromScriptName(
14226
    Handle<String> script_name) {
14227
  // Scan the heap for Script objects to find the script with the requested
14228
  // script data.
14229
  Handle<Script> script;
14230
  Factory* factory = script_name->GetIsolate()->factory();
14231
  Heap* heap = script_name->GetHeap();
14232
  heap->EnsureHeapIsIterable();
14233
  DisallowHeapAllocation no_allocation_during_heap_iteration;
14234
  HeapIterator iterator(heap);
14235
  HeapObject* obj = NULL;
14236
  while (script.is_null() && ((obj = iterator.next()) != NULL)) {
14237
    // If a script is found check if it has the script data requested.
14238
    if (obj->IsScript()) {
14239
      if (Script::cast(obj)->name()->IsString()) {
14240
        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
14241
          script = Handle<Script>(Script::cast(obj));
14242
        }
14243
      }
14244
    }
14245
  }
14246

    
14247
  // If no script with the requested script data is found return undefined.
14248
  if (script.is_null()) return factory->undefined_value();
14249

    
14250
  // Return the script found.
14251
  return GetScriptWrapper(script);
14252
}
14253

    
14254

    
14255
// Get the script object from script data. NOTE: Regarding performance
14256
// see the NOTE for GetScriptFromScriptData.
14257
// args[0]: script data for the script to find the source for
14258
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetScript) {
14259
  HandleScope scope(isolate);
14260

    
14261
  ASSERT(args.length() == 1);
14262

    
14263
  CONVERT_ARG_CHECKED(String, script_name, 0);
14264

    
14265
  // Find the requested script.
14266
  Handle<Object> result =
14267
      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
14268
  return *result;
14269
}
14270

    
14271

    
14272
// Collect the raw data for a stack trace.  Returns an array of 4
14273
// element segments each containing a receiver, function, code and
14274
// native code offset.
14275
RUNTIME_FUNCTION(MaybeObject*, Runtime_CollectStackTrace) {
14276
  HandleScope scope(isolate);
14277
  ASSERT_EQ(args.length(), 3);
14278
  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14279
  Handle<Object> caller = args.at<Object>(1);
14280
  CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[2]);
14281

    
14282
  // Optionally capture a more detailed stack trace for the message.
14283
  isolate->CaptureAndSetDetailedStackTrace(error_object);
14284
  // Capture a simple stack trace for the stack property.
14285
  return *isolate->CaptureSimpleStackTrace(error_object, caller, limit);
14286
}
14287

    
14288

    
14289
// Retrieve the stack trace.  This is the raw stack trace that yet has to
14290
// be formatted.  Since we only need this once, clear it afterwards.
14291
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetAndClearOverflowedStackTrace) {
14292
  HandleScope scope(isolate);
14293
  ASSERT_EQ(args.length(), 1);
14294
  CONVERT_ARG_HANDLE_CHECKED(JSObject, error_object, 0);
14295
  Handle<String> key = isolate->factory()->hidden_stack_trace_string();
14296
  Handle<Object> result(error_object->GetHiddenProperty(*key), isolate);
14297
  if (result->IsTheHole()) return isolate->heap()->undefined_value();
14298
  RUNTIME_ASSERT(result->IsJSArray() || result->IsUndefined());
14299
  JSObject::DeleteHiddenProperty(error_object, key);
14300
  return *result;
14301
}
14302

    
14303

    
14304
// Returns V8 version as a string.
14305
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetV8Version) {
14306
  SealHandleScope shs(isolate);
14307
  ASSERT_EQ(args.length(), 0);
14308

    
14309
  const char* version_string = v8::V8::GetVersion();
14310

    
14311
  return isolate->heap()->AllocateStringFromOneByte(CStrVector(version_string),
14312
                                                  NOT_TENURED);
14313
}
14314

    
14315

    
14316
RUNTIME_FUNCTION(MaybeObject*, Runtime_Abort) {
14317
  SealHandleScope shs(isolate);
14318
  ASSERT(args.length() == 2);
14319
  OS::PrintError("abort: %s\n",
14320
                 reinterpret_cast<char*>(args[0]) + args.smi_at(1));
14321
  isolate->PrintStack(stderr);
14322
  OS::Abort();
14323
  UNREACHABLE();
14324
  return NULL;
14325
}
14326

    
14327

    
14328
RUNTIME_FUNCTION(MaybeObject*, Runtime_FlattenString) {
14329
  HandleScope scope(isolate);
14330
  ASSERT(args.length() == 1);
14331
  CONVERT_ARG_HANDLE_CHECKED(String, str, 0);
14332
  FlattenString(str);
14333
  return isolate->heap()->undefined_value();
14334
}
14335

    
14336

    
14337
RUNTIME_FUNCTION(MaybeObject*, Runtime_NotifyContextDisposed) {
14338
  HandleScope scope(isolate);
14339
  ASSERT(args.length() == 0);
14340
  isolate->heap()->NotifyContextDisposed();
14341
  return isolate->heap()->undefined_value();
14342
}
14343

    
14344

    
14345
RUNTIME_FUNCTION(MaybeObject*, Runtime_MigrateInstance) {
14346
  HandleScope scope(isolate);
14347
  ASSERT(args.length() == 1);
14348
  CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
14349
  if (!object->IsJSObject()) return Smi::FromInt(0);
14350
  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
14351
  if (!js_object->map()->is_deprecated()) return Smi::FromInt(0);
14352
  JSObject::MigrateInstance(js_object);
14353
  return *object;
14354
}
14355

    
14356

    
14357
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetFromCache) {
14358
  SealHandleScope shs(isolate);
14359
  // This is only called from codegen, so checks might be more lax.
14360
  CONVERT_ARG_CHECKED(JSFunctionResultCache, cache, 0);
14361
  Object* key = args[1];
14362

    
14363
  int finger_index = cache->finger_index();
14364
  Object* o = cache->get(finger_index);
14365
  if (o == key) {
14366
    // The fastest case: hit the same place again.
14367
    return cache->get(finger_index + 1);
14368
  }
14369

    
14370
  for (int i = finger_index - 2;
14371
       i >= JSFunctionResultCache::kEntriesIndex;
14372
       i -= 2) {
14373
    o = cache->get(i);
14374
    if (o == key) {
14375
      cache->set_finger_index(i);
14376
      return cache->get(i + 1);
14377
    }
14378
  }
14379

    
14380
  int size = cache->size();
14381
  ASSERT(size <= cache->length());
14382

    
14383
  for (int i = size - 2; i > finger_index; i -= 2) {
14384
    o = cache->get(i);
14385
    if (o == key) {
14386
      cache->set_finger_index(i);
14387
      return cache->get(i + 1);
14388
    }
14389
  }
14390

    
14391
  // There is no value in the cache.  Invoke the function and cache result.
14392
  HandleScope scope(isolate);
14393

    
14394
  Handle<JSFunctionResultCache> cache_handle(cache);
14395
  Handle<Object> key_handle(key, isolate);
14396
  Handle<Object> value;
14397
  {
14398
    Handle<JSFunction> factory(JSFunction::cast(
14399
          cache_handle->get(JSFunctionResultCache::kFactoryIndex)));
14400
    // TODO(antonm): consider passing a receiver when constructing a cache.
14401
    Handle<Object> receiver(isolate->native_context()->global_object(),
14402
                            isolate);
14403
    // This handle is nor shared, nor used later, so it's safe.
14404
    Handle<Object> argv[] = { key_handle };
14405
    bool pending_exception;
14406
    value = Execution::Call(isolate,
14407
                            factory,
14408
                            receiver,
14409
                            ARRAY_SIZE(argv),
14410
                            argv,
14411
                            &pending_exception);
14412
    if (pending_exception) return Failure::Exception();
14413
  }
14414

    
14415
#ifdef VERIFY_HEAP
14416
  if (FLAG_verify_heap) {
14417
    cache_handle->JSFunctionResultCacheVerify();
14418
  }
14419
#endif
14420

    
14421
  // Function invocation may have cleared the cache.  Reread all the data.
14422
  finger_index = cache_handle->finger_index();
14423
  size = cache_handle->size();
14424

    
14425
  // If we have spare room, put new data into it, otherwise evict post finger
14426
  // entry which is likely to be the least recently used.
14427
  int index = -1;
14428
  if (size < cache_handle->length()) {
14429
    cache_handle->set_size(size + JSFunctionResultCache::kEntrySize);
14430
    index = size;
14431
  } else {
14432
    index = finger_index + JSFunctionResultCache::kEntrySize;
14433
    if (index == cache_handle->length()) {
14434
      index = JSFunctionResultCache::kEntriesIndex;
14435
    }
14436
  }
14437

    
14438
  ASSERT(index % 2 == 0);
14439
  ASSERT(index >= JSFunctionResultCache::kEntriesIndex);
14440
  ASSERT(index < cache_handle->length());
14441

    
14442
  cache_handle->set(index, *key_handle);
14443
  cache_handle->set(index + 1, *value);
14444
  cache_handle->set_finger_index(index);
14445

    
14446
#ifdef VERIFY_HEAP
14447
  if (FLAG_verify_heap) {
14448
    cache_handle->JSFunctionResultCacheVerify();
14449
  }
14450
#endif
14451

    
14452
  return *value;
14453
}
14454

    
14455

    
14456
RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetStartPosition) {
14457
  SealHandleScope shs(isolate);
14458
  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14459
  return Smi::FromInt(message->start_position());
14460
}
14461

    
14462

    
14463
RUNTIME_FUNCTION(MaybeObject*, Runtime_MessageGetScript) {
14464
  SealHandleScope shs(isolate);
14465
  CONVERT_ARG_CHECKED(JSMessageObject, message, 0);
14466
  return message->script();
14467
}
14468

    
14469

    
14470
#ifdef DEBUG
14471
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
14472
// Exclude the code in release mode.
14473
RUNTIME_FUNCTION(MaybeObject*, Runtime_ListNatives) {
14474
  HandleScope scope(isolate);
14475
  ASSERT(args.length() == 0);
14476
#define COUNT_ENTRY(Name, argc, ressize) + 1
14477
  int entry_count = 0
14478
      RUNTIME_FUNCTION_LIST(COUNT_ENTRY)
14479
      INLINE_FUNCTION_LIST(COUNT_ENTRY)
14480
      INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY);
14481
#undef COUNT_ENTRY
14482
  Factory* factory = isolate->factory();
14483
  Handle<FixedArray> elements = factory->NewFixedArray(entry_count);
14484
  int index = 0;
14485
  bool inline_runtime_functions = false;
14486
#define ADD_ENTRY(Name, argc, ressize)                                       \
14487
  {                                                                          \
14488
    HandleScope inner(isolate);                                              \
14489
    Handle<String> name;                                                     \
14490
    /* Inline runtime functions have an underscore in front of the name. */  \
14491
    if (inline_runtime_functions) {                                          \
14492
      name = factory->NewStringFromAscii(                                    \
14493
          Vector<const char>("_" #Name, StrLength("_" #Name)));              \
14494
    } else {                                                                 \
14495
      name = factory->NewStringFromAscii(                                    \
14496
          Vector<const char>(#Name, StrLength(#Name)));                      \
14497
    }                                                                        \
14498
    Handle<FixedArray> pair_elements = factory->NewFixedArray(2);            \
14499
    pair_elements->set(0, *name);                                            \
14500
    pair_elements->set(1, Smi::FromInt(argc));                               \
14501
    Handle<JSArray> pair = factory->NewJSArrayWithElements(pair_elements);   \
14502
    elements->set(index++, *pair);                                           \
14503
  }
14504
  inline_runtime_functions = false;
14505
  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14506
  inline_runtime_functions = true;
14507
  INLINE_FUNCTION_LIST(ADD_ENTRY)
14508
  INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY)
14509
#undef ADD_ENTRY
14510
  ASSERT_EQ(index, entry_count);
14511
  Handle<JSArray> result = factory->NewJSArrayWithElements(elements);
14512
  return *result;
14513
}
14514
#endif
14515

    
14516

    
14517
RUNTIME_FUNCTION(MaybeObject*, Runtime_Log) {
14518
  SealHandleScope shs(isolate);
14519
  ASSERT(args.length() == 2);
14520
  CONVERT_ARG_CHECKED(String, format, 0);
14521
  CONVERT_ARG_CHECKED(JSArray, elms, 1);
14522
  DisallowHeapAllocation no_gc;
14523
  String::FlatContent format_content = format->GetFlatContent();
14524
  RUNTIME_ASSERT(format_content.IsAscii());
14525
  Vector<const uint8_t> chars = format_content.ToOneByteVector();
14526
  isolate->logger()->LogRuntime(Vector<const char>::cast(chars), elms);
14527
  return isolate->heap()->undefined_value();
14528
}
14529

    
14530

    
14531
RUNTIME_FUNCTION(MaybeObject*, Runtime_IS_VAR) {
14532
  UNREACHABLE();  // implemented as macro in the parser
14533
  return NULL;
14534
}
14535

    
14536

    
14537
#define ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(Name)        \
14538
  RUNTIME_FUNCTION(MaybeObject*, Runtime_Has##Name) {     \
14539
    CONVERT_ARG_CHECKED(JSObject, obj, 0);              \
14540
    return isolate->heap()->ToBoolean(obj->Has##Name());  \
14541
  }
14542

    
14543
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiElements)
14544
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastObjectElements)
14545
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastSmiOrObjectElements)
14546
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastDoubleElements)
14547
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastHoleyElements)
14548
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(DictionaryElements)
14549
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(NonStrictArgumentsElements)
14550
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalPixelElements)
14551
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalArrayElements)
14552
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalByteElements)
14553
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedByteElements)
14554
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalShortElements)
14555
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedShortElements)
14556
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalIntElements)
14557
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalUnsignedIntElements)
14558
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalFloatElements)
14559
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(ExternalDoubleElements)
14560
// Properties test sitting with elements tests - not fooling anyone.
14561
ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION(FastProperties)
14562

    
14563
#undef ELEMENTS_KIND_CHECK_RUNTIME_FUNCTION
14564

    
14565

    
14566
RUNTIME_FUNCTION(MaybeObject*, Runtime_HaveSameMap) {
14567
  SealHandleScope shs(isolate);
14568
  ASSERT(args.length() == 2);
14569
  CONVERT_ARG_CHECKED(JSObject, obj1, 0);
14570
  CONVERT_ARG_CHECKED(JSObject, obj2, 1);
14571
  return isolate->heap()->ToBoolean(obj1->map() == obj2->map());
14572
}
14573

    
14574

    
14575
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessCheckNeeded) {
14576
  SealHandleScope shs(isolate);
14577
  ASSERT(args.length() == 1);
14578
  CONVERT_ARG_CHECKED(HeapObject, obj, 0);
14579
  return isolate->heap()->ToBoolean(obj->IsAccessCheckNeeded());
14580
}
14581

    
14582

    
14583
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsObserved) {
14584
  SealHandleScope shs(isolate);
14585
  ASSERT(args.length() == 1);
14586

    
14587
  if (!args[0]->IsJSReceiver()) return isolate->heap()->false_value();
14588
  JSReceiver* obj = JSReceiver::cast(args[0]);
14589
  if (obj->IsJSGlobalProxy()) {
14590
    Object* proto = obj->GetPrototype();
14591
    if (proto->IsNull()) return isolate->heap()->false_value();
14592
    ASSERT(proto->IsJSGlobalObject());
14593
    obj = JSReceiver::cast(proto);
14594
  }
14595
  return isolate->heap()->ToBoolean(obj->map()->is_observed());
14596
}
14597

    
14598

    
14599
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetIsObserved) {
14600
  HandleScope scope(isolate);
14601
  ASSERT(args.length() == 1);
14602
  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, obj, 0);
14603
  if (obj->IsJSGlobalProxy()) {
14604
    Object* proto = obj->GetPrototype();
14605
    if (proto->IsNull()) return isolate->heap()->undefined_value();
14606
    ASSERT(proto->IsJSGlobalObject());
14607
    obj = handle(JSReceiver::cast(proto));
14608
  }
14609
  if (obj->IsJSProxy())
14610
    return isolate->heap()->undefined_value();
14611

    
14612
  ASSERT(!(obj->map()->is_observed() && obj->IsJSObject() &&
14613
           Handle<JSObject>::cast(obj)->HasFastElements()));
14614
  ASSERT(obj->IsJSObject());
14615
  JSObject::SetObserved(Handle<JSObject>::cast(obj));
14616
  return isolate->heap()->undefined_value();
14617
}
14618

    
14619

    
14620
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetObserverDeliveryPending) {
14621
  SealHandleScope shs(isolate);
14622
  ASSERT(args.length() == 0);
14623
  isolate->set_observer_delivery_pending(true);
14624
  return isolate->heap()->undefined_value();
14625
}
14626

    
14627

    
14628
RUNTIME_FUNCTION(MaybeObject*, Runtime_GetObservationState) {
14629
  SealHandleScope shs(isolate);
14630
  ASSERT(args.length() == 0);
14631
  return isolate->heap()->observation_state();
14632
}
14633

    
14634

    
14635
RUNTIME_FUNCTION(MaybeObject*, Runtime_ObservationWeakMapCreate) {
14636
  HandleScope scope(isolate);
14637
  ASSERT(args.length() == 0);
14638
  // TODO(adamk): Currently this runtime function is only called three times per
14639
  // isolate. If it's called more often, the map should be moved into the
14640
  // strong root list.
14641
  Handle<Map> map =
14642
      isolate->factory()->NewMap(JS_WEAK_MAP_TYPE, JSWeakMap::kSize);
14643
  Handle<JSWeakMap> weakmap =
14644
      Handle<JSWeakMap>::cast(isolate->factory()->NewJSObjectFromMap(map));
14645
  return WeakCollectionInitialize(isolate, weakmap);
14646
}
14647

    
14648

    
14649
RUNTIME_FUNCTION(MaybeObject*, Runtime_UnwrapGlobalProxy) {
14650
  SealHandleScope shs(isolate);
14651
  ASSERT(args.length() == 1);
14652
  Object* object = args[0];
14653
  if (object->IsJSGlobalProxy()) {
14654
    object = object->GetPrototype(isolate);
14655
    if (object->IsNull()) return isolate->heap()->undefined_value();
14656
  }
14657
  return object;
14658
}
14659

    
14660

    
14661
RUNTIME_FUNCTION(MaybeObject*, Runtime_IsAccessAllowedForObserver) {
14662
  HandleScope scope(isolate);
14663
  ASSERT(args.length() == 3);
14664
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, observer, 0);
14665
  CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 1);
14666
  ASSERT(object->IsAccessCheckNeeded());
14667
  Handle<Object> key = args.at<Object>(2);
14668
  SaveContext save(isolate);
14669
  isolate->set_context(observer->context());
14670
  if (!isolate->MayNamedAccess(*object, isolate->heap()->undefined_value(),
14671
                               v8::ACCESS_KEYS)) {
14672
    return isolate->heap()->false_value();
14673
  }
14674
  bool access_allowed = false;
14675
  uint32_t index = 0;
14676
  if (key->ToArrayIndex(&index) ||
14677
      (key->IsString() && String::cast(*key)->AsArrayIndex(&index))) {
14678
    access_allowed =
14679
        isolate->MayIndexedAccess(*object, index, v8::ACCESS_GET) &&
14680
        isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS);
14681
  } else {
14682
    access_allowed = isolate->MayNamedAccess(*object, *key, v8::ACCESS_GET) &&
14683
        isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS);
14684
  }
14685
  return isolate->heap()->ToBoolean(access_allowed);
14686
}
14687

    
14688

    
14689
static MaybeObject* ArrayConstructorCommon(Isolate* isolate,
14690
                                           Handle<JSFunction> constructor,
14691
                                           Handle<Object> type_info,
14692
                                           Arguments* caller_args) {
14693
  bool holey = false;
14694
  bool can_use_type_feedback = true;
14695
  if (caller_args->length() == 1) {
14696
    Object* argument_one = (*caller_args)[0];
14697
    if (argument_one->IsSmi()) {
14698
      int value = Smi::cast(argument_one)->value();
14699
      if (value < 0 || value >= JSObject::kInitialMaxFastElementArray) {
14700
        // the array is a dictionary in this case.
14701
        can_use_type_feedback = false;
14702
      } else if (value != 0) {
14703
        holey = true;
14704
      }
14705
    } else {
14706
      // Non-smi length argument produces a dictionary
14707
      can_use_type_feedback = false;
14708
    }
14709
  }
14710

    
14711
  JSArray* array;
14712
  MaybeObject* maybe_array;
14713
  if (!type_info.is_null() &&
14714
      *type_info != isolate->heap()->undefined_value() &&
14715
      Cell::cast(*type_info)->value()->IsAllocationSite() &&
14716
      can_use_type_feedback) {
14717
    Handle<Cell> cell = Handle<Cell>::cast(type_info);
14718
    Handle<AllocationSite> site = Handle<AllocationSite>(
14719
        AllocationSite::cast(cell->value()), isolate);
14720
    ASSERT(!site->SitePointsToLiteral());
14721
    ElementsKind to_kind = site->GetElementsKind();
14722
    if (holey && !IsFastHoleyElementsKind(to_kind)) {
14723
      to_kind = GetHoleyElementsKind(to_kind);
14724
      // Update the allocation site info to reflect the advice alteration.
14725
      site->SetElementsKind(to_kind);
14726
    }
14727

    
14728
    maybe_array = isolate->heap()->AllocateJSObjectWithAllocationSite(
14729
        *constructor, site);
14730
    if (!maybe_array->To(&array)) return maybe_array;
14731
  } else {
14732
    maybe_array = isolate->heap()->AllocateJSObject(*constructor);
14733
    if (!maybe_array->To(&array)) return maybe_array;
14734
    // We might need to transition to holey
14735
    ElementsKind kind = constructor->initial_map()->elements_kind();
14736
    if (holey && !IsFastHoleyElementsKind(kind)) {
14737
      kind = GetHoleyElementsKind(kind);
14738
      maybe_array = array->TransitionElementsKind(kind);
14739
      if (maybe_array->IsFailure()) return maybe_array;
14740
    }
14741
  }
14742

    
14743
  maybe_array = isolate->heap()->AllocateJSArrayStorage(array, 0, 0,
14744
      DONT_INITIALIZE_ARRAY_ELEMENTS);
14745
  if (maybe_array->IsFailure()) return maybe_array;
14746
  maybe_array = ArrayConstructInitializeElements(array, caller_args);
14747
  if (maybe_array->IsFailure()) return maybe_array;
14748
  return array;
14749
}
14750

    
14751

    
14752
RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConstructor) {
14753
  HandleScope scope(isolate);
14754
  // If we get 2 arguments then they are the stub parameters (constructor, type
14755
  // info).  If we get 3, then the first one is a pointer to the arguments
14756
  // passed by the caller.
14757
  Arguments empty_args(0, NULL);
14758
  bool no_caller_args = args.length() == 2;
14759
  ASSERT(no_caller_args || args.length() == 3);
14760
  int parameters_start = no_caller_args ? 0 : 1;
14761
  Arguments* caller_args = no_caller_args
14762
      ? &empty_args
14763
      : reinterpret_cast<Arguments*>(args[0]);
14764
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14765
  CONVERT_ARG_HANDLE_CHECKED(Object, type_info, parameters_start + 1);
14766

    
14767
  return ArrayConstructorCommon(isolate,
14768
                                constructor,
14769
                                type_info,
14770
                                caller_args);
14771
}
14772

    
14773

    
14774
RUNTIME_FUNCTION(MaybeObject*, Runtime_InternalArrayConstructor) {
14775
  HandleScope scope(isolate);
14776
  Arguments empty_args(0, NULL);
14777
  bool no_caller_args = args.length() == 1;
14778
  ASSERT(no_caller_args || args.length() == 2);
14779
  int parameters_start = no_caller_args ? 0 : 1;
14780
  Arguments* caller_args = no_caller_args
14781
      ? &empty_args
14782
      : reinterpret_cast<Arguments*>(args[0]);
14783
  CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, parameters_start);
14784

    
14785
  return ArrayConstructorCommon(isolate,
14786
                                constructor,
14787
                                Handle<Object>::null(),
14788
                                caller_args);
14789
}
14790

    
14791

    
14792
// ----------------------------------------------------------------------------
14793
// Implementation of Runtime
14794

    
14795
#define F(name, number_of_args, result_size)                             \
14796
  { Runtime::k##name, Runtime::RUNTIME, #name,   \
14797
    FUNCTION_ADDR(Runtime_##name), number_of_args, result_size },
14798

    
14799

    
14800
#define I(name, number_of_args, result_size)                             \
14801
  { Runtime::kInline##name, Runtime::INLINE,     \
14802
    "_" #name, NULL, number_of_args, result_size },
14803

    
14804
static const Runtime::Function kIntrinsicFunctions[] = {
14805
  RUNTIME_FUNCTION_LIST(F)
14806
  INLINE_FUNCTION_LIST(I)
14807
  INLINE_RUNTIME_FUNCTION_LIST(I)
14808
};
14809

    
14810

    
14811
MaybeObject* Runtime::InitializeIntrinsicFunctionNames(Heap* heap,
14812
                                                       Object* dictionary) {
14813
  ASSERT(dictionary != NULL);
14814
  ASSERT(NameDictionary::cast(dictionary)->NumberOfElements() == 0);
14815
  for (int i = 0; i < kNumFunctions; ++i) {
14816
    Object* name_string;
14817
    { MaybeObject* maybe_name_string =
14818
          heap->InternalizeUtf8String(kIntrinsicFunctions[i].name);
14819
      if (!maybe_name_string->ToObject(&name_string)) return maybe_name_string;
14820
    }
14821
    NameDictionary* name_dictionary = NameDictionary::cast(dictionary);
14822
    { MaybeObject* maybe_dictionary = name_dictionary->Add(
14823
          String::cast(name_string),
14824
          Smi::FromInt(i),
14825
          PropertyDetails(NONE, NORMAL, Representation::None()));
14826
      if (!maybe_dictionary->ToObject(&dictionary)) {
14827
        // Non-recoverable failure.  Calling code must restart heap
14828
        // initialization.
14829
        return maybe_dictionary;
14830
      }
14831
    }
14832
  }
14833
  return dictionary;
14834
}
14835

    
14836

    
14837
const Runtime::Function* Runtime::FunctionForName(Handle<String> name) {
14838
  Heap* heap = name->GetHeap();
14839
  int entry = heap->intrinsic_function_names()->FindEntry(*name);
14840
  if (entry != kNotFound) {
14841
    Object* smi_index = heap->intrinsic_function_names()->ValueAt(entry);
14842
    int function_index = Smi::cast(smi_index)->value();
14843
    return &(kIntrinsicFunctions[function_index]);
14844
  }
14845
  return NULL;
14846
}
14847

    
14848

    
14849
const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
14850
  return &(kIntrinsicFunctions[static_cast<int>(id)]);
14851
}
14852

    
14853

    
14854
void Runtime::PerformGC(Object* result, Isolate* isolate) {
14855
  Failure* failure = Failure::cast(result);
14856
  if (failure->IsRetryAfterGC()) {
14857
    if (isolate->heap()->new_space()->AddFreshPage()) {
14858
      return;
14859
    }
14860

    
14861
    // Try to do a garbage collection; ignore it if it fails. The C
14862
    // entry stub will throw an out-of-memory exception in that case.
14863
    isolate->heap()->CollectGarbage(failure->allocation_space(),
14864
                                    "Runtime::PerformGC");
14865
  } else {
14866
    // Handle last resort GC and make sure to allow future allocations
14867
    // to grow the heap without causing GCs (if possible).
14868
    isolate->counters()->gc_last_resort_from_js()->Increment();
14869
    isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
14870
                                       "Runtime::PerformGC");
14871
  }
14872
}
14873

    
14874

    
14875
} }  // namespace v8::internal