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 @ 40c0f755

History | View | Annotate | Download (225 KB)

1
// Copyright 2006-2009 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

    
30
#include "v8.h"
31

    
32
#include "accessors.h"
33
#include "api.h"
34
#include "arguments.h"
35
#include "compiler.h"
36
#include "cpu.h"
37
#include "dateparser.h"
38
#include "dateparser-inl.h"
39
#include "debug.h"
40
#include "execution.h"
41
#include "jsregexp.h"
42
#include "platform.h"
43
#include "runtime.h"
44
#include "scopeinfo.h"
45
#include "v8threads.h"
46
#include "smart-pointer.h"
47
#include "parser.h"
48

    
49
namespace v8 { namespace internal {
50

    
51

    
52
#define RUNTIME_ASSERT(value) do {                                   \
53
  if (!(value)) return IllegalOperation();                           \
54
} while (false)
55

    
56
// Cast the given object to a value of the specified type and store
57
// it in a variable with the given name.  If the object is not of the
58
// expected type call IllegalOperation and return.
59
#define CONVERT_CHECKED(Type, name, obj)                             \
60
  RUNTIME_ASSERT(obj->Is##Type());                                   \
61
  Type* name = Type::cast(obj);
62

    
63
#define CONVERT_ARG_CHECKED(Type, name, index)                       \
64
  RUNTIME_ASSERT(args[index]->Is##Type());                           \
65
  Handle<Type> name = args.at<Type>(index);
66

    
67
// Cast the given object to a boolean and store it in a variable with
68
// the given name.  If the object is not a boolean call IllegalOperation
69
// and return.
70
#define CONVERT_BOOLEAN_CHECKED(name, obj)                            \
71
  RUNTIME_ASSERT(obj->IsBoolean());                                   \
72
  bool name = (obj)->IsTrue();
73

    
74
// Cast the given object to a Smi and store its value in an int variable
75
// with the given name.  If the object is not a Smi call IllegalOperation
76
// and return.
77
#define CONVERT_SMI_CHECKED(name, obj)                            \
78
  RUNTIME_ASSERT(obj->IsSmi());                                   \
79
  int name = Smi::cast(obj)->value();
80

    
81
// Cast the given object to a double and store it in a variable with
82
// the given name.  If the object is not a number (as opposed to
83
// the number not-a-number) call IllegalOperation and return.
84
#define CONVERT_DOUBLE_CHECKED(name, obj)                            \
85
  RUNTIME_ASSERT(obj->IsNumber());                                   \
86
  double name = (obj)->Number();
87

    
88
// Call the specified converter on the object *comand store the result in
89
// a variable of the specified type with the given name.  If the
90
// object is not a Number call IllegalOperation and return.
91
#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \
92
  RUNTIME_ASSERT(obj->IsNumber());                                   \
93
  type name = NumberTo##Type(obj);
94

    
95
// Non-reentrant string buffer for efficient general use in this file.
96
static StaticResource<StringInputBuffer> runtime_string_input_buffer;
97

    
98

    
99
static Object* IllegalOperation() {
100
  return Top::Throw(Heap::illegal_access_symbol());
101
}
102

    
103

    
104
static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
105
  StackLimitCheck check;
106
  if (check.HasOverflowed()) return Top::StackOverflow();
107

    
108
  Object* result = Heap::CopyJSObject(boilerplate);
109
  if (result->IsFailure()) return result;
110
  JSObject* copy = JSObject::cast(result);
111

    
112
  // Deep copy local properties.
113
  if (copy->HasFastProperties()) {
114
    FixedArray* properties = copy->properties();
115
    WriteBarrierMode mode = properties->GetWriteBarrierMode();
116
    for (int i = 0; i < properties->length(); i++) {
117
      Object* value = properties->get(i);
118
      if (value->IsJSObject()) {
119
        JSObject* jsObject = JSObject::cast(value);
120
        result = DeepCopyBoilerplate(jsObject);
121
        if (result->IsFailure()) return result;
122
        properties->set(i, result, mode);
123
      }
124
    }
125
    mode = copy->GetWriteBarrierMode();
126
    for (int i = 0; i < copy->map()->inobject_properties(); i++) {
127
      Object* value = copy->InObjectPropertyAt(i);
128
      if (value->IsJSObject()) {
129
        JSObject* jsObject = JSObject::cast(value);
130
        result = DeepCopyBoilerplate(jsObject);
131
        if (result->IsFailure()) return result;
132
        copy->InObjectPropertyAtPut(i, result, mode);
133
      }
134
    }
135
  } else {
136
    result = Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
137
    if (result->IsFailure()) return result;
138
    FixedArray* names = FixedArray::cast(result);
139
    copy->GetLocalPropertyNames(names, 0);
140
    for (int i = 0; i < names->length(); i++) {
141
      ASSERT(names->get(i)->IsString());
142
      String* keyString = String::cast(names->get(i));
143
      PropertyAttributes attributes =
144
        copy->GetLocalPropertyAttribute(keyString);
145
      // Only deep copy fields from the object literal expression.
146
      // In particular, don't try to copy the length attribute of
147
      // an array.
148
      if (attributes != NONE) continue;
149
      Object* value = copy->GetProperty(keyString, &attributes);
150
      ASSERT(!value->IsFailure());
151
      if (value->IsJSObject()) {
152
        JSObject* jsObject = JSObject::cast(value);
153
        result = DeepCopyBoilerplate(jsObject);
154
        if (result->IsFailure()) return result;
155
        result = copy->SetProperty(keyString, result, NONE);
156
        if (result->IsFailure()) return result;
157
      }
158
    }
159
  }
160

    
161
  // Deep copy local elements.
162
  if (copy->HasFastElements()) {
163
    FixedArray* elements = copy->elements();
164
    WriteBarrierMode mode = elements->GetWriteBarrierMode();
165
    for (int i = 0; i < elements->length(); i++) {
166
      Object* value = elements->get(i);
167
      if (value->IsJSObject()) {
168
        JSObject* jsObject = JSObject::cast(value);
169
        result = DeepCopyBoilerplate(jsObject);
170
        if (result->IsFailure()) return result;
171
        elements->set(i, result, mode);
172
      }
173
    }
174
  } else {
175
    Dictionary* element_dictionary = copy->element_dictionary();
176
    int capacity = element_dictionary->Capacity();
177
    for (int i = 0; i < capacity; i++) {
178
      Object* k = element_dictionary->KeyAt(i);
179
      if (element_dictionary->IsKey(k)) {
180
        Object* value = element_dictionary->ValueAt(i);
181
        if (value->IsJSObject()) {
182
          JSObject* jsObject = JSObject::cast(value);
183
          result = DeepCopyBoilerplate(jsObject);
184
          if (result->IsFailure()) return result;
185
          element_dictionary->ValueAtPut(i, result);
186
        }
187
      }
188
    }
189
  }
190
  return copy;
191
}
192

    
193

    
194
static Object* Runtime_CloneLiteralBoilerplate(Arguments args) {
195
  CONVERT_CHECKED(JSObject, boilerplate, args[0]);
196
  return DeepCopyBoilerplate(boilerplate);
197
}
198

    
199

    
200
static Object* Runtime_CloneShallowLiteralBoilerplate(Arguments args) {
201
  CONVERT_CHECKED(JSObject, boilerplate, args[0]);
202
  return Heap::CopyJSObject(boilerplate);
203
}
204

    
205

    
206
static Handle<Map> ComputeObjectLiteralMap(
207
    Handle<Context> context,
208
    Handle<FixedArray> constant_properties,
209
    bool* is_result_from_cache) {
210
  int number_of_properties = constant_properties->length() / 2;
211
  if (FLAG_canonicalize_object_literal_maps) {
212
    // First find prefix of consecutive symbol keys.
213
    int number_of_symbol_keys = 0;
214
    while ((number_of_symbol_keys < number_of_properties) &&
215
           (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {
216
      number_of_symbol_keys++;
217
    }
218
    // Based on the number of prefix symbols key we decide whether
219
    // to use the map cache in the global context.
220
    const int kMaxKeys = 10;
221
    if ((number_of_symbol_keys == number_of_properties) &&
222
        (number_of_symbol_keys < kMaxKeys)) {
223
      // Create the fixed array with the key.
224
      Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys);
225
      for (int i = 0; i < number_of_symbol_keys; i++) {
226
        keys->set(i, constant_properties->get(i*2));
227
      }
228
      *is_result_from_cache = true;
229
      return Factory::ObjectLiteralMapFromCache(context, keys);
230
    }
231
  }
232
  *is_result_from_cache = false;
233
  return Factory::CopyMap(
234
      Handle<Map>(context->object_function()->initial_map()),
235
      number_of_properties);
236
}
237

    
238

    
239
static Handle<Object> CreateLiteralBoilerplate(
240
    Handle<FixedArray> literals,
241
    Handle<FixedArray> constant_properties);
242

    
243

    
244
static Handle<Object> CreateObjectLiteralBoilerplate(
245
    Handle<FixedArray> literals,
246
    Handle<FixedArray> constant_properties) {
247
  // Get the global context from the literals array.  This is the
248
  // context in which the function was created and we use the object
249
  // function from this context to create the object literal.  We do
250
  // not use the object function from the current global context
251
  // because this might be the object function from another context
252
  // which we should not have access to.
253
  Handle<Context> context =
254
      Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
255

    
256
  bool is_result_from_cache;
257
  Handle<Map> map = ComputeObjectLiteralMap(context,
258
                                            constant_properties,
259
                                            &is_result_from_cache);
260

    
261
  Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
262
  {  // Add the constant properties to the boilerplate.
263
    int length = constant_properties->length();
264
    OptimizedObjectForAddingMultipleProperties opt(boilerplate,
265
                                                   !is_result_from_cache);
266
    for (int index = 0; index < length; index +=2) {
267
      Handle<Object> key(constant_properties->get(index+0));
268
      Handle<Object> value(constant_properties->get(index+1));
269
      if (value->IsFixedArray()) {
270
        // The value contains the constant_properties of a
271
        // simple object literal.
272
        Handle<FixedArray> array = Handle<FixedArray>::cast(value);
273
        value = CreateLiteralBoilerplate(literals, array);
274
        if (value.is_null()) return value;
275
      }
276
      Handle<Object> result;
277
      uint32_t element_index = 0;
278
      if (key->IsSymbol()) {
279
        // If key is a symbol it is not an array element.
280
        Handle<String> name(String::cast(*key));
281
        ASSERT(!name->AsArrayIndex(&element_index));
282
        result = SetProperty(boilerplate, name, value, NONE);
283
      } else if (Array::IndexFromObject(*key, &element_index)) {
284
        // Array index (uint32).
285
        result = SetElement(boilerplate, element_index, value);
286
      } else {
287
        // Non-uint32 number.
288
        ASSERT(key->IsNumber());
289
        double num = key->Number();
290
        char arr[100];
291
        Vector<char> buffer(arr, ARRAY_SIZE(arr));
292
        const char* str = DoubleToCString(num, buffer);
293
        Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
294
        result = SetProperty(boilerplate, name, value, NONE);
295
      }
296
      // If setting the property on the boilerplate throws an
297
      // exception, the exception is converted to an empty handle in
298
      // the handle based operations.  In that case, we need to
299
      // convert back to an exception.
300
      if (result.is_null()) return result;
301
    }
302
  }
303

    
304
  return boilerplate;
305
}
306

    
307

    
308
static Handle<Object> CreateArrayLiteralBoilerplate(
309
    Handle<FixedArray> literals,
310
    Handle<FixedArray> elements) {
311
  // Create the JSArray.
312
  Handle<JSFunction> constructor(
313
      JSFunction::GlobalContextFromLiterals(*literals)->array_function());
314
  Handle<Object> object = Factory::NewJSObject(constructor);
315

    
316
  Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
317

    
318
  Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
319
  for (int i = 0; i < content->length(); i++) {
320
    if (content->get(i)->IsFixedArray()) {
321
      // The value contains the constant_properties of a
322
      // simple object literal.
323
      Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
324
      Handle<Object> result =
325
        CreateLiteralBoilerplate(literals, fa);
326
      if (result.is_null()) return result;
327
      content->set(i, *result);
328
    }
329
  }
330

    
331
  // Set the elements.
332
  Handle<JSArray>::cast(object)->SetContent(*content);
333
  return object;
334
}
335

    
336

    
337
static Handle<Object> CreateLiteralBoilerplate(
338
    Handle<FixedArray> literals,
339
    Handle<FixedArray> array) {
340
  Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
341
  switch (CompileTimeValue::GetType(array)) {
342
    case CompileTimeValue::OBJECT_LITERAL:
343
      return CreateObjectLiteralBoilerplate(literals, elements);
344
    case CompileTimeValue::ARRAY_LITERAL:
345
      return CreateArrayLiteralBoilerplate(literals, elements);
346
    default:
347
      UNREACHABLE();
348
      return Handle<Object>::null();
349
  }
350
}
351

    
352

    
353
static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
354
  HandleScope scope;
355
  ASSERT(args.length() == 3);
356
  // Copy the arguments.
357
  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
358
  CONVERT_SMI_CHECKED(literals_index, args[1]);
359
  CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
360

    
361
  Handle<Object> result =
362
    CreateObjectLiteralBoilerplate(literals, constant_properties);
363

    
364
  if (result.is_null()) return Failure::Exception();
365

    
366
  // Update the functions literal and return the boilerplate.
367
  literals->set(literals_index, *result);
368

    
369
  return *result;
370
}
371

    
372

    
373
static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
374
  // Takes a FixedArray of elements containing the literal elements of
375
  // the array literal and produces JSArray with those elements.
376
  // Additionally takes the literals array of the surrounding function
377
  // which contains the context from which to get the Array function
378
  // to use for creating the array literal.
379
  HandleScope scope;
380
  ASSERT(args.length() == 3);
381
  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
382
  CONVERT_SMI_CHECKED(literals_index, args[1]);
383
  CONVERT_ARG_CHECKED(FixedArray, elements, 2);
384

    
385
  Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements);
386
  if (object.is_null()) return Failure::Exception();
387

    
388
  // Update the functions literal and return the boilerplate.
389
  literals->set(literals_index, *object);
390
  return *object;
391
}
392

    
393

    
394
static Object* Runtime_CreateCatchExtensionObject(Arguments args) {
395
  ASSERT(args.length() == 2);
396
  CONVERT_CHECKED(String, key, args[0]);
397
  Object* value = args[1];
398
  // Create a catch context extension object.
399
  JSFunction* constructor =
400
      Top::context()->global_context()->context_extension_function();
401
  Object* object = Heap::AllocateJSObject(constructor);
402
  if (object->IsFailure()) return object;
403
  // Assign the exception value to the catch variable and make sure
404
  // that the catch variable is DontDelete.
405
  value = JSObject::cast(object)->SetProperty(key, value, DONT_DELETE);
406
  if (value->IsFailure()) return value;
407
  return object;
408
}
409

    
410

    
411
static Object* Runtime_ClassOf(Arguments args) {
412
  NoHandleAllocation ha;
413
  ASSERT(args.length() == 1);
414
  Object* obj = args[0];
415
  if (!obj->IsJSObject()) return Heap::null_value();
416
  return JSObject::cast(obj)->class_name();
417
}
418

    
419

    
420
static Object* Runtime_HasStringClass(Arguments args) {
421
  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::String_symbol()));
422
}
423

    
424

    
425
static Object* Runtime_HasDateClass(Arguments args) {
426
  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Date_symbol()));
427
}
428

    
429

    
430
static Object* Runtime_HasArrayClass(Arguments args) {
431
  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Array_symbol()));
432
}
433

    
434

    
435
static Object* Runtime_HasFunctionClass(Arguments args) {
436
  return Heap::ToBoolean(
437
             args[0]->HasSpecificClassOf(Heap::function_class_symbol()));
438
}
439

    
440

    
441
static Object* Runtime_HasNumberClass(Arguments args) {
442
  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Number_symbol()));
443
}
444

    
445

    
446
static Object* Runtime_HasBooleanClass(Arguments args) {
447
  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::Boolean_symbol()));
448
}
449

    
450

    
451
static Object* Runtime_HasArgumentsClass(Arguments args) {
452
  return Heap::ToBoolean(
453
             args[0]->HasSpecificClassOf(Heap::Arguments_symbol()));
454
}
455

    
456

    
457
static Object* Runtime_HasRegExpClass(Arguments args) {
458
  return Heap::ToBoolean(args[0]->HasSpecificClassOf(Heap::RegExp_symbol()));
459
}
460

    
461

    
462
static Object* Runtime_IsInPrototypeChain(Arguments args) {
463
  NoHandleAllocation ha;
464
  ASSERT(args.length() == 2);
465
  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
466
  Object* O = args[0];
467
  Object* V = args[1];
468
  while (true) {
469
    Object* prototype = V->GetPrototype();
470
    if (prototype->IsNull()) return Heap::false_value();
471
    if (O == prototype) return Heap::true_value();
472
    V = prototype;
473
  }
474
}
475

    
476

    
477
static Object* Runtime_IsConstructCall(Arguments args) {
478
  NoHandleAllocation ha;
479
  ASSERT(args.length() == 0);
480
  JavaScriptFrameIterator it;
481
  return Heap::ToBoolean(it.frame()->IsConstructor());
482
}
483

    
484

    
485
static Object* Runtime_RegExpCompile(Arguments args) {
486
  HandleScope scope;
487
  ASSERT(args.length() == 3);
488
  CONVERT_CHECKED(JSRegExp, raw_re, args[0]);
489
  Handle<JSRegExp> re(raw_re);
490
  CONVERT_CHECKED(String, raw_pattern, args[1]);
491
  Handle<String> pattern(raw_pattern);
492
  CONVERT_CHECKED(String, raw_flags, args[2]);
493
  Handle<String> flags(raw_flags);
494
  Handle<Object> result = RegExpImpl::Compile(re, pattern, flags);
495
  if (result.is_null()) return Failure::Exception();
496
  return *result;
497
}
498

    
499

    
500
static Object* Runtime_CreateApiFunction(Arguments args) {
501
  HandleScope scope;
502
  ASSERT(args.length() == 1);
503
  CONVERT_CHECKED(FunctionTemplateInfo, raw_data, args[0]);
504
  Handle<FunctionTemplateInfo> data(raw_data);
505
  return *Factory::CreateApiFunction(data);
506
}
507

    
508

    
509
static Object* Runtime_IsTemplate(Arguments args) {
510
  ASSERT(args.length() == 1);
511
  Object* arg = args[0];
512
  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
513
  return Heap::ToBoolean(result);
514
}
515

    
516

    
517
static Object* Runtime_GetTemplateField(Arguments args) {
518
  ASSERT(args.length() == 2);
519
  CONVERT_CHECKED(HeapObject, templ, args[0]);
520
  CONVERT_CHECKED(Smi, field, args[1]);
521
  int index = field->value();
522
  int offset = index * kPointerSize + HeapObject::kHeaderSize;
523
  InstanceType type = templ->map()->instance_type();
524
  RUNTIME_ASSERT(type ==  FUNCTION_TEMPLATE_INFO_TYPE ||
525
                 type ==  OBJECT_TEMPLATE_INFO_TYPE);
526
  RUNTIME_ASSERT(offset > 0);
527
  if (type ==  FUNCTION_TEMPLATE_INFO_TYPE) {
528
    RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
529
  } else {
530
    RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
531
  }
532
  return *HeapObject::RawField(templ, offset);
533
}
534

    
535

    
536
static Object* Runtime_DisableAccessChecks(Arguments args) {
537
  ASSERT(args.length() == 1);
538
  CONVERT_CHECKED(HeapObject, object, args[0]);
539
  Map* old_map = object->map();
540
  bool needs_access_checks = old_map->is_access_check_needed();
541
  if (needs_access_checks) {
542
    // Copy map so it won't interfere constructor's initial map.
543
    Object* new_map = old_map->CopyDropTransitions();
544
    if (new_map->IsFailure()) return new_map;
545

    
546
    Map::cast(new_map)->set_is_access_check_needed(false);
547
    object->set_map(Map::cast(new_map));
548
  }
549
  return needs_access_checks ? Heap::true_value() : Heap::false_value();
550
}
551

    
552

    
553
static Object* Runtime_EnableAccessChecks(Arguments args) {
554
  ASSERT(args.length() == 1);
555
  CONVERT_CHECKED(HeapObject, object, args[0]);
556
  Map* old_map = object->map();
557
  if (!old_map->is_access_check_needed()) {
558
    // Copy map so it won't interfere constructor's initial map.
559
    Object* new_map = old_map->CopyDropTransitions();
560
    if (new_map->IsFailure()) return new_map;
561

    
562
    Map::cast(new_map)->set_is_access_check_needed(true);
563
    object->set_map(Map::cast(new_map));
564
  }
565
  return Heap::undefined_value();
566
}
567

    
568

    
569
static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
570
  HandleScope scope;
571
  Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
572
  Handle<Object> args[2] = { type_handle, name };
573
  Handle<Object> error =
574
      Factory::NewTypeError("redeclaration", HandleVector(args, 2));
575
  return Top::Throw(*error);
576
}
577

    
578

    
579
static Object* Runtime_DeclareGlobals(Arguments args) {
580
  HandleScope scope;
581
  Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());
582

    
583
  CONVERT_ARG_CHECKED(FixedArray, pairs, 0);
584
  Handle<Context> context = args.at<Context>(1);
585
  bool is_eval = Smi::cast(args[2])->value() == 1;
586

    
587
  // Compute the property attributes. According to ECMA-262, section
588
  // 13, page 71, the property must be read-only and
589
  // non-deletable. However, neither SpiderMonkey nor KJS creates the
590
  // property as read-only, so we don't either.
591
  PropertyAttributes base = is_eval ? NONE : DONT_DELETE;
592

    
593
  // Only optimize the object if we intend to add more than 5 properties.
594
  OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2 > 5);
595

    
596
  // Traverse the name/value pairs and set the properties.
597
  int length = pairs->length();
598
  for (int i = 0; i < length; i += 2) {
599
    HandleScope scope;
600
    Handle<String> name(String::cast(pairs->get(i)));
601
    Handle<Object> value(pairs->get(i + 1));
602

    
603
    // We have to declare a global const property. To capture we only
604
    // assign to it when evaluating the assignment for "const x =
605
    // <expr>" the initial value is the hole.
606
    bool is_const_property = value->IsTheHole();
607

    
608
    if (value->IsUndefined() || is_const_property) {
609
      // Lookup the property in the global object, and don't set the
610
      // value of the variable if the property is already there.
611
      LookupResult lookup;
612
      global->Lookup(*name, &lookup);
613
      if (lookup.IsProperty()) {
614
        // Determine if the property is local by comparing the holder
615
        // against the global object. The information will be used to
616
        // avoid throwing re-declaration errors when declaring
617
        // variables or constants that exist in the prototype chain.
618
        bool is_local = (*global == lookup.holder());
619
        // Get the property attributes and determine if the property is
620
        // read-only.
621
        PropertyAttributes attributes = global->GetPropertyAttribute(*name);
622
        bool is_read_only = (attributes & READ_ONLY) != 0;
623
        if (lookup.type() == INTERCEPTOR) {
624
          // If the interceptor says the property is there, we
625
          // just return undefined without overwriting the property.
626
          // Otherwise, we continue to setting the property.
627
          if (attributes != ABSENT) {
628
            // Check if the existing property conflicts with regards to const.
629
            if (is_local && (is_read_only || is_const_property)) {
630
              const char* type = (is_read_only) ? "const" : "var";
631
              return ThrowRedeclarationError(type, name);
632
            };
633
            // The property already exists without conflicting: Go to
634
            // the next declaration.
635
            continue;
636
          }
637
          // Fall-through and introduce the absent property by using
638
          // SetProperty.
639
        } else {
640
          if (is_local && (is_read_only || is_const_property)) {
641
            const char* type = (is_read_only) ? "const" : "var";
642
            return ThrowRedeclarationError(type, name);
643
          }
644
          // The property already exists without conflicting: Go to
645
          // the next declaration.
646
          continue;
647
        }
648
      }
649
    } else {
650
      // Copy the function and update its context. Use it as value.
651
      Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(value);
652
      Handle<JSFunction> function =
653
          Factory::NewFunctionFromBoilerplate(boilerplate, context);
654
      value = function;
655
    }
656

    
657
    LookupResult lookup;
658
    global->LocalLookup(*name, &lookup);
659

    
660
    PropertyAttributes attributes = is_const_property
661
        ? static_cast<PropertyAttributes>(base | READ_ONLY)
662
        : base;
663

    
664
    if (lookup.IsProperty()) {
665
      // There's a local property that we need to overwrite because
666
      // we're either declaring a function or there's an interceptor
667
      // that claims the property is absent.
668

    
669
      // Check for conflicting re-declarations. We cannot have
670
      // conflicting types in case of intercepted properties because
671
      // they are absent.
672
      if (lookup.type() != INTERCEPTOR &&
673
          (lookup.IsReadOnly() || is_const_property)) {
674
        const char* type = (lookup.IsReadOnly()) ? "const" : "var";
675
        return ThrowRedeclarationError(type, name);
676
      }
677
      SetProperty(global, name, value, attributes);
678
    } else {
679
      // If a property with this name does not already exist on the
680
      // global object add the property locally.  We take special
681
      // precautions to always add it as a local property even in case
682
      // of callbacks in the prototype chain (this rules out using
683
      // SetProperty).  Also, we must use the handle-based version to
684
      // avoid GC issues.
685
      IgnoreAttributesAndSetLocalProperty(global, name, value, attributes);
686
    }
687
  }
688

    
689
  return Heap::undefined_value();
690
}
691

    
692

    
693
static Object* Runtime_DeclareContextSlot(Arguments args) {
694
  HandleScope scope;
695
  ASSERT(args.length() == 4);
696

    
697
  CONVERT_ARG_CHECKED(Context, context, 0);
698
  Handle<String> name(String::cast(args[1]));
699
  PropertyAttributes mode =
700
      static_cast<PropertyAttributes>(Smi::cast(args[2])->value());
701
  ASSERT(mode == READ_ONLY || mode == NONE);
702
  Handle<Object> initial_value(args[3]);
703

    
704
  // Declarations are always done in the function context.
705
  context = Handle<Context>(context->fcontext());
706

    
707
  int index;
708
  PropertyAttributes attributes;
709
  ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
710
  Handle<Object> holder =
711
      context->Lookup(name, flags, &index, &attributes);
712

    
713
  if (attributes != ABSENT) {
714
    // The name was declared before; check for conflicting
715
    // re-declarations: This is similar to the code in parser.cc in
716
    // the AstBuildingParser::Declare function.
717
    if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
718
      // Functions are not read-only.
719
      ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
720
      const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
721
      return ThrowRedeclarationError(type, name);
722
    }
723

    
724
    // Initialize it if necessary.
725
    if (*initial_value != NULL) {
726
      if (index >= 0) {
727
        // The variable or constant context slot should always be in
728
        // the function context; not in any outer context nor in the
729
        // arguments object.
730
        ASSERT(holder.is_identical_to(context));
731
        if (((attributes & READ_ONLY) == 0) ||
732
            context->get(index)->IsTheHole()) {
733
          context->set(index, *initial_value);
734
        }
735
      } else {
736
        // Slow case: The property is not in the FixedArray part of the context.
737
        Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
738
        SetProperty(context_ext, name, initial_value, mode);
739
      }
740
    }
741

    
742
  } else {
743
    // The property is not in the function context. It needs to be
744
    // "declared" in the function context's extension context, or in the
745
    // global context.
746
    Handle<JSObject> context_ext;
747
    if (context->has_extension()) {
748
      // The function context's extension context exists - use it.
749
      context_ext = Handle<JSObject>(context->extension());
750
    } else {
751
      // The function context's extension context does not exists - allocate
752
      // it.
753
      context_ext = Factory::NewJSObject(Top::context_extension_function());
754
      // And store it in the extension slot.
755
      context->set_extension(*context_ext);
756
    }
757
    ASSERT(*context_ext != NULL);
758

    
759
    // Declare the property by setting it to the initial value if provided,
760
    // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
761
    // constant declarations).
762
    ASSERT(!context_ext->HasLocalProperty(*name));
763
    Handle<Object> value(Heap::undefined_value());
764
    if (*initial_value != NULL) value = initial_value;
765
    SetProperty(context_ext, name, value, mode);
766
    ASSERT(context_ext->GetLocalPropertyAttribute(*name) == mode);
767
  }
768

    
769
  return Heap::undefined_value();
770
}
771

    
772

    
773
static Object* Runtime_InitializeVarGlobal(Arguments args) {
774
  NoHandleAllocation nha;
775

    
776
  // Determine if we need to assign to the variable if it already
777
  // exists (based on the number of arguments).
778
  RUNTIME_ASSERT(args.length() == 1 || args.length() == 2);
779
  bool assign = args.length() == 2;
780

    
781
  CONVERT_ARG_CHECKED(String, name, 0);
782
  GlobalObject* global = Top::context()->global();
783

    
784
  // According to ECMA-262, section 12.2, page 62, the property must
785
  // not be deletable.
786
  PropertyAttributes attributes = DONT_DELETE;
787

    
788
  // Lookup the property locally in the global object. If it isn't
789
  // there, we add the property and take special precautions to always
790
  // add it as a local property even in case of callbacks in the
791
  // prototype chain (this rules out using SetProperty).
792
  // We have IgnoreAttributesAndSetLocalProperty for this.
793
  LookupResult lookup;
794
  global->LocalLookup(*name, &lookup);
795
  if (!lookup.IsProperty()) {
796
    Object* value = (assign) ? args[1] : Heap::undefined_value();
797
    return global->IgnoreAttributesAndSetLocalProperty(*name,
798
                                                       value,
799
                                                       attributes);
800
  }
801

    
802
  // Determine if this is a redeclaration of something read-only.
803
  if (lookup.IsReadOnly()) {
804
    return ThrowRedeclarationError("const", name);
805
  }
806

    
807
  // Determine if this is a redeclaration of an intercepted read-only
808
  // property and figure out if the property exists at all.
809
  bool found = true;
810
  PropertyType type = lookup.type();
811
  if (type == INTERCEPTOR) {
812
    PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
813
    if (intercepted == ABSENT) {
814
      // The interceptor claims the property isn't there. We need to
815
      // make sure to introduce it.
816
      found = false;
817
    } else if ((intercepted & READ_ONLY) != 0) {
818
      // The property is present, but read-only. Since we're trying to
819
      // overwrite it with a variable declaration we must throw a
820
      // re-declaration error.
821
      return ThrowRedeclarationError("const", name);
822
    }
823
    // Restore global object from context (in case of GC).
824
    global = Top::context()->global();
825
  }
826

    
827
  if (found && !assign) {
828
    // The global property is there and we're not assigning any value
829
    // to it. Just return.
830
    return Heap::undefined_value();
831
  }
832

    
833
  // Assign the value (or undefined) to the property.
834
  Object* value = (assign) ? args[1] : Heap::undefined_value();
835
  return global->SetProperty(&lookup, *name, value, attributes);
836
}
837

    
838

    
839
static Object* Runtime_InitializeConstGlobal(Arguments args) {
840
  // All constants are declared with an initial value. The name
841
  // of the constant is the first argument and the initial value
842
  // is the second.
843
  RUNTIME_ASSERT(args.length() == 2);
844
  CONVERT_ARG_CHECKED(String, name, 0);
845
  Handle<Object> value = args.at<Object>(1);
846

    
847
  // Get the current global object from top.
848
  GlobalObject* global = Top::context()->global();
849

    
850
  // According to ECMA-262, section 12.2, page 62, the property must
851
  // not be deletable. Since it's a const, it must be READ_ONLY too.
852
  PropertyAttributes attributes =
853
      static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
854

    
855
  // Lookup the property locally in the global object. If it isn't
856
  // there, we add the property and take special precautions to always
857
  // add it as a local property even in case of callbacks in the
858
  // prototype chain (this rules out using SetProperty).
859
  // We use IgnoreAttributesAndSetLocalProperty instead
860
  LookupResult lookup;
861
  global->LocalLookup(*name, &lookup);
862
  if (!lookup.IsProperty()) {
863
    return global->IgnoreAttributesAndSetLocalProperty(*name,
864
                                                       *value,
865
                                                       attributes);
866
  }
867

    
868
  // Determine if this is a redeclaration of something not
869
  // read-only. In case the result is hidden behind an interceptor we
870
  // need to ask it for the property attributes.
871
  if (!lookup.IsReadOnly()) {
872
    if (lookup.type() != INTERCEPTOR) {
873
      return ThrowRedeclarationError("var", name);
874
    }
875

    
876
    PropertyAttributes intercepted = global->GetPropertyAttribute(*name);
877

    
878
    // Throw re-declaration error if the intercepted property is present
879
    // but not read-only.
880
    if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
881
      return ThrowRedeclarationError("var", name);
882
    }
883

    
884
    // Restore global object from context (in case of GC) and continue
885
    // with setting the value because the property is either absent or
886
    // read-only. We also have to do redo the lookup.
887
    global = Top::context()->global();
888

    
889
    // BUG 1213579: Handle the case where we have to set a read-only
890
    // property through an interceptor and only do it if it's
891
    // uninitialized, e.g. the hole. Nirk...
892
    global->SetProperty(*name, *value, attributes);
893
    return *value;
894
  }
895

    
896
  // Set the value, but only we're assigning the initial value to a
897
  // constant. For now, we determine this by checking if the
898
  // current value is the hole.
899
  PropertyType type = lookup.type();
900
  if (type == FIELD) {
901
    FixedArray* properties = global->properties();
902
    int index = lookup.GetFieldIndex();
903
    if (properties->get(index)->IsTheHole()) {
904
      properties->set(index, *value);
905
    }
906
  } else if (type == NORMAL) {
907
    Dictionary* dictionary = global->property_dictionary();
908
    int entry = lookup.GetDictionaryEntry();
909
    if (dictionary->ValueAt(entry)->IsTheHole()) {
910
      dictionary->ValueAtPut(entry, *value);
911
    }
912
  } else {
913
    // Ignore re-initialization of constants that have already been
914
    // assigned a function value.
915
    ASSERT(lookup.IsReadOnly() && type == CONSTANT_FUNCTION);
916
  }
917

    
918
  // Use the set value as the result of the operation.
919
  return *value;
920
}
921

    
922

    
923
static Object* Runtime_InitializeConstContextSlot(Arguments args) {
924
  HandleScope scope;
925
  ASSERT(args.length() == 3);
926

    
927
  Handle<Object> value(args[0]);
928
  ASSERT(!value->IsTheHole());
929
  CONVERT_ARG_CHECKED(Context, context, 1);
930
  Handle<String> name(String::cast(args[2]));
931

    
932
  // Initializations are always done in the function context.
933
  context = Handle<Context>(context->fcontext());
934

    
935
  int index;
936
  PropertyAttributes attributes;
937
  ContextLookupFlags flags = FOLLOW_CHAINS;
938
  Handle<Object> holder =
939
      context->Lookup(name, flags, &index, &attributes);
940

    
941
  // In most situations, the property introduced by the const
942
  // declaration should be present in the context extension object.
943
  // However, because declaration and initialization are separate, the
944
  // property might have been deleted (if it was introduced by eval)
945
  // before we reach the initialization point.
946
  //
947
  // Example:
948
  //
949
  //    function f() { eval("delete x; const x;"); }
950
  //
951
  // In that case, the initialization behaves like a normal assignment
952
  // to property 'x'.
953
  if (index >= 0) {
954
    // Property was found in a context.
955
    if (holder->IsContext()) {
956
      // The holder cannot be the function context.  If it is, there
957
      // should have been a const redeclaration error when declaring
958
      // the const property.
959
      ASSERT(!holder.is_identical_to(context));
960
      if ((attributes & READ_ONLY) == 0) {
961
        Handle<Context>::cast(holder)->set(index, *value);
962
      }
963
    } else {
964
      // The holder is an arguments object.
965
      ASSERT((attributes & READ_ONLY) == 0);
966
      Handle<JSObject>::cast(holder)->SetElement(index, *value);
967
    }
968
    return *value;
969
  }
970

    
971
  // The property could not be found, we introduce it in the global
972
  // context.
973
  if (attributes == ABSENT) {
974
    Handle<JSObject> global = Handle<JSObject>(Top::context()->global());
975
    SetProperty(global, name, value, NONE);
976
    return *value;
977
  }
978

    
979
  // The property was present in a context extension object.
980
  Handle<JSObject> context_ext = Handle<JSObject>::cast(holder);
981

    
982
  if (*context_ext == context->extension()) {
983
    // This is the property that was introduced by the const
984
    // declaration.  Set it if it hasn't been set before.  NOTE: We
985
    // cannot use GetProperty() to get the current value as it
986
    // 'unholes' the value.
987
    LookupResult lookup;
988
    context_ext->LocalLookupRealNamedProperty(*name, &lookup);
989
    ASSERT(lookup.IsProperty());  // the property was declared
990
    ASSERT(lookup.IsReadOnly());  // and it was declared as read-only
991

    
992
    PropertyType type = lookup.type();
993
    if (type == FIELD) {
994
      FixedArray* properties = context_ext->properties();
995
      int index = lookup.GetFieldIndex();
996
      if (properties->get(index)->IsTheHole()) {
997
        properties->set(index, *value);
998
      }
999
    } else if (type == NORMAL) {
1000
      Dictionary* dictionary = context_ext->property_dictionary();
1001
      int entry = lookup.GetDictionaryEntry();
1002
      if (dictionary->ValueAt(entry)->IsTheHole()) {
1003
        dictionary->ValueAtPut(entry, *value);
1004
      }
1005
    } else {
1006
      // We should not reach here. Any real, named property should be
1007
      // either a field or a dictionary slot.
1008
      UNREACHABLE();
1009
    }
1010
  } else {
1011
    // The property was found in a different context extension object.
1012
    // Set it if it is not a read-only property.
1013
    if ((attributes & READ_ONLY) == 0) {
1014
      Handle<Object> set = SetProperty(context_ext, name, value, attributes);
1015
      // Setting a property might throw an exception.  Exceptions
1016
      // are converted to empty handles in handle operations.  We
1017
      // need to convert back to exceptions here.
1018
      if (set.is_null()) {
1019
        ASSERT(Top::has_pending_exception());
1020
        return Failure::Exception();
1021
      }
1022
    }
1023
  }
1024

    
1025
  return *value;
1026
}
1027

    
1028

    
1029
static Object* Runtime_RegExpExec(Arguments args) {
1030
  HandleScope scope;
1031
  ASSERT(args.length() == 4);
1032
  CONVERT_CHECKED(JSRegExp, raw_regexp, args[0]);
1033
  Handle<JSRegExp> regexp(raw_regexp);
1034
  CONVERT_CHECKED(String, raw_subject, args[1]);
1035
  Handle<String> subject(raw_subject);
1036
  // Due to the way the JS files are constructed this must be less than the
1037
  // length of a string, i.e. it is always a Smi.  We check anyway for security.
1038
  CONVERT_CHECKED(Smi, index, args[2]);
1039
  CONVERT_CHECKED(JSArray, raw_last_match_info, args[3]);
1040
  Handle<JSArray> last_match_info(raw_last_match_info);
1041
  RUNTIME_ASSERT(last_match_info->HasFastElements());
1042
  RUNTIME_ASSERT(index->value() >= 0);
1043
  RUNTIME_ASSERT(index->value() <= subject->length());
1044
  Handle<Object> result = RegExpImpl::Exec(regexp,
1045
                                           subject,
1046
                                           index->value(),
1047
                                           last_match_info);
1048
  if (result.is_null()) return Failure::Exception();
1049
  return *result;
1050
}
1051

    
1052

    
1053
static Object* Runtime_MaterializeRegExpLiteral(Arguments args) {
1054
  HandleScope scope;
1055
  ASSERT(args.length() == 4);
1056
  CONVERT_ARG_CHECKED(FixedArray, literals, 0);
1057
  int index = Smi::cast(args[1])->value();
1058
  Handle<String> pattern = args.at<String>(2);
1059
  Handle<String> flags = args.at<String>(3);
1060

    
1061
  // Get the RegExp function from the context in the literals array.
1062
  // This is the RegExp function from the context in which the
1063
  // function was created.  We do not use the RegExp function from the
1064
  // current global context because this might be the RegExp function
1065
  // from another context which we should not have access to.
1066
  Handle<JSFunction> constructor =
1067
      Handle<JSFunction>(
1068
          JSFunction::GlobalContextFromLiterals(*literals)->regexp_function());
1069
  // Compute the regular expression literal.
1070
  bool has_pending_exception;
1071
  Handle<Object> regexp =
1072
      RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
1073
                                      &has_pending_exception);
1074
  if (has_pending_exception) {
1075
    ASSERT(Top::has_pending_exception());
1076
    return Failure::Exception();
1077
  }
1078
  literals->set(index, *regexp);
1079
  return *regexp;
1080
}
1081

    
1082

    
1083
static Object* Runtime_FunctionGetName(Arguments args) {
1084
  NoHandleAllocation ha;
1085
  ASSERT(args.length() == 1);
1086

    
1087
  CONVERT_CHECKED(JSFunction, f, args[0]);
1088
  return f->shared()->name();
1089
}
1090

    
1091

    
1092
static Object* Runtime_FunctionSetName(Arguments args) {
1093
  NoHandleAllocation ha;
1094
  ASSERT(args.length() == 2);
1095

    
1096
  CONVERT_CHECKED(JSFunction, f, args[0]);
1097
  CONVERT_CHECKED(String, name, args[1]);
1098
  f->shared()->set_name(name);
1099
  return Heap::undefined_value();
1100
}
1101

    
1102

    
1103
static Object* Runtime_FunctionGetScript(Arguments args) {
1104
  HandleScope scope;
1105
  ASSERT(args.length() == 1);
1106

    
1107
  CONVERT_CHECKED(JSFunction, fun, args[0]);
1108
  Handle<Object> script = Handle<Object>(fun->shared()->script());
1109
  if (!script->IsScript()) return Heap::undefined_value();
1110

    
1111
  return *GetScriptWrapper(Handle<Script>::cast(script));
1112
}
1113

    
1114

    
1115
static Object* Runtime_FunctionGetSourceCode(Arguments args) {
1116
  NoHandleAllocation ha;
1117
  ASSERT(args.length() == 1);
1118

    
1119
  CONVERT_CHECKED(JSFunction, f, args[0]);
1120
  return f->shared()->GetSourceCode();
1121
}
1122

    
1123

    
1124
static Object* Runtime_FunctionGetScriptSourcePosition(Arguments args) {
1125
  NoHandleAllocation ha;
1126
  ASSERT(args.length() == 1);
1127

    
1128
  CONVERT_CHECKED(JSFunction, fun, args[0]);
1129
  int pos = fun->shared()->start_position();
1130
  return Smi::FromInt(pos);
1131
}
1132

    
1133

    
1134
static Object* Runtime_FunctionSetInstanceClassName(Arguments args) {
1135
  NoHandleAllocation ha;
1136
  ASSERT(args.length() == 2);
1137

    
1138
  CONVERT_CHECKED(JSFunction, fun, args[0]);
1139
  CONVERT_CHECKED(String, name, args[1]);
1140
  fun->SetInstanceClassName(name);
1141
  return Heap::undefined_value();
1142
}
1143

    
1144

    
1145
static Object* Runtime_FunctionSetLength(Arguments args) {
1146
  NoHandleAllocation ha;
1147
  ASSERT(args.length() == 2);
1148

    
1149
  CONVERT_CHECKED(JSFunction, fun, args[0]);
1150
  CONVERT_CHECKED(Smi, length, args[1]);
1151
  fun->shared()->set_length(length->value());
1152
  return length;
1153
}
1154

    
1155

    
1156
static Object* Runtime_FunctionSetPrototype(Arguments args) {
1157
  NoHandleAllocation ha;
1158
  ASSERT(args.length() == 2);
1159

    
1160
  CONVERT_CHECKED(JSFunction, fun, args[0]);
1161
  Object* obj = Accessors::FunctionSetPrototype(fun, args[1], NULL);
1162
  if (obj->IsFailure()) return obj;
1163
  return args[0];  // return TOS
1164
}
1165

    
1166

    
1167
static Object* Runtime_FunctionIsAPIFunction(Arguments args) {
1168
  NoHandleAllocation ha;
1169
  ASSERT(args.length() == 1);
1170

    
1171
  CONVERT_CHECKED(JSFunction, f, args[0]);
1172
  // The function_data field of the shared function info is used exclusively by
1173
  // the API.
1174
  return !f->shared()->function_data()->IsUndefined() ? Heap::true_value()
1175
                                                      : Heap::false_value();
1176
}
1177

    
1178

    
1179
static Object* Runtime_SetCode(Arguments args) {
1180
  HandleScope scope;
1181
  ASSERT(args.length() == 2);
1182

    
1183
  CONVERT_CHECKED(JSFunction, raw_target, args[0]);
1184
  Handle<JSFunction> target(raw_target);
1185
  Handle<Object> code = args.at<Object>(1);
1186

    
1187
  Handle<Context> context(target->context());
1188

    
1189
  if (!code->IsNull()) {
1190
    RUNTIME_ASSERT(code->IsJSFunction());
1191
    Handle<JSFunction> fun = Handle<JSFunction>::cast(code);
1192
    SetExpectedNofProperties(target, fun->shared()->expected_nof_properties());
1193
    if (!fun->is_compiled() && !CompileLazy(fun, KEEP_EXCEPTION)) {
1194
      return Failure::Exception();
1195
    }
1196
    // Set the code, formal parameter count, and the length of the target
1197
    // function.
1198
    target->set_code(fun->code());
1199
    target->shared()->set_length(fun->shared()->length());
1200
    target->shared()->set_formal_parameter_count(
1201
        fun->shared()->formal_parameter_count());
1202
    // Set the source code of the target function to undefined.
1203
    // SetCode is only used for built-in constructors like String,
1204
    // Array, and Object, and some web code
1205
    // doesn't like seeing source code for constructors.
1206
    target->shared()->set_script(Heap::undefined_value());
1207
    context = Handle<Context>(fun->context());
1208

    
1209
    // Make sure we get a fresh copy of the literal vector to avoid
1210
    // cross context contamination.
1211
    int number_of_literals = fun->NumberOfLiterals();
1212
    Handle<FixedArray> literals =
1213
        Factory::NewFixedArray(number_of_literals, TENURED);
1214
    if (number_of_literals > 0) {
1215
      // Insert the object, regexp and array functions in the literals
1216
      // array prefix.  These are the functions that will be used when
1217
      // creating object, regexp and array literals.
1218
      literals->set(JSFunction::kLiteralGlobalContextIndex,
1219
                    context->global_context());
1220
    }
1221
    target->set_literals(*literals, SKIP_WRITE_BARRIER);
1222
  }
1223

    
1224
  target->set_context(*context);
1225
  return *target;
1226
}
1227

    
1228

    
1229
static Object* CharCodeAt(String* subject, Object* index) {
1230
  uint32_t i = 0;
1231
  if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
1232
  // Flatten the string.  If someone wants to get a char at an index
1233
  // in a cons string, it is likely that more indices will be
1234
  // accessed.
1235
  subject->TryFlattenIfNotFlat();
1236
  if (i >= static_cast<uint32_t>(subject->length())) {
1237
    return Heap::nan_value();
1238
  }
1239
  return Smi::FromInt(subject->Get(i));
1240
}
1241

    
1242

    
1243
static Object* Runtime_StringCharCodeAt(Arguments args) {
1244
  NoHandleAllocation ha;
1245
  ASSERT(args.length() == 2);
1246

    
1247
  CONVERT_CHECKED(String, subject, args[0]);
1248
  Object* index = args[1];
1249
  return CharCodeAt(subject, index);
1250
}
1251

    
1252

    
1253
static Object* Runtime_CharFromCode(Arguments args) {
1254
  NoHandleAllocation ha;
1255
  ASSERT(args.length() == 1);
1256
  uint32_t code;
1257
  if (Array::IndexFromObject(args[0], &code)) {
1258
    if (code <= 0xffff) {
1259
      return Heap::LookupSingleCharacterStringFromCode(code);
1260
    }
1261
  }
1262
  return Heap::empty_string();
1263
}
1264

    
1265
// Forward declarations.
1266
static const int kStringBuilderConcatHelperLengthBits = 11;
1267
static const int kStringBuilderConcatHelperPositionBits = 19;
1268

    
1269
template <typename schar>
1270
static inline void StringBuilderConcatHelper(String*,
1271
                                             schar*,
1272
                                             FixedArray*,
1273
                                             int);
1274

    
1275
typedef BitField<int, 0, 11> StringBuilderSubstringLength;
1276
typedef BitField<int, 11, 19> StringBuilderSubstringPosition;
1277

    
1278
class ReplacementStringBuilder {
1279
 public:
1280
  ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
1281
      : subject_(subject),
1282
        parts_(Factory::NewFixedArray(estimated_part_count)),
1283
        part_count_(0),
1284
        character_count_(0),
1285
        is_ascii_(StringShape(*subject).IsAsciiRepresentation()) {
1286
    // Require a non-zero initial size. Ensures that doubling the size to
1287
    // extend the array will work.
1288
    ASSERT(estimated_part_count > 0);
1289
  }
1290

    
1291
  void EnsureCapacity(int elements) {
1292
    int length = parts_->length();
1293
    int required_length = part_count_ + elements;
1294
    if (length < required_length) {
1295
      int new_length = length;
1296
      do {
1297
        new_length *= 2;
1298
      } while (new_length < required_length);
1299
      Handle<FixedArray> extended_array =
1300
          Factory::NewFixedArray(new_length);
1301
      parts_->CopyTo(0, *extended_array, 0, part_count_);
1302
      parts_ = extended_array;
1303
    }
1304
  }
1305

    
1306
  void AddSubjectSlice(int from, int to) {
1307
    ASSERT(from >= 0);
1308
    int length = to - from;
1309
    ASSERT(length > 0);
1310
    // Can we encode the slice in 11 bits for length and 19 bits for
1311
    // start position - as used by StringBuilderConcatHelper?
1312
    if (StringBuilderSubstringLength::is_valid(length) &&
1313
        StringBuilderSubstringPosition::is_valid(from)) {
1314
      int encoded_slice = StringBuilderSubstringLength::encode(length) |
1315
          StringBuilderSubstringPosition::encode(from);
1316
      AddElement(Smi::FromInt(encoded_slice));
1317
    } else {
1318
      Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
1319
      AddElement(*slice);
1320
    }
1321
    IncrementCharacterCount(length);
1322
  }
1323

    
1324

    
1325
  void AddString(Handle<String> string) {
1326
    int length = string->length();
1327
    ASSERT(length > 0);
1328
    AddElement(*string);
1329
    if (!StringShape(*string).IsAsciiRepresentation()) {
1330
      is_ascii_ = false;
1331
    }
1332
    IncrementCharacterCount(length);
1333
  }
1334

    
1335

    
1336
  Handle<String> ToString() {
1337
    if (part_count_ == 0) {
1338
      return Factory::empty_string();
1339
    }
1340

    
1341
    Handle<String> joined_string;
1342
    if (is_ascii_) {
1343
      joined_string = NewRawAsciiString(character_count_);
1344
      AssertNoAllocation no_alloc;
1345
      SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
1346
      char* char_buffer = seq->GetChars();
1347
      StringBuilderConcatHelper(*subject_,
1348
                                char_buffer,
1349
                                *parts_,
1350
                                part_count_);
1351
    } else {
1352
      // Non-ASCII.
1353
      joined_string = NewRawTwoByteString(character_count_);
1354
      AssertNoAllocation no_alloc;
1355
      SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
1356
      uc16* char_buffer = seq->GetChars();
1357
      StringBuilderConcatHelper(*subject_,
1358
                                char_buffer,
1359
                                *parts_,
1360
                                part_count_);
1361
    }
1362
    return joined_string;
1363
  }
1364

    
1365

    
1366
  void IncrementCharacterCount(int by) {
1367
    if (character_count_ > Smi::kMaxValue - by) {
1368
      V8::FatalProcessOutOfMemory("String.replace result too large.");
1369
    }
1370
    character_count_ += by;
1371
  }
1372

    
1373
 private:
1374

    
1375
  Handle<String> NewRawAsciiString(int size) {
1376
    CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
1377
  }
1378

    
1379

    
1380
  Handle<String> NewRawTwoByteString(int size) {
1381
    CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
1382
  }
1383

    
1384

    
1385
  void AddElement(Object* element) {
1386
    ASSERT(element->IsSmi() || element->IsString());
1387
    parts_->set(part_count_, element);
1388
    part_count_++;
1389
  }
1390

    
1391
  Handle<String> subject_;
1392
  Handle<FixedArray> parts_;
1393
  int part_count_;
1394
  int character_count_;
1395
  bool is_ascii_;
1396
};
1397

    
1398

    
1399
class CompiledReplacement {
1400
 public:
1401
  CompiledReplacement()
1402
      : parts_(1), replacement_substrings_(0) {}
1403

    
1404
  void Compile(Handle<String> replacement,
1405
               int capture_count,
1406
               int subject_length);
1407

    
1408
  void Apply(ReplacementStringBuilder* builder,
1409
             int match_from,
1410
             int match_to,
1411
             Handle<JSArray> last_match_info);
1412

    
1413
  // Number of distinct parts of the replacement pattern.
1414
  int parts() {
1415
    return parts_.length();
1416
  }
1417
 private:
1418
  enum PartType {
1419
    SUBJECT_PREFIX = 1,
1420
    SUBJECT_SUFFIX,
1421
    SUBJECT_CAPTURE,
1422
    REPLACEMENT_SUBSTRING,
1423
    REPLACEMENT_STRING,
1424

    
1425
    NUMBER_OF_PART_TYPES
1426
  };
1427

    
1428
  struct ReplacementPart {
1429
    static inline ReplacementPart SubjectMatch() {
1430
      return ReplacementPart(SUBJECT_CAPTURE, 0);
1431
    }
1432
    static inline ReplacementPart SubjectCapture(int capture_index) {
1433
      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
1434
    }
1435
    static inline ReplacementPart SubjectPrefix() {
1436
      return ReplacementPart(SUBJECT_PREFIX, 0);
1437
    }
1438
    static inline ReplacementPart SubjectSuffix(int subject_length) {
1439
      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
1440
    }
1441
    static inline ReplacementPart ReplacementString() {
1442
      return ReplacementPart(REPLACEMENT_STRING, 0);
1443
    }
1444
    static inline ReplacementPart ReplacementSubString(int from, int to) {
1445
      ASSERT(from >= 0);
1446
      ASSERT(to > from);
1447
      return ReplacementPart(-from, to);
1448
    }
1449

    
1450
    // If tag <= 0 then it is the negation of a start index of a substring of
1451
    // the replacement pattern, otherwise it's a value from PartType.
1452
    ReplacementPart(int tag, int data)
1453
        : tag(tag), data(data) {
1454
      // Must be non-positive or a PartType value.
1455
      ASSERT(tag < NUMBER_OF_PART_TYPES);
1456
    }
1457
    // Either a value of PartType or a non-positive number that is
1458
    // the negation of an index into the replacement string.
1459
    int tag;
1460
    // The data value's interpretation depends on the value of tag:
1461
    // tag == SUBJECT_PREFIX ||
1462
    // tag == SUBJECT_SUFFIX:  data is unused.
1463
    // tag == SUBJECT_CAPTURE: data is the number of the capture.
1464
    // tag == REPLACEMENT_SUBSTRING ||
1465
    // tag == REPLACEMENT_STRING:    data is index into array of substrings
1466
    //                               of the replacement string.
1467
    // tag <= 0: Temporary representation of the substring of the replacement
1468
    //           string ranging over -tag .. data.
1469
    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
1470
    //           substring objects.
1471
    int data;
1472
  };
1473

    
1474
  template<typename Char>
1475
  static void ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
1476
                                      Vector<Char> characters,
1477
                                      int capture_count,
1478
                                      int subject_length) {
1479
    int length = characters.length();
1480
    int last = 0;
1481
    for (int i = 0; i < length; i++) {
1482
      Char c = characters[i];
1483
      if (c == '$') {
1484
        int next_index = i + 1;
1485
        if (next_index == length) {  // No next character!
1486
          break;
1487
        }
1488
        Char c2 = characters[next_index];
1489
        switch (c2) {
1490
        case '$':
1491
          if (i > last) {
1492
            // There is a substring before. Include the first "$".
1493
            parts->Add(ReplacementPart::ReplacementSubString(last, next_index));
1494
            last = next_index + 1;  // Continue after the second "$".
1495
          } else {
1496
            // Let the next substring start with the second "$".
1497
            last = next_index;
1498
          }
1499
          i = next_index;
1500
          break;
1501
        case '`':
1502
          if (i > last) {
1503
            parts->Add(ReplacementPart::ReplacementSubString(last, i));
1504
          }
1505
          parts->Add(ReplacementPart::SubjectPrefix());
1506
          i = next_index;
1507
          last = i + 1;
1508
          break;
1509
        case '\'':
1510
          if (i > last) {
1511
            parts->Add(ReplacementPart::ReplacementSubString(last, i));
1512
          }
1513
          parts->Add(ReplacementPart::SubjectSuffix(subject_length));
1514
          i = next_index;
1515
          last = i + 1;
1516
          break;
1517
        case '&':
1518
          if (i > last) {
1519
            parts->Add(ReplacementPart::ReplacementSubString(last, i));
1520
          }
1521
          parts->Add(ReplacementPart::SubjectMatch());
1522
          i = next_index;
1523
          last = i + 1;
1524
          break;
1525
        case '0':
1526
        case '1':
1527
        case '2':
1528
        case '3':
1529
        case '4':
1530
        case '5':
1531
        case '6':
1532
        case '7':
1533
        case '8':
1534
        case '9': {
1535
          int capture_ref = c2 - '0';
1536
          if (capture_ref > capture_count) {
1537
            i = next_index;
1538
            continue;
1539
          }
1540
          int second_digit_index = next_index + 1;
1541
          if (second_digit_index < length) {
1542
            // Peek ahead to see if we have two digits.
1543
            Char c3 = characters[second_digit_index];
1544
            if ('0' <= c3 && c3 <= '9') {  // Double digits.
1545
              int double_digit_ref = capture_ref * 10 + c3 - '0';
1546
              if (double_digit_ref <= capture_count) {
1547
                next_index = second_digit_index;
1548
                capture_ref = double_digit_ref;
1549
              }
1550
            }
1551
          }
1552
          if (capture_ref > 0) {
1553
            if (i > last) {
1554
              parts->Add(ReplacementPart::ReplacementSubString(last, i));
1555
            }
1556
            parts->Add(ReplacementPart::SubjectCapture(capture_ref));
1557
            last = next_index + 1;
1558
          }
1559
          i = next_index;
1560
          break;
1561
        }
1562
        default:
1563
          i = next_index;
1564
          break;
1565
        }
1566
      }
1567
    }
1568
    if (length > last) {
1569
      if (last == 0) {
1570
        parts->Add(ReplacementPart::ReplacementString());
1571
      } else {
1572
        parts->Add(ReplacementPart::ReplacementSubString(last, length));
1573
      }
1574
    }
1575
  }
1576

    
1577
  ZoneList<ReplacementPart> parts_;
1578
  ZoneList<Handle<String> > replacement_substrings_;
1579
};
1580

    
1581

    
1582
void CompiledReplacement::Compile(Handle<String> replacement,
1583
                                  int capture_count,
1584
                                  int subject_length) {
1585
  ASSERT(replacement->IsFlat());
1586
  if (StringShape(*replacement).IsAsciiRepresentation()) {
1587
    AssertNoAllocation no_alloc;
1588
    ParseReplacementPattern(&parts_,
1589
                            replacement->ToAsciiVector(),
1590
                            capture_count,
1591
                            subject_length);
1592
  } else {
1593
    ASSERT(StringShape(*replacement).IsTwoByteRepresentation());
1594
    AssertNoAllocation no_alloc;
1595

    
1596
    ParseReplacementPattern(&parts_,
1597
                            replacement->ToUC16Vector(),
1598
                            capture_count,
1599
                            subject_length);
1600
  }
1601
  // Find substrings of replacement string and create them as String objects..
1602
  int substring_index = 0;
1603
  for (int i = 0, n = parts_.length(); i < n; i++) {
1604
    int tag = parts_[i].tag;
1605
    if (tag <= 0) {  // A replacement string slice.
1606
      int from = -tag;
1607
      int to = parts_[i].data;
1608
      replacement_substrings_.Add(Factory::NewStringSlice(replacement,
1609
                                                          from,
1610
                                                          to));
1611
      parts_[i].tag = REPLACEMENT_SUBSTRING;
1612
      parts_[i].data = substring_index;
1613
      substring_index++;
1614
    } else if (tag == REPLACEMENT_STRING) {
1615
      replacement_substrings_.Add(replacement);
1616
      parts_[i].data = substring_index;
1617
      substring_index++;
1618
    }
1619
  }
1620
}
1621

    
1622

    
1623
void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
1624
                                int match_from,
1625
                                int match_to,
1626
                                Handle<JSArray> last_match_info) {
1627
  for (int i = 0, n = parts_.length(); i < n; i++) {
1628
    ReplacementPart part = parts_[i];
1629
    switch (part.tag) {
1630
      case SUBJECT_PREFIX:
1631
        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
1632
        break;
1633
      case SUBJECT_SUFFIX: {
1634
        int subject_length = part.data;
1635
        if (match_to < subject_length) {
1636
          builder->AddSubjectSlice(match_to, subject_length);
1637
        }
1638
        break;
1639
      }
1640
      case SUBJECT_CAPTURE: {
1641
        int capture = part.data;
1642
        FixedArray* match_info = last_match_info->elements();
1643
        int from = RegExpImpl::GetCapture(match_info, capture * 2);
1644
        int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
1645
        if (from >= 0 && to > from) {
1646
          builder->AddSubjectSlice(from, to);
1647
        }
1648
        break;
1649
      }
1650
      case REPLACEMENT_SUBSTRING:
1651
      case REPLACEMENT_STRING:
1652
        builder->AddString(replacement_substrings_[part.data]);
1653
        break;
1654
      default:
1655
        UNREACHABLE();
1656
    }
1657
  }
1658
}
1659

    
1660

    
1661

    
1662
static Object* StringReplaceRegExpWithString(String* subject,
1663
                                             JSRegExp* regexp,
1664
                                             String* replacement,
1665
                                             JSArray* last_match_info) {
1666
  ASSERT(subject->IsFlat());
1667
  ASSERT(replacement->IsFlat());
1668

    
1669
  HandleScope handles;
1670

    
1671
  int length = subject->length();
1672
  Handle<String> subject_handle(subject);
1673
  Handle<JSRegExp> regexp_handle(regexp);
1674
  Handle<String> replacement_handle(replacement);
1675
  Handle<JSArray> last_match_info_handle(last_match_info);
1676
  Handle<Object> match = RegExpImpl::Exec(regexp_handle,
1677
                                          subject_handle,
1678
                                          0,
1679
                                          last_match_info_handle);
1680
  if (match.is_null()) {
1681
    return Failure::Exception();
1682
  }
1683
  if (match->IsNull()) {
1684
    return *subject_handle;
1685
  }
1686

    
1687
  int capture_count = regexp_handle->CaptureCount();
1688

    
1689
  // CompiledReplacement uses zone allocation.
1690
  ZoneScope zone(DELETE_ON_EXIT);
1691
  CompiledReplacement compiled_replacement;
1692
  compiled_replacement.Compile(replacement_handle,
1693
                               capture_count,
1694
                               length);
1695

    
1696
  bool is_global = regexp_handle->GetFlags().is_global();
1697

    
1698
  // Guessing the number of parts that the final result string is built
1699
  // from. Global regexps can match any number of times, so we guess
1700
  // conservatively.
1701
  int expected_parts =
1702
      (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
1703
  ReplacementStringBuilder builder(subject_handle, expected_parts);
1704

    
1705
  // Index of end of last match.
1706
  int prev = 0;
1707

    
1708
  // Number of parts added by compiled replacement plus preceeding string
1709
  // and possibly suffix after last match.
1710
  const int parts_added_per_loop = compiled_replacement.parts() + 2;
1711
  bool matched = true;
1712
  do {
1713
    ASSERT(last_match_info_handle->HasFastElements());
1714
    // Increase the capacity of the builder before entering local handle-scope,
1715
    // so its internal buffer can safely allocate a new handle if it grows.
1716
    builder.EnsureCapacity(parts_added_per_loop);
1717

    
1718
    HandleScope loop_scope;
1719
    int start, end;
1720
    {
1721
      AssertNoAllocation match_info_array_is_not_in_a_handle;
1722
      FixedArray* match_info_array = last_match_info_handle->elements();
1723

    
1724
      ASSERT_EQ(capture_count * 2 + 2,
1725
                RegExpImpl::GetLastCaptureCount(match_info_array));
1726
      start = RegExpImpl::GetCapture(match_info_array, 0);
1727
      end = RegExpImpl::GetCapture(match_info_array, 1);
1728
    }
1729

    
1730
    if (prev < start) {
1731
      builder.AddSubjectSlice(prev, start);
1732
    }
1733
    compiled_replacement.Apply(&builder,
1734
                               start,
1735
                               end,
1736
                               last_match_info_handle);
1737
    prev = end;
1738

    
1739
    // Only continue checking for global regexps.
1740
    if (!is_global) break;
1741

    
1742
    // Continue from where the match ended, unless it was an empty match.
1743
    int next = end;
1744
    if (start == end) {
1745
      next = end + 1;
1746
      if (next > length) break;
1747
    }
1748

    
1749
    match = RegExpImpl::Exec(regexp_handle,
1750
                             subject_handle,
1751
                             next,
1752
                             last_match_info_handle);
1753
    if (match.is_null()) {
1754
      return Failure::Exception();
1755
    }
1756
    matched = !match->IsNull();
1757
  } while (matched);
1758

    
1759
  if (prev < length) {
1760
    builder.AddSubjectSlice(prev, length);
1761
  }
1762

    
1763
  return *(builder.ToString());
1764
}
1765

    
1766

    
1767
static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
1768
  ASSERT(args.length() == 4);
1769

    
1770
  CONVERT_CHECKED(String, subject, args[0]);
1771
  if (!subject->IsFlat()) {
1772
    Object* flat_subject = subject->TryFlatten();
1773
    if (flat_subject->IsFailure()) {
1774
      return flat_subject;
1775
    }
1776
    subject = String::cast(flat_subject);
1777
  }
1778

    
1779
  CONVERT_CHECKED(String, replacement, args[2]);
1780
  if (!replacement->IsFlat()) {
1781
    Object* flat_replacement = replacement->TryFlatten();
1782
    if (flat_replacement->IsFailure()) {
1783
      return flat_replacement;
1784
    }
1785
    replacement = String::cast(flat_replacement);
1786
  }
1787

    
1788
  CONVERT_CHECKED(JSRegExp, regexp, args[1]);
1789
  CONVERT_CHECKED(JSArray, last_match_info, args[3]);
1790

    
1791
  ASSERT(last_match_info->HasFastElements());
1792

    
1793
  return StringReplaceRegExpWithString(subject,
1794
                                       regexp,
1795
                                       replacement,
1796
                                       last_match_info);
1797
}
1798

    
1799

    
1800

    
1801
// Cap on the maximal shift in the Boyer-Moore implementation. By setting a
1802
// limit, we can fix the size of tables.
1803
static const int kBMMaxShift = 0xff;
1804
// Reduce alphabet to this size.
1805
static const int kBMAlphabetSize = 0x100;
1806
// For patterns below this length, the skip length of Boyer-Moore is too short
1807
// to compensate for the algorithmic overhead compared to simple brute force.
1808
static const int kBMMinPatternLength = 5;
1809

    
1810
// Holds the two buffers used by Boyer-Moore string search's Good Suffix
1811
// shift. Only allows the last kBMMaxShift characters of the needle
1812
// to be indexed.
1813
class BMGoodSuffixBuffers {
1814
 public:
1815
  BMGoodSuffixBuffers() {}
1816
  inline void init(int needle_length) {
1817
    ASSERT(needle_length > 1);
1818
    int start = needle_length < kBMMaxShift ? 0 : needle_length - kBMMaxShift;
1819
    int len = needle_length - start;
1820
    biased_suffixes_ = suffixes_ - start;
1821
    biased_good_suffix_shift_ = good_suffix_shift_ - start;
1822
    for (int i = 0; i <= len; i++) {
1823
      good_suffix_shift_[i] = len;
1824
    }
1825
  }
1826
  inline int& suffix(int index) {
1827
    ASSERT(biased_suffixes_ + index >= suffixes_);
1828
    return biased_suffixes_[index];
1829
  }
1830
  inline int& shift(int index) {
1831
    ASSERT(biased_good_suffix_shift_ + index >= good_suffix_shift_);
1832
    return biased_good_suffix_shift_[index];
1833
  }
1834
 private:
1835
  int suffixes_[kBMMaxShift + 1];
1836
  int good_suffix_shift_[kBMMaxShift + 1];
1837
  int* biased_suffixes_;
1838
  int* biased_good_suffix_shift_;
1839
  DISALLOW_COPY_AND_ASSIGN(BMGoodSuffixBuffers);
1840
};
1841

    
1842
// buffers reused by BoyerMoore
1843
static int bad_char_occurrence[kBMAlphabetSize];
1844
static BMGoodSuffixBuffers bmgs_buffers;
1845

    
1846
// Compute the bad-char table for Boyer-Moore in the static buffer.
1847
template <typename pchar>
1848
static void BoyerMoorePopulateBadCharTable(Vector<const pchar> pattern,
1849
                                          int start) {
1850
  // Run forwards to populate bad_char_table, so that *last* instance
1851
  // of character equivalence class is the one registered.
1852
  // Notice: Doesn't include the last character.
1853
  int table_size = (sizeof(pchar) == 1) ? String::kMaxAsciiCharCode + 1
1854
                                        : kBMAlphabetSize;
1855
  if (start == 0) {  // All patterns less than kBMMaxShift in length.
1856
    memset(bad_char_occurrence, -1, table_size * sizeof(*bad_char_occurrence));
1857
  } else {
1858
    for (int i = 0; i < table_size; i++) {
1859
      bad_char_occurrence[i] = start - 1;
1860
    }
1861
  }
1862
  for (int i = start; i < pattern.length() - 1; i++) {
1863
    pchar c = pattern[i];
1864
    int bucket = (sizeof(pchar) ==1) ? c : c % kBMAlphabetSize;
1865
    bad_char_occurrence[bucket] = i;
1866
  }
1867
}
1868

    
1869
template <typename pchar>
1870
static void BoyerMoorePopulateGoodSuffixTable(Vector<const pchar> pattern,
1871
                                              int start) {
1872
  int m = pattern.length();
1873
  int len = m - start;
1874
  // Compute Good Suffix tables.
1875
  bmgs_buffers.init(m);
1876

    
1877
  bmgs_buffers.shift(m-1) = 1;
1878
  bmgs_buffers.suffix(m) = m + 1;
1879
  pchar last_char = pattern[m - 1];
1880
  int suffix = m + 1;
1881
  for (int i = m; i > start;) {
1882
    for (pchar c = pattern[i - 1]; suffix <= m && c != pattern[suffix - 1];) {
1883
      if (bmgs_buffers.shift(suffix) == len) {
1884
        bmgs_buffers.shift(suffix) = suffix - i;
1885
      }
1886
      suffix = bmgs_buffers.suffix(suffix);
1887
    }
1888
    i--;
1889
    suffix--;
1890
    bmgs_buffers.suffix(i) = suffix;
1891
    if (suffix == m) {
1892
      // No suffix to extend, so we check against last_char only.
1893
      while (i > start && pattern[i - 1] != last_char) {
1894
        if (bmgs_buffers.shift(m) == len) {
1895
          bmgs_buffers.shift(m) = m - i;
1896
        }
1897
        i--;
1898
        bmgs_buffers.suffix(i) = m;
1899
      }
1900
      if (i > start) {
1901
        i--;
1902
        suffix--;
1903
        bmgs_buffers.suffix(i) = suffix;
1904
      }
1905
    }
1906
  }
1907
  if (suffix < m) {
1908
    for (int i = start; i <= m; i++) {
1909
      if (bmgs_buffers.shift(i) == len) {
1910
        bmgs_buffers.shift(i) = suffix - start;
1911
      }
1912
      if (i == suffix) {
1913
        suffix = bmgs_buffers.suffix(suffix);
1914
      }
1915
    }
1916
  }
1917
}
1918

    
1919
template <typename schar, typename pchar>
1920
static inline int CharOccurrence(int char_code) {
1921
  if (sizeof(schar) == 1) {
1922
    return bad_char_occurrence[char_code];
1923
  }
1924
  if (sizeof(pchar) == 1) {
1925
    if (char_code > String::kMaxAsciiCharCode) {
1926
      return -1;
1927
    }
1928
    return bad_char_occurrence[char_code];
1929
  }
1930
  return bad_char_occurrence[char_code % kBMAlphabetSize];
1931
}
1932

    
1933
// Restricted simplified Boyer-Moore string matching.
1934
// Uses only the bad-shift table of Boyer-Moore and only uses it
1935
// for the character compared to the last character of the needle.
1936
template <typename schar, typename pchar>
1937
static int BoyerMooreHorspool(Vector<const schar> subject,
1938
                              Vector<const pchar> pattern,
1939
                              int start_index,
1940
                              bool* complete) {
1941
  int n = subject.length();
1942
  int m = pattern.length();
1943
  // Only preprocess at most kBMMaxShift last characters of pattern.
1944
  int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
1945

    
1946
  BoyerMoorePopulateBadCharTable(pattern, start);
1947

    
1948
  int badness = -m;  // How bad we are doing without a good-suffix table.
1949
  int idx;  // No matches found prior to this index.
1950
  pchar last_char = pattern[m - 1];
1951
  int last_char_shift = m - 1 - CharOccurrence<schar, pchar>(last_char);
1952
  // Perform search
1953
  for (idx = start_index; idx <= n - m;) {
1954
    int j = m - 1;
1955
    int c;
1956
    while (last_char != (c = subject[idx + j])) {
1957
      int bc_occ = CharOccurrence<schar, pchar>(c);
1958
      int shift = j - bc_occ;
1959
      idx += shift;
1960
      badness += 1 - shift;  // at most zero, so badness cannot increase.
1961
      if (idx > n - m) {
1962
        *complete = true;
1963
        return -1;
1964
      }
1965
    }
1966
    j--;
1967
    while (j >= 0 && pattern[j] == (subject[idx + j])) j--;
1968
    if (j < 0) {
1969
      *complete = true;
1970
      return idx;
1971
    } else {
1972
      idx += last_char_shift;
1973
      // Badness increases by the number of characters we have
1974
      // checked, and decreases by the number of characters we
1975
      // can skip by shifting. It's a measure of how we are doing
1976
      // compared to reading each character exactly once.
1977
      badness += (m - j) - last_char_shift;
1978
      if (badness > 0) {
1979
        *complete = false;
1980
        return idx;
1981
      }
1982
    }
1983
  }
1984
  *complete = true;
1985
  return -1;
1986
}
1987

    
1988

    
1989
template <typename schar, typename pchar>
1990
static int BoyerMooreIndexOf(Vector<const schar> subject,
1991
                             Vector<const pchar> pattern,
1992
                             int idx) {
1993
  int n = subject.length();
1994
  int m = pattern.length();
1995
  // Only preprocess at most kBMMaxShift last characters of pattern.
1996
  int start = m < kBMMaxShift ? 0 : m - kBMMaxShift;
1997

    
1998
  // Build the Good Suffix table and continue searching.
1999
  BoyerMoorePopulateGoodSuffixTable(pattern, start);
2000
  pchar last_char = pattern[m - 1];
2001
  // Continue search from i.
2002
  do {
2003
    int j = m - 1;
2004
    schar c;
2005
    while (last_char != (c = subject[idx + j])) {
2006
      int shift = j - CharOccurrence<schar, pchar>(c);
2007
      idx += shift;
2008
      if (idx > n - m) {
2009
        return -1;
2010
      }
2011
    }
2012
    while (j >= 0 && pattern[j] == (c = subject[idx + j])) j--;
2013
    if (j < 0) {
2014
      return idx;
2015
    } else if (j < start) {
2016
      // we have matched more than our tables allow us to be smart about.
2017
      // Fall back on BMH shift.
2018
      idx += m - 1 - CharOccurrence<schar, pchar>(last_char);
2019
    } else {
2020
      int gs_shift = bmgs_buffers.shift(j + 1);       // Good suffix shift.
2021
      int bc_occ = CharOccurrence<schar, pchar>(c);
2022
      int shift = j - bc_occ;                         // Bad-char shift.
2023
      if (gs_shift > shift) {
2024
        shift = gs_shift;
2025
      }
2026
      idx += shift;
2027
    }
2028
  } while (idx <= n - m);
2029

    
2030
  return -1;
2031
}
2032

    
2033

    
2034
template <typename schar>
2035
static int SingleCharIndexOf(Vector<const schar> string,
2036
                             schar pattern_char,
2037
                             int start_index) {
2038
  for (int i = start_index, n = string.length(); i < n; i++) {
2039
    if (pattern_char == string[i]) {
2040
      return i;
2041
    }
2042
  }
2043
  return -1;
2044
}
2045

    
2046
// Trivial string search for shorter strings.
2047
// On return, if "complete" is set to true, the return value is the
2048
// final result of searching for the patter in the subject.
2049
// If "complete" is set to false, the return value is the index where
2050
// further checking should start, i.e., it's guaranteed that the pattern
2051
// does not occur at a position prior to the returned index.
2052
template <typename pchar, typename schar>
2053
static int SimpleIndexOf(Vector<const schar> subject,
2054
                         Vector<const pchar> pattern,
2055
                         int idx,
2056
                         bool* complete) {
2057
  // Badness is a count of how much work we have done.  When we have
2058
  // done enough work we decide it's probably worth switching to a better
2059
  // algorithm.
2060
  int badness = -10 - (pattern.length() << 2);
2061
  // We know our pattern is at least 2 characters, we cache the first so
2062
  // the common case of the first character not matching is faster.
2063
  pchar pattern_first_char = pattern[0];
2064

    
2065
  for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
2066
    badness++;
2067
    if (badness > 0) {
2068
      *complete = false;
2069
      return i;
2070
    }
2071
    if (subject[i] != pattern_first_char) continue;
2072
    int j = 1;
2073
    do {
2074
      if (pattern[j] != subject[i+j]) {
2075
        break;
2076
      }
2077
      j++;
2078
    } while (j < pattern.length());
2079
    if (j == pattern.length()) {
2080
      *complete = true;
2081
      return i;
2082
    }
2083
    badness += j;
2084
  }
2085
  *complete = true;
2086
  return -1;
2087
}
2088

    
2089
// Simple indexOf that never bails out. For short patterns only.
2090
template <typename pchar, typename schar>
2091
static int SimpleIndexOf(Vector<const schar> subject,
2092
                         Vector<const pchar> pattern,
2093
                         int idx) {
2094
  pchar pattern_first_char = pattern[0];
2095
  for (int i = idx, n = subject.length() - pattern.length(); i <= n; i++) {
2096
    if (subject[i] != pattern_first_char) continue;
2097
    int j = 1;
2098
    do {
2099
      if (pattern[j] != subject[i+j]) {
2100
        break;
2101
      }
2102
      j++;
2103
    } while (j < pattern.length());
2104
    if (j == pattern.length()) {
2105
      return i;
2106
    }
2107
  }
2108
  return -1;
2109
}
2110

    
2111

    
2112
// Dispatch to different algorithms.
2113
template <typename schar, typename pchar>
2114
static int StringMatchStrategy(Vector<const schar> sub,
2115
                               Vector<const pchar> pat,
2116
                               int start_index) {
2117
  ASSERT(pat.length() > 1);
2118

    
2119
  // We have an ASCII haystack and a non-ASCII needle. Check if there
2120
  // really is a non-ASCII character in the needle and bail out if there
2121
  // is.
2122
  if (sizeof(pchar) > 1 && sizeof(schar) == 1) {
2123
    for (int i = 0; i < pat.length(); i++) {
2124
      uc16 c = pat[i];
2125
      if (c > String::kMaxAsciiCharCode) {
2126
        return -1;
2127
      }
2128
    }
2129
  }
2130
  if (pat.length() < kBMMinPatternLength) {
2131
    // We don't believe fancy searching can ever be more efficient.
2132
    // The max shift of Boyer-Moore on a pattern of this length does
2133
    // not compensate for the overhead.
2134
    return SimpleIndexOf(sub, pat, start_index);
2135
  }
2136
  // Try algorithms in order of increasing setup cost and expected performance.
2137
  bool complete;
2138
  int idx = SimpleIndexOf(sub, pat, start_index, &complete);
2139
  if (complete) return idx;
2140
  idx = BoyerMooreHorspool(sub, pat, idx, &complete);
2141
  if (complete) return idx;
2142
  return BoyerMooreIndexOf(sub, pat, idx);
2143
}
2144

    
2145
// Perform string match of pattern on subject, starting at start index.
2146
// Caller must ensure that 0 <= start_index <= sub->length(),
2147
// and should check that pat->length() + start_index <= sub->length()
2148
int Runtime::StringMatch(Handle<String> sub,
2149
                         Handle<String> pat,
2150
                         int start_index) {
2151
  ASSERT(0 <= start_index);
2152
  ASSERT(start_index <= sub->length());
2153

    
2154
  int pattern_length = pat->length();
2155
  if (pattern_length == 0) return start_index;
2156

    
2157
  int subject_length = sub->length();
2158
  if (start_index + pattern_length > subject_length) return -1;
2159

    
2160
  if (!sub->IsFlat()) {
2161
    FlattenString(sub);
2162
  }
2163
  // Searching for one specific character is common.  For one
2164
  // character patterns linear search is necessary, so any smart
2165
  // algorithm is unnecessary overhead.
2166
  if (pattern_length == 1) {
2167
    AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2168
    if (StringShape(*sub).IsAsciiRepresentation()) {
2169
      uc16 pchar = pat->Get(0);
2170
      if (pchar > String::kMaxAsciiCharCode) {
2171
        return -1;
2172
      }
2173
      Vector<const char> ascii_vector =
2174
        sub->ToAsciiVector().SubVector(start_index, subject_length);
2175
      const void* pos = memchr(ascii_vector.start(),
2176
                               static_cast<const char>(pchar),
2177
                               static_cast<size_t>(ascii_vector.length()));
2178
      if (pos == NULL) {
2179
        return -1;
2180
      }
2181
      return reinterpret_cast<const char*>(pos) - ascii_vector.start()
2182
          + start_index;
2183
    }
2184
    return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index);
2185
  }
2186

    
2187
  if (!pat->IsFlat()) {
2188
    FlattenString(pat);
2189
  }
2190

    
2191
  AssertNoAllocation no_heap_allocation;  // ensure vectors stay valid
2192
  // dispatch on type of strings
2193
  if (StringShape(*pat).IsAsciiRepresentation()) {
2194
    Vector<const char> pat_vector = pat->ToAsciiVector();
2195
    if (StringShape(*sub).IsAsciiRepresentation()) {
2196
      return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
2197
    }
2198
    return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
2199
  }
2200
  Vector<const uc16> pat_vector = pat->ToUC16Vector();
2201
  if (StringShape(*sub).IsAsciiRepresentation()) {
2202
    return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
2203
  }
2204
  return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
2205
}
2206

    
2207

    
2208
static Object* Runtime_StringIndexOf(Arguments args) {
2209
  HandleScope scope;  // create a new handle scope
2210
  ASSERT(args.length() == 3);
2211

    
2212
  CONVERT_ARG_CHECKED(String, sub, 0);
2213
  CONVERT_ARG_CHECKED(String, pat, 1);
2214

    
2215
  Object* index = args[2];
2216
  uint32_t start_index;
2217
  if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
2218

    
2219
  RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
2220
  int position = Runtime::StringMatch(sub, pat, start_index);
2221
  return Smi::FromInt(position);
2222
}
2223

    
2224

    
2225
static Object* Runtime_StringLastIndexOf(Arguments args) {
2226
  NoHandleAllocation ha;
2227
  ASSERT(args.length() == 3);
2228

    
2229
  CONVERT_CHECKED(String, sub, args[0]);
2230
  CONVERT_CHECKED(String, pat, args[1]);
2231
  Object* index = args[2];
2232

    
2233
  sub->TryFlattenIfNotFlat();
2234
  pat->TryFlattenIfNotFlat();
2235

    
2236
  uint32_t start_index;
2237
  if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
2238

    
2239
  uint32_t pattern_length = pat->length();
2240
  uint32_t sub_length = sub->length();
2241

    
2242
  if (start_index + pattern_length > sub_length) {
2243
    start_index = sub_length - pattern_length;
2244
  }
2245

    
2246
  for (int i = start_index; i >= 0; i--) {
2247
    bool found = true;
2248
    for (uint32_t j = 0; j < pattern_length; j++) {
2249
      if (sub->Get(i + j) != pat->Get(j)) {
2250
        found = false;
2251
        break;
2252
      }
2253
    }
2254
    if (found) return Smi::FromInt(i);
2255
  }
2256

    
2257
  return Smi::FromInt(-1);
2258
}
2259

    
2260

    
2261
static Object* Runtime_StringLocaleCompare(Arguments args) {
2262
  NoHandleAllocation ha;
2263
  ASSERT(args.length() == 2);
2264

    
2265
  CONVERT_CHECKED(String, str1, args[0]);
2266
  CONVERT_CHECKED(String, str2, args[1]);
2267

    
2268
  if (str1 == str2) return Smi::FromInt(0);  // Equal.
2269
  int str1_length = str1->length();
2270
  int str2_length = str2->length();
2271

    
2272
  // Decide trivial cases without flattening.
2273
  if (str1_length == 0) {
2274
    if (str2_length == 0) return Smi::FromInt(0);  // Equal.
2275
    return Smi::FromInt(-str2_length);
2276
  } else {
2277
    if (str2_length == 0) return Smi::FromInt(str1_length);
2278
  }
2279

    
2280
  int end = str1_length < str2_length ? str1_length : str2_length;
2281

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

    
2288
  str1->TryFlattenIfNotFlat();
2289
  str2->TryFlattenIfNotFlat();
2290

    
2291
  static StringInputBuffer buf1;
2292
  static StringInputBuffer buf2;
2293

    
2294
  buf1.Reset(str1);
2295
  buf2.Reset(str2);
2296

    
2297
  for (int i = 0; i < end; i++) {
2298
    uint16_t char1 = buf1.GetNext();
2299
    uint16_t char2 = buf2.GetNext();
2300
    if (char1 != char2) return Smi::FromInt(char1 - char2);
2301
  }
2302

    
2303
  return Smi::FromInt(str1_length - str2_length);
2304
}
2305

    
2306

    
2307
static Object* Runtime_StringSlice(Arguments args) {
2308
  NoHandleAllocation ha;
2309
  ASSERT(args.length() == 3);
2310

    
2311
  CONVERT_CHECKED(String, value, args[0]);
2312
  CONVERT_DOUBLE_CHECKED(from_number, args[1]);
2313
  CONVERT_DOUBLE_CHECKED(to_number, args[2]);
2314

    
2315
  int start = FastD2I(from_number);
2316
  int end = FastD2I(to_number);
2317

    
2318
  RUNTIME_ASSERT(end >= start);
2319
  RUNTIME_ASSERT(start >= 0);
2320
  RUNTIME_ASSERT(end <= value->length());
2321
  return value->Slice(start, end);
2322
}
2323

    
2324

    
2325
static Object* Runtime_StringMatch(Arguments args) {
2326
  ASSERT_EQ(3, args.length());
2327

    
2328
  CONVERT_ARG_CHECKED(String, subject, 0);
2329
  CONVERT_ARG_CHECKED(JSRegExp, regexp, 1);
2330
  CONVERT_ARG_CHECKED(JSArray, regexp_info, 2);
2331
  HandleScope handles;
2332

    
2333
  Handle<Object> match = RegExpImpl::Exec(regexp, subject, 0, regexp_info);
2334

    
2335
  if (match.is_null()) {
2336
    return Failure::Exception();
2337
  }
2338
  if (match->IsNull()) {
2339
    return Heap::null_value();
2340
  }
2341
  int length = subject->length();
2342

    
2343
  ZoneScope zone_space(DELETE_ON_EXIT);
2344
  ZoneList<int> offsets(8);
2345
  do {
2346
    int start;
2347
    int end;
2348
    {
2349
      AssertNoAllocation no_alloc;
2350
      FixedArray* elements = regexp_info->elements();
2351
      start = Smi::cast(elements->get(RegExpImpl::kFirstCapture))->value();
2352
      end = Smi::cast(elements->get(RegExpImpl::kFirstCapture + 1))->value();
2353
    }
2354
    offsets.Add(start);
2355
    offsets.Add(end);
2356
    int index = start < end ? end : end + 1;
2357
    if (index > length) break;
2358
    match = RegExpImpl::Exec(regexp, subject, index, regexp_info);
2359
    if (match.is_null()) {
2360
      return Failure::Exception();
2361
    }
2362
  } while (!match->IsNull());
2363
  int matches = offsets.length() / 2;
2364
  Handle<FixedArray> elements = Factory::NewFixedArray(matches);
2365
  for (int i = 0; i < matches ; i++) {
2366
    int from = offsets.at(i * 2);
2367
    int to = offsets.at(i * 2 + 1);
2368
    elements->set(i, *Factory::NewStringSlice(subject, from, to));
2369
  }
2370
  Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
2371
  result->set_length(Smi::FromInt(matches));
2372
  return *result;
2373
}
2374

    
2375

    
2376
static Object* Runtime_NumberToRadixString(Arguments args) {
2377
  NoHandleAllocation ha;
2378
  ASSERT(args.length() == 2);
2379

    
2380
  CONVERT_DOUBLE_CHECKED(value, args[0]);
2381
  if (isnan(value)) {
2382
    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
2383
  }
2384
  if (isinf(value)) {
2385
    if (value < 0) {
2386
      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
2387
    }
2388
    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
2389
  }
2390
  CONVERT_DOUBLE_CHECKED(radix_number, args[1]);
2391
  int radix = FastD2I(radix_number);
2392
  RUNTIME_ASSERT(2 <= radix && radix <= 36);
2393
  char* str = DoubleToRadixCString(value, radix);
2394
  Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
2395
  DeleteArray(str);
2396
  return result;
2397
}
2398

    
2399

    
2400
static Object* Runtime_NumberToFixed(Arguments args) {
2401
  NoHandleAllocation ha;
2402
  ASSERT(args.length() == 2);
2403

    
2404
  CONVERT_DOUBLE_CHECKED(value, args[0]);
2405
  if (isnan(value)) {
2406
    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
2407
  }
2408
  if (isinf(value)) {
2409
    if (value < 0) {
2410
      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
2411
    }
2412
    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
2413
  }
2414
  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
2415
  int f = FastD2I(f_number);
2416
  RUNTIME_ASSERT(f >= 0);
2417
  char* str = DoubleToFixedCString(value, f);
2418
  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
2419
  DeleteArray(str);
2420
  return res;
2421
}
2422

    
2423

    
2424
static Object* Runtime_NumberToExponential(Arguments args) {
2425
  NoHandleAllocation ha;
2426
  ASSERT(args.length() == 2);
2427

    
2428
  CONVERT_DOUBLE_CHECKED(value, args[0]);
2429
  if (isnan(value)) {
2430
    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
2431
  }
2432
  if (isinf(value)) {
2433
    if (value < 0) {
2434
      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
2435
    }
2436
    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
2437
  }
2438
  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
2439
  int f = FastD2I(f_number);
2440
  RUNTIME_ASSERT(f >= -1 && f <= 20);
2441
  char* str = DoubleToExponentialCString(value, f);
2442
  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
2443
  DeleteArray(str);
2444
  return res;
2445
}
2446

    
2447

    
2448
static Object* Runtime_NumberToPrecision(Arguments args) {
2449
  NoHandleAllocation ha;
2450
  ASSERT(args.length() == 2);
2451

    
2452
  CONVERT_DOUBLE_CHECKED(value, args[0]);
2453
  if (isnan(value)) {
2454
    return Heap::AllocateStringFromAscii(CStrVector("NaN"));
2455
  }
2456
  if (isinf(value)) {
2457
    if (value < 0) {
2458
      return Heap::AllocateStringFromAscii(CStrVector("-Infinity"));
2459
    }
2460
    return Heap::AllocateStringFromAscii(CStrVector("Infinity"));
2461
  }
2462
  CONVERT_DOUBLE_CHECKED(f_number, args[1]);
2463
  int f = FastD2I(f_number);
2464
  RUNTIME_ASSERT(f >= 1 && f <= 21);
2465
  char* str = DoubleToPrecisionCString(value, f);
2466
  Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
2467
  DeleteArray(str);
2468
  return res;
2469
}
2470

    
2471

    
2472
// Returns a single character string where first character equals
2473
// string->Get(index).
2474
static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
2475
  if (index < static_cast<uint32_t>(string->length())) {
2476
    string->TryFlattenIfNotFlat();
2477
    return LookupSingleCharacterStringFromCode(
2478
        string->Get(index));
2479
  }
2480
  return Execution::CharAt(string, index);
2481
}
2482

    
2483

    
2484
Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
2485
  // Handle [] indexing on Strings
2486
  if (object->IsString()) {
2487
    Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
2488
    if (!result->IsUndefined()) return *result;
2489
  }
2490

    
2491
  // Handle [] indexing on String objects
2492
  if (object->IsStringObjectWithCharacterAt(index)) {
2493
    Handle<JSValue> js_value = Handle<JSValue>::cast(object);
2494
    Handle<Object> result =
2495
        GetCharAt(Handle<String>(String::cast(js_value->value())), index);
2496
    if (!result->IsUndefined()) return *result;
2497
  }
2498

    
2499
  if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
2500
    Handle<Object> prototype = GetPrototype(object);
2501
    return prototype->GetElement(index);
2502
  }
2503

    
2504
  return object->GetElement(index);
2505
}
2506

    
2507

    
2508
Object* Runtime::GetObjectProperty(Handle<Object> object, Handle<Object> key) {
2509
  HandleScope scope;
2510

    
2511
  if (object->IsUndefined() || object->IsNull()) {
2512
    Handle<Object> args[2] = { key, object };
2513
    Handle<Object> error =
2514
        Factory::NewTypeError("non_object_property_load",
2515
                              HandleVector(args, 2));
2516
    return Top::Throw(*error);
2517
  }
2518

    
2519
  // Check if the given key is an array index.
2520
  uint32_t index;
2521
  if (Array::IndexFromObject(*key, &index)) {
2522
    return GetElementOrCharAt(object, index);
2523
  }
2524

    
2525
  // Convert the key to a string - possibly by calling back into JavaScript.
2526
  Handle<String> name;
2527
  if (key->IsString()) {
2528
    name = Handle<String>::cast(key);
2529
  } else {
2530
    bool has_pending_exception = false;
2531
    Handle<Object> converted =
2532
        Execution::ToString(key, &has_pending_exception);
2533
    if (has_pending_exception) return Failure::Exception();
2534
    name = Handle<String>::cast(converted);
2535
  }
2536

    
2537
  // Check if the name is trivially convertible to an index and get
2538
  // the element if so.
2539
  if (name->AsArrayIndex(&index)) {
2540
    return GetElementOrCharAt(object, index);
2541
  } else {
2542
    PropertyAttributes attr;
2543
    return object->GetProperty(*name, &attr);
2544
  }
2545
}
2546

    
2547

    
2548
static Object* Runtime_GetProperty(Arguments args) {
2549
  NoHandleAllocation ha;
2550
  ASSERT(args.length() == 2);
2551

    
2552
  Handle<Object> object = args.at<Object>(0);
2553
  Handle<Object> key = args.at<Object>(1);
2554

    
2555
  return Runtime::GetObjectProperty(object, key);
2556
}
2557

    
2558

    
2559

    
2560
// KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
2561
static Object* Runtime_KeyedGetProperty(Arguments args) {
2562
  NoHandleAllocation ha;
2563
  ASSERT(args.length() == 2);
2564

    
2565
  // Fast cases for getting named properties of the receiver JSObject
2566
  // itself.
2567
  //
2568
  // The global proxy objects has to be excluded since LocalLookup on
2569
  // the global proxy object can return a valid result even though the
2570
  // global proxy object never has properties.  This is the case
2571
  // because the global proxy object forwards everything to its hidden
2572
  // prototype including local lookups.
2573
  //
2574
  // Additionally, we need to make sure that we do not cache results
2575
  // for objects that require access checks.
2576
  if (args[0]->IsJSObject() &&
2577
      !args[0]->IsJSGlobalProxy() &&
2578
      !args[0]->IsAccessCheckNeeded() &&
2579
      args[1]->IsString()) {
2580
    JSObject* receiver = JSObject::cast(args[0]);
2581
    String* key = String::cast(args[1]);
2582
    if (receiver->HasFastProperties()) {
2583
      // Attempt to use lookup cache.
2584
      Object* obj = Heap::GetKeyedLookupCache();
2585
      if (obj->IsFailure()) return obj;
2586
      LookupCache* cache = LookupCache::cast(obj);
2587
      Map* receiver_map = receiver->map();
2588
      int offset = cache->Lookup(receiver_map, key);
2589
      if (offset != LookupCache::kNotFound) {
2590
        Object* value = receiver->FastPropertyAt(offset);
2591
        return value->IsTheHole() ? Heap::undefined_value() : value;
2592
      }
2593
      // Lookup cache miss.  Perform lookup and update the cache if
2594
      // appropriate.
2595
      LookupResult result;
2596
      receiver->LocalLookup(key, &result);
2597
      if (result.IsProperty() && result.IsLoaded() && result.type() == FIELD) {
2598
        int offset = result.GetFieldIndex();
2599
        Object* obj = cache->Put(receiver_map, key, offset);
2600
        if (obj->IsFailure()) return obj;
2601
        Heap::SetKeyedLookupCache(LookupCache::cast(obj));
2602
        Object* value = receiver->FastPropertyAt(offset);
2603
        return value->IsTheHole() ? Heap::undefined_value() : value;
2604
      }
2605
    } else {
2606
      // Attempt dictionary lookup.
2607
      Dictionary* dictionary = receiver->property_dictionary();
2608
      int entry = dictionary->FindStringEntry(key);
2609
      if ((entry != DescriptorArray::kNotFound) &&
2610
          (dictionary->DetailsAt(entry).type() == NORMAL)) {
2611
        return dictionary->ValueAt(entry);
2612
      }
2613
    }
2614
  }
2615

    
2616
  // Fall back to GetObjectProperty.
2617
  return Runtime::GetObjectProperty(args.at<Object>(0),
2618
                                    args.at<Object>(1));
2619
}
2620

    
2621

    
2622
Object* Runtime::SetObjectProperty(Handle<Object> object,
2623
                                   Handle<Object> key,
2624
                                   Handle<Object> value,
2625
                                   PropertyAttributes attr) {
2626
  HandleScope scope;
2627

    
2628
  if (object->IsUndefined() || object->IsNull()) {
2629
    Handle<Object> args[2] = { key, object };
2630
    Handle<Object> error =
2631
        Factory::NewTypeError("non_object_property_store",
2632
                              HandleVector(args, 2));
2633
    return Top::Throw(*error);
2634
  }
2635

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

    
2639
  Handle<JSObject> js_object = Handle<JSObject>::cast(object);
2640

    
2641
  // Check if the given key is an array index.
2642
  uint32_t index;
2643
  if (Array::IndexFromObject(*key, &index)) {
2644
    ASSERT(attr == NONE);
2645

    
2646
    // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
2647
    // of a string using [] notation.  We need to support this too in
2648
    // JavaScript.
2649
    // In the case of a String object we just need to redirect the assignment to
2650
    // the underlying string if the index is in range.  Since the underlying
2651
    // string does nothing with the assignment then we can ignore such
2652
    // assignments.
2653
    if (js_object->IsStringObjectWithCharacterAt(index)) {
2654
      return *value;
2655
    }
2656

    
2657
    Handle<Object> result = SetElement(js_object, index, value);
2658
    if (result.is_null()) return Failure::Exception();
2659
    return *value;
2660
  }
2661

    
2662
  if (key->IsString()) {
2663
    Handle<Object> result;
2664
    if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
2665
      ASSERT(attr == NONE);
2666
      result = SetElement(js_object, index, value);
2667
    } else {
2668
      Handle<String> key_string = Handle<String>::cast(key);
2669
      key_string->TryFlattenIfNotFlat();
2670
      result = SetProperty(js_object, key_string, value, attr);
2671
    }
2672
    if (result.is_null()) return Failure::Exception();
2673
    return *value;
2674
  }
2675

    
2676
  // Call-back into JavaScript to convert the key to a string.
2677
  bool has_pending_exception = false;
2678
  Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
2679
  if (has_pending_exception) return Failure::Exception();
2680
  Handle<String> name = Handle<String>::cast(converted);
2681

    
2682
  if (name->AsArrayIndex(&index)) {
2683
    ASSERT(attr == NONE);
2684
    return js_object->SetElement(index, *value);
2685
  } else {
2686
    return js_object->SetProperty(*name, *value, attr);
2687
  }
2688
}
2689

    
2690

    
2691
static Object* Runtime_SetProperty(Arguments args) {
2692
  NoHandleAllocation ha;
2693
  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
2694

    
2695
  Handle<Object> object = args.at<Object>(0);
2696
  Handle<Object> key = args.at<Object>(1);
2697
  Handle<Object> value = args.at<Object>(2);
2698

    
2699
  // Compute attributes.
2700
  PropertyAttributes attributes = NONE;
2701
  if (args.length() == 4) {
2702
    CONVERT_CHECKED(Smi, value_obj, args[3]);
2703
    int unchecked_value = value_obj->value();
2704
    // Only attribute bits should be set.
2705
    RUNTIME_ASSERT(
2706
        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
2707
    attributes = static_cast<PropertyAttributes>(unchecked_value);
2708
  }
2709
  return Runtime::SetObjectProperty(object, key, value, attributes);
2710
}
2711

    
2712

    
2713
// Set a local property, even if it is READ_ONLY.  If the property does not
2714
// exist, it will be added with attributes NONE.
2715
static Object* Runtime_IgnoreAttributesAndSetProperty(Arguments args) {
2716
  NoHandleAllocation ha;
2717
  RUNTIME_ASSERT(args.length() == 3 || args.length() == 4);
2718
  CONVERT_CHECKED(JSObject, object, args[0]);
2719
  CONVERT_CHECKED(String, name, args[1]);
2720
  // Compute attributes.
2721
  PropertyAttributes attributes = NONE;
2722
  if (args.length() == 4) {
2723
    CONVERT_CHECKED(Smi, value_obj, args[3]);
2724
    int unchecked_value = value_obj->value();
2725
    // Only attribute bits should be set.
2726
    RUNTIME_ASSERT(
2727
        (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
2728
    attributes = static_cast<PropertyAttributes>(unchecked_value);
2729
  }
2730

    
2731
  return object->
2732
      IgnoreAttributesAndSetLocalProperty(name, args[2], attributes);
2733
}
2734

    
2735

    
2736
static Object* Runtime_DeleteProperty(Arguments args) {
2737
  NoHandleAllocation ha;
2738
  ASSERT(args.length() == 2);
2739

    
2740
  CONVERT_CHECKED(JSObject, object, args[0]);
2741
  CONVERT_CHECKED(String, key, args[1]);
2742
  return object->DeleteProperty(key);
2743
}
2744

    
2745

    
2746
static Object* Runtime_HasLocalProperty(Arguments args) {
2747
  NoHandleAllocation ha;
2748
  ASSERT(args.length() == 2);
2749
  CONVERT_CHECKED(String, key, args[1]);
2750

    
2751
  // Only JS objects can have properties.
2752
  if (args[0]->IsJSObject()) {
2753
    JSObject* object = JSObject::cast(args[0]);
2754
    if (object->HasLocalProperty(key)) return Heap::true_value();
2755
  } else if (args[0]->IsString()) {
2756
    // Well, there is one exception:  Handle [] on strings.
2757
    uint32_t index;
2758
    if (key->AsArrayIndex(&index)) {
2759
      String* string = String::cast(args[0]);
2760
      if (index < static_cast<uint32_t>(string->length()))
2761
        return Heap::true_value();
2762
    }
2763
  }
2764
  return Heap::false_value();
2765
}
2766

    
2767

    
2768
static Object* Runtime_HasProperty(Arguments args) {
2769
  NoHandleAllocation na;
2770
  ASSERT(args.length() == 2);
2771

    
2772
  // Only JS objects can have properties.
2773
  if (args[0]->IsJSObject()) {
2774
    JSObject* object = JSObject::cast(args[0]);
2775
    CONVERT_CHECKED(String, key, args[1]);
2776
    if (object->HasProperty(key)) return Heap::true_value();
2777
  }
2778
  return Heap::false_value();
2779
}
2780

    
2781

    
2782
static Object* Runtime_HasElement(Arguments args) {
2783
  NoHandleAllocation na;
2784
  ASSERT(args.length() == 2);
2785

    
2786
  // Only JS objects can have elements.
2787
  if (args[0]->IsJSObject()) {
2788
    JSObject* object = JSObject::cast(args[0]);
2789
    CONVERT_CHECKED(Smi, index_obj, args[1]);
2790
    uint32_t index = index_obj->value();
2791
    if (object->HasElement(index)) return Heap::true_value();
2792
  }
2793
  return Heap::false_value();
2794
}
2795

    
2796

    
2797
static Object* Runtime_IsPropertyEnumerable(Arguments args) {
2798
  NoHandleAllocation ha;
2799
  ASSERT(args.length() == 2);
2800

    
2801
  CONVERT_CHECKED(JSObject, object, args[0]);
2802
  CONVERT_CHECKED(String, key, args[1]);
2803

    
2804
  uint32_t index;
2805
  if (key->AsArrayIndex(&index)) {
2806
    return Heap::ToBoolean(object->HasElement(index));
2807
  }
2808

    
2809
  PropertyAttributes att = object->GetLocalPropertyAttribute(key);
2810
  return Heap::ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
2811
}
2812

    
2813

    
2814
static Object* Runtime_GetPropertyNames(Arguments args) {
2815
  HandleScope scope;
2816
  ASSERT(args.length() == 1);
2817

    
2818
  CONVERT_CHECKED(JSObject, raw_object, args[0]);
2819
  Handle<JSObject> object(raw_object);
2820
  return *GetKeysFor(object);
2821
}
2822

    
2823

    
2824
// Returns either a FixedArray as Runtime_GetPropertyNames,
2825
// or, if the given object has an enum cache that contains
2826
// all enumerable properties of the object and its prototypes
2827
// have none, the map of the object. This is used to speed up
2828
// the check for deletions during a for-in.
2829
static Object* Runtime_GetPropertyNamesFast(Arguments args) {
2830
  ASSERT(args.length() == 1);
2831

    
2832
  CONVERT_CHECKED(JSObject, raw_object, args[0]);
2833

    
2834
  if (raw_object->IsSimpleEnum()) return raw_object->map();
2835

    
2836
  HandleScope scope;
2837
  Handle<JSObject> object(raw_object);
2838
  Handle<FixedArray> content = GetKeysInFixedArrayFor(object);
2839

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

    
2843
  return *content;
2844
}
2845

    
2846

    
2847
static Object* Runtime_GetArgumentsProperty(Arguments args) {
2848
  NoHandleAllocation ha;
2849
  ASSERT(args.length() == 1);
2850

    
2851
  // Compute the frame holding the arguments.
2852
  JavaScriptFrameIterator it;
2853
  it.AdvanceToArgumentsFrame();
2854
  JavaScriptFrame* frame = it.frame();
2855

    
2856
  // Get the actual number of provided arguments.
2857
  const uint32_t n = frame->GetProvidedParametersCount();
2858

    
2859
  // Try to convert the key to an index. If successful and within
2860
  // index return the the argument from the frame.
2861
  uint32_t index;
2862
  if (Array::IndexFromObject(args[0], &index) && index < n) {
2863
    return frame->GetParameter(index);
2864
  }
2865

    
2866
  // Convert the key to a string.
2867
  HandleScope scope;
2868
  bool exception = false;
2869
  Handle<Object> converted =
2870
      Execution::ToString(args.at<Object>(0), &exception);
2871
  if (exception) return Failure::Exception();
2872
  Handle<String> key = Handle<String>::cast(converted);
2873

    
2874
  // Try to convert the string key into an array index.
2875
  if (key->AsArrayIndex(&index)) {
2876
    if (index < n) {
2877
      return frame->GetParameter(index);
2878
    } else {
2879
      return Top::initial_object_prototype()->GetElement(index);
2880
    }
2881
  }
2882

    
2883
  // Handle special arguments properties.
2884
  if (key->Equals(Heap::length_symbol())) return Smi::FromInt(n);
2885
  if (key->Equals(Heap::callee_symbol())) return frame->function();
2886

    
2887
  // Lookup in the initial Object.prototype object.
2888
  return Top::initial_object_prototype()->GetProperty(*key);
2889
}
2890

    
2891

    
2892
static Object* Runtime_ToFastProperties(Arguments args) {
2893
  ASSERT(args.length() == 1);
2894
  Handle<Object> object = args.at<Object>(0);
2895
  if (object->IsJSObject()) {
2896
    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
2897
    js_object->TransformToFastProperties(0);
2898
  }
2899
  return *object;
2900
}
2901

    
2902

    
2903
static Object* Runtime_ToSlowProperties(Arguments args) {
2904
  ASSERT(args.length() == 1);
2905
  Handle<Object> object = args.at<Object>(0);
2906
  if (object->IsJSObject()) {
2907
    Handle<JSObject> js_object = Handle<JSObject>::cast(object);
2908
    js_object->NormalizeProperties(CLEAR_INOBJECT_PROPERTIES);
2909
  }
2910
  return *object;
2911
}
2912

    
2913

    
2914
static Object* Runtime_ToBool(Arguments args) {
2915
  NoHandleAllocation ha;
2916
  ASSERT(args.length() == 1);
2917

    
2918
  return args[0]->ToBoolean();
2919
}
2920

    
2921

    
2922
// Returns the type string of a value; see ECMA-262, 11.4.3 (p 47).
2923
// Possible optimizations: put the type string into the oddballs.
2924
static Object* Runtime_Typeof(Arguments args) {
2925
  NoHandleAllocation ha;
2926

    
2927
  Object* obj = args[0];
2928
  if (obj->IsNumber()) return Heap::number_symbol();
2929
  HeapObject* heap_obj = HeapObject::cast(obj);
2930

    
2931
  // typeof an undetectable object is 'undefined'
2932
  if (heap_obj->map()->is_undetectable()) return Heap::undefined_symbol();
2933

    
2934
  InstanceType instance_type = heap_obj->map()->instance_type();
2935
  if (instance_type < FIRST_NONSTRING_TYPE) {
2936
    return Heap::string_symbol();
2937
  }
2938

    
2939
  switch (instance_type) {
2940
    case ODDBALL_TYPE:
2941
      if (heap_obj->IsTrue() || heap_obj->IsFalse()) {
2942
        return Heap::boolean_symbol();
2943
      }
2944
      if (heap_obj->IsNull()) {
2945
        return Heap::object_symbol();
2946
      }
2947
      ASSERT(heap_obj->IsUndefined());
2948
      return Heap::undefined_symbol();
2949
    case JS_FUNCTION_TYPE:
2950
      return Heap::function_symbol();
2951
    default:
2952
      // For any kind of object not handled above, the spec rule for
2953
      // host objects gives that it is okay to return "object"
2954
      return Heap::object_symbol();
2955
  }
2956
}
2957

    
2958

    
2959
static Object* Runtime_StringToNumber(Arguments args) {
2960
  NoHandleAllocation ha;
2961
  ASSERT(args.length() == 1);
2962
  CONVERT_CHECKED(String, subject, args[0]);
2963
  subject->TryFlattenIfNotFlat();
2964
  return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
2965
}
2966

    
2967

    
2968
static Object* Runtime_StringFromCharCodeArray(Arguments args) {
2969
  NoHandleAllocation ha;
2970
  ASSERT(args.length() == 1);
2971

    
2972
  CONVERT_CHECKED(JSArray, codes, args[0]);
2973
  int length = Smi::cast(codes->length())->value();
2974

    
2975
  // Check if the string can be ASCII.
2976
  int i;
2977
  for (i = 0; i < length; i++) {
2978
    Object* element = codes->GetElement(i);
2979
    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2980
    if ((chr & 0xffff) > String::kMaxAsciiCharCode)
2981
      break;
2982
  }
2983

    
2984
  Object* object = NULL;
2985
  if (i == length) {  // The string is ASCII.
2986
    object = Heap::AllocateRawAsciiString(length);
2987
  } else {  // The string is not ASCII.
2988
    object = Heap::AllocateRawTwoByteString(length);
2989
  }
2990

    
2991
  if (object->IsFailure()) return object;
2992
  String* result = String::cast(object);
2993
  for (int i = 0; i < length; i++) {
2994
    Object* element = codes->GetElement(i);
2995
    CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2996
    result->Set(i, chr & 0xffff);
2997
  }
2998
  return result;
2999
}
3000

    
3001

    
3002
// kNotEscaped is generated by the following:
3003
//
3004
// #!/bin/perl
3005
// for (my $i = 0; $i < 256; $i++) {
3006
//   print "\n" if $i % 16 == 0;
3007
//   my $c = chr($i);
3008
//   my $escaped = 1;
3009
//   $escaped = 0 if $c =~ m#[A-Za-z0-9@*_+./-]#;
3010
//   print $escaped ? "0, " : "1, ";
3011
// }
3012

    
3013

    
3014
static bool IsNotEscaped(uint16_t character) {
3015
  // Only for 8 bit characters, the rest are always escaped (in a different way)
3016
  ASSERT(character < 256);
3017
  static const char kNotEscaped[256] = {
3018
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3019
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3020
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
3021
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
3022
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3023
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
3024
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3025
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
3026
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3027
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3028
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3029
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3030
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3031
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3032
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3033
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
3034
  };
3035
  return kNotEscaped[character] != 0;
3036
}
3037

    
3038

    
3039
static Object* Runtime_URIEscape(Arguments args) {
3040
  const char hex_chars[] = "0123456789ABCDEF";
3041
  NoHandleAllocation ha;
3042
  ASSERT(args.length() == 1);
3043
  CONVERT_CHECKED(String, source, args[0]);
3044

    
3045
  source->TryFlattenIfNotFlat();
3046

    
3047
  int escaped_length = 0;
3048
  int length = source->length();
3049
  {
3050
    Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
3051
    buffer->Reset(source);
3052
    while (buffer->has_more()) {
3053
      uint16_t character = buffer->GetNext();
3054
      if (character >= 256) {
3055
        escaped_length += 6;
3056
      } else if (IsNotEscaped(character)) {
3057
        escaped_length++;
3058
      } else {
3059
        escaped_length += 3;
3060
      }
3061
      // We don't allow strings that are longer than Smi range.
3062
      if (!Smi::IsValid(escaped_length)) {
3063
        Top::context()->mark_out_of_memory();
3064
        return Failure::OutOfMemoryException();
3065
      }
3066
    }
3067
  }
3068
  // No length change implies no change.  Return original string if no change.
3069
  if (escaped_length == length) {
3070
    return source;
3071
  }
3072
  Object* o = Heap::AllocateRawAsciiString(escaped_length);
3073
  if (o->IsFailure()) return o;
3074
  String* destination = String::cast(o);
3075
  int dest_position = 0;
3076

    
3077
  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
3078
  buffer->Rewind();
3079
  while (buffer->has_more()) {
3080
    uint16_t chr = buffer->GetNext();
3081
    if (chr >= 256) {
3082
      destination->Set(dest_position, '%');
3083
      destination->Set(dest_position+1, 'u');
3084
      destination->Set(dest_position+2, hex_chars[chr >> 12]);
3085
      destination->Set(dest_position+3, hex_chars[(chr >> 8) & 0xf]);
3086
      destination->Set(dest_position+4, hex_chars[(chr >> 4) & 0xf]);
3087
      destination->Set(dest_position+5, hex_chars[chr & 0xf]);
3088
      dest_position += 6;
3089
    } else if (IsNotEscaped(chr)) {
3090
      destination->Set(dest_position, chr);
3091
      dest_position++;
3092
    } else {
3093
      destination->Set(dest_position, '%');
3094
      destination->Set(dest_position+1, hex_chars[chr >> 4]);
3095
      destination->Set(dest_position+2, hex_chars[chr & 0xf]);
3096
      dest_position += 3;
3097
    }
3098
  }
3099
  return destination;
3100
}
3101

    
3102

    
3103
static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
3104
  static const signed char kHexValue['g'] = {
3105
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3106
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3107
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3108
    0,  1,  2,   3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
3109
    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3110
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3111
    -1, 10, 11, 12, 13, 14, 15 };
3112

    
3113
  if (character1 > 'f') return -1;
3114
  int hi = kHexValue[character1];
3115
  if (hi == -1) return -1;
3116
  if (character2 > 'f') return -1;
3117
  int lo = kHexValue[character2];
3118
  if (lo == -1) return -1;
3119
  return (hi << 4) + lo;
3120
}
3121

    
3122

    
3123
static inline int Unescape(String* source,
3124
                           int i,
3125
                           int length,
3126
                           int* step) {
3127
  uint16_t character = source->Get(i);
3128
  int32_t hi = 0;
3129
  int32_t lo = 0;
3130
  if (character == '%' &&
3131
      i <= length - 6 &&
3132
      source->Get(i + 1) == 'u' &&
3133
      (hi = TwoDigitHex(source->Get(i + 2),
3134
                        source->Get(i + 3))) != -1 &&
3135
      (lo = TwoDigitHex(source->Get(i + 4),
3136
                        source->Get(i + 5))) != -1) {
3137
    *step = 6;
3138
    return (hi << 8) + lo;
3139
  } else if (character == '%' &&
3140
      i <= length - 3 &&
3141
      (lo = TwoDigitHex(source->Get(i + 1),
3142
                        source->Get(i + 2))) != -1) {
3143
    *step = 3;
3144
    return lo;
3145
  } else {
3146
    *step = 1;
3147
    return character;
3148
  }
3149
}
3150

    
3151

    
3152
static Object* Runtime_URIUnescape(Arguments args) {
3153
  NoHandleAllocation ha;
3154
  ASSERT(args.length() == 1);
3155
  CONVERT_CHECKED(String, source, args[0]);
3156

    
3157
  source->TryFlattenIfNotFlat();
3158

    
3159
  bool ascii = true;
3160
  int length = source->length();
3161

    
3162
  int unescaped_length = 0;
3163
  for (int i = 0; i < length; unescaped_length++) {
3164
    int step;
3165
    if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
3166
      ascii = false;
3167
    }
3168
    i += step;
3169
  }
3170

    
3171
  // No length change implies no change.  Return original string if no change.
3172
  if (unescaped_length == length)
3173
    return source;
3174

    
3175
  Object* o = ascii ?
3176
              Heap::AllocateRawAsciiString(unescaped_length) :
3177
              Heap::AllocateRawTwoByteString(unescaped_length);
3178
  if (o->IsFailure()) return o;
3179
  String* destination = String::cast(o);
3180

    
3181
  int dest_position = 0;
3182
  for (int i = 0; i < length; dest_position++) {
3183
    int step;
3184
    destination->Set(dest_position, Unescape(source, i, length, &step));
3185
    i += step;
3186
  }
3187
  return destination;
3188
}
3189

    
3190

    
3191
static Object* Runtime_StringParseInt(Arguments args) {
3192
  NoHandleAllocation ha;
3193

    
3194
  CONVERT_CHECKED(String, s, args[0]);
3195
  CONVERT_DOUBLE_CHECKED(n, args[1]);
3196
  int radix = FastD2I(n);
3197

    
3198
  s->TryFlattenIfNotFlat();
3199

    
3200
  int len = s->length();
3201
  int i;
3202

    
3203
  // Skip leading white space.
3204
  for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ;
3205
  if (i == len) return Heap::nan_value();
3206

    
3207
  // Compute the sign (default to +).
3208
  int sign = 1;
3209
  if (s->Get(i) == '-') {
3210
    sign = -1;
3211
    i++;
3212
  } else if (s->Get(i) == '+') {
3213
    i++;
3214
  }
3215

    
3216
  // Compute the radix if 0.
3217
  if (radix == 0) {
3218
    radix = 10;
3219
    if (i < len && s->Get(i) == '0') {
3220
      radix = 8;
3221
      if (i + 1 < len) {
3222
        int c = s->Get(i + 1);
3223
        if (c == 'x' || c == 'X') {
3224
          radix = 16;
3225
          i += 2;
3226
        }
3227
      }
3228
    }
3229
  } else if (radix == 16) {
3230
    // Allow 0x or 0X prefix if radix is 16.
3231
    if (i + 1 < len && s->Get(i) == '0') {
3232
      int c = s->Get(i + 1);
3233
      if (c == 'x' || c == 'X') i += 2;
3234
    }
3235
  }
3236

    
3237
  RUNTIME_ASSERT(2 <= radix && radix <= 36);
3238
  double value;
3239
  int end_index = StringToInt(s, i, radix, &value);
3240
  if (end_index != i) {
3241
    return Heap::NumberFromDouble(sign * value);
3242
  }
3243
  return Heap::nan_value();
3244
}
3245

    
3246

    
3247
static Object* Runtime_StringParseFloat(Arguments args) {
3248
  NoHandleAllocation ha;
3249
  CONVERT_CHECKED(String, str, args[0]);
3250

    
3251
  // ECMA-262 section 15.1.2.3, empty string is NaN
3252
  double value = StringToDouble(str, ALLOW_TRAILING_JUNK, OS::nan_value());
3253

    
3254
  // Create a number object from the value.
3255
  return Heap::NumberFromDouble(value);
3256
}
3257

    
3258

    
3259
static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
3260
static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
3261

    
3262

    
3263
template <class Converter>
3264
static Object* ConvertCaseHelper(String* s,
3265
                                 int length,
3266
                                 int input_string_length,
3267
                                 unibrow::Mapping<Converter, 128>* mapping) {
3268
  // We try this twice, once with the assumption that the result is no longer
3269
  // than the input and, if that assumption breaks, again with the exact
3270
  // length.  This may not be pretty, but it is nicer than what was here before
3271
  // and I hereby claim my vaffel-is.
3272
  //
3273
  // Allocate the resulting string.
3274
  //
3275
  // NOTE: This assumes that the upper/lower case of an ascii
3276
  // character is also ascii.  This is currently the case, but it
3277
  // might break in the future if we implement more context and locale
3278
  // dependent upper/lower conversions.
3279
  Object* o = StringShape(s).IsAsciiRepresentation()
3280
      ? Heap::AllocateRawAsciiString(length)
3281
      : Heap::AllocateRawTwoByteString(length);
3282
  if (o->IsFailure()) return o;
3283
  String* result = String::cast(o);
3284
  bool has_changed_character = false;
3285

    
3286
  // Convert all characters to upper case, assuming that they will fit
3287
  // in the buffer
3288
  Access<StringInputBuffer> buffer(&runtime_string_input_buffer);
3289
  buffer->Reset(s);
3290
  unibrow::uchar chars[Converter::kMaxWidth];
3291
  // We can assume that the string is not empty
3292
  uc32 current = buffer->GetNext();
3293
  for (int i = 0; i < length;) {
3294
    bool has_next = buffer->has_more();
3295
    uc32 next = has_next ? buffer->GetNext() : 0;
3296
    int char_length = mapping->get(current, next, chars);
3297
    if (char_length == 0) {
3298
      // The case conversion of this character is the character itself.
3299
      result->Set(i, current);
3300
      i++;
3301
    } else if (char_length == 1) {
3302
      // Common case: converting the letter resulted in one character.
3303
      ASSERT(static_cast<uc32>(chars[0]) != current);
3304
      result->Set(i, chars[0]);
3305
      has_changed_character = true;
3306
      i++;
3307
    } else if (length == input_string_length) {
3308
      // We've assumed that the result would be as long as the
3309
      // input but here is a character that converts to several
3310
      // characters.  No matter, we calculate the exact length
3311
      // of the result and try the whole thing again.
3312
      //
3313
      // Note that this leaves room for optimization.  We could just
3314
      // memcpy what we already have to the result string.  Also,
3315
      // the result string is the last object allocated we could
3316
      // "realloc" it and probably, in the vast majority of cases,
3317
      // extend the existing string to be able to hold the full
3318
      // result.
3319
      int next_length = 0;
3320
      if (has_next) {
3321
        next_length = mapping->get(next, 0, chars);
3322
        if (next_length == 0) next_length = 1;
3323
      }
3324
      int current_length = i + char_length + next_length;
3325
      while (buffer->has_more()) {
3326
        current = buffer->GetNext();
3327
        // NOTE: we use 0 as the next character here because, while
3328
        // the next character may affect what a character converts to,
3329
        // it does not in any case affect the length of what it convert
3330
        // to.
3331
        int char_length = mapping->get(current, 0, chars);
3332
        if (char_length == 0) char_length = 1;
3333
        current_length += char_length;
3334
        if (current_length > Smi::kMaxValue) {
3335
          Top::context()->mark_out_of_memory();
3336
          return Failure::OutOfMemoryException();
3337
        }
3338
      }
3339
      // Try again with the real length.
3340
      return Smi::FromInt(current_length);
3341
    } else {
3342
      for (int j = 0; j < char_length; j++) {
3343
        result->Set(i, chars[j]);
3344
        i++;
3345
      }
3346
      has_changed_character = true;
3347
    }
3348
    current = next;
3349
  }
3350
  if (has_changed_character) {
3351
    return result;
3352
  } else {
3353
    // If we didn't actually change anything in doing the conversion
3354
    // we simple return the result and let the converted string
3355
    // become garbage; there is no reason to keep two identical strings
3356
    // alive.
3357
    return s;
3358
  }
3359
}
3360

    
3361

    
3362
template <class Converter>
3363
static Object* ConvertCase(Arguments args,
3364
                           unibrow::Mapping<Converter, 128>* mapping) {
3365
  NoHandleAllocation ha;
3366

    
3367
  CONVERT_CHECKED(String, s, args[0]);
3368
  s->TryFlattenIfNotFlat();
3369

    
3370
  int input_string_length = s->length();
3371
  // Assume that the string is not empty; we need this assumption later
3372
  if (input_string_length == 0) return s;
3373
  int length = input_string_length;
3374

    
3375
  Object* answer = ConvertCaseHelper(s, length, length, mapping);
3376
  if (answer->IsSmi()) {
3377
    // Retry with correct length.
3378
    answer = ConvertCaseHelper(s, Smi::cast(answer)->value(), length, mapping);
3379
  }
3380
  return answer;  // This may be a failure.
3381
}
3382

    
3383

    
3384
static Object* Runtime_StringToLowerCase(Arguments args) {
3385
  return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
3386
}
3387

    
3388

    
3389
static Object* Runtime_StringToUpperCase(Arguments args) {
3390
  return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
3391
}
3392

    
3393

    
3394
bool Runtime::IsUpperCaseChar(uint16_t ch) {
3395
  unibrow::uchar chars[unibrow::ToUppercase::kMaxWidth];
3396
  int char_length = to_upper_mapping.get(ch, 0, chars);
3397
  return char_length == 0;
3398
}
3399

    
3400

    
3401
static Object* Runtime_NumberToString(Arguments args) {
3402
  NoHandleAllocation ha;
3403
  ASSERT(args.length() == 1);
3404

    
3405
  Object* number = args[0];
3406
  RUNTIME_ASSERT(number->IsNumber());
3407

    
3408
  Object* cached = Heap::GetNumberStringCache(number);
3409
  if (cached != Heap::undefined_value()) {
3410
    return cached;
3411
  }
3412

    
3413
  char arr[100];
3414
  Vector<char> buffer(arr, ARRAY_SIZE(arr));
3415
  const char* str;
3416
  if (number->IsSmi()) {
3417
    int num = Smi::cast(number)->value();
3418
    str = IntToCString(num, buffer);
3419
  } else {
3420
    double num = HeapNumber::cast(number)->value();
3421
    str = DoubleToCString(num, buffer);
3422
  }
3423
  Object* result = Heap::AllocateStringFromAscii(CStrVector(str));
3424

    
3425
  if (!result->IsFailure()) {
3426
    Heap::SetNumberStringCache(number, String::cast(result));
3427
  }
3428
  return result;
3429
}
3430

    
3431

    
3432
static Object* Runtime_NumberToInteger(Arguments args) {
3433
  NoHandleAllocation ha;
3434
  ASSERT(args.length() == 1);
3435

    
3436
  Object* obj = args[0];
3437
  if (obj->IsSmi()) return obj;
3438
  CONVERT_DOUBLE_CHECKED(number, obj);
3439
  return Heap::NumberFromDouble(DoubleToInteger(number));
3440
}
3441

    
3442

    
3443
static Object* Runtime_NumberToJSUint32(Arguments args) {
3444
  NoHandleAllocation ha;
3445
  ASSERT(args.length() == 1);
3446

    
3447
  Object* obj = args[0];
3448
  if (obj->IsSmi() && Smi::cast(obj)->value() >= 0) return obj;
3449
  CONVERT_NUMBER_CHECKED(int32_t, number, Uint32, obj);
3450
  return Heap::NumberFromUint32(number);
3451
}
3452

    
3453

    
3454
static Object* Runtime_NumberToJSInt32(Arguments args) {
3455
  NoHandleAllocation ha;
3456
  ASSERT(args.length() == 1);
3457

    
3458
  Object* obj = args[0];
3459
  if (obj->IsSmi()) return obj;
3460
  CONVERT_DOUBLE_CHECKED(number, obj);
3461
  return Heap::NumberFromInt32(DoubleToInt32(number));
3462
}
3463

    
3464

    
3465
// Converts a Number to a Smi, if possible. Returns NaN if the number is not
3466
// a small integer.
3467
static Object* Runtime_NumberToSmi(Arguments args) {
3468
  NoHandleAllocation ha;
3469
  ASSERT(args.length() == 1);
3470

    
3471
  Object* obj = args[0];
3472
  if (obj->IsSmi()) {
3473
    return obj;
3474
  }
3475
  if (obj->IsHeapNumber()) {
3476
    double value = HeapNumber::cast(obj)->value();
3477
    int int_value = FastD2I(value);
3478
    if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
3479
      return Smi::FromInt(int_value);
3480
    }
3481
  }
3482
  return Heap::nan_value();
3483
}
3484

    
3485
static Object* Runtime_NumberAdd(Arguments args) {
3486
  NoHandleAllocation ha;
3487
  ASSERT(args.length() == 2);
3488

    
3489
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3490
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3491
  return Heap::AllocateHeapNumber(x + y);
3492
}
3493

    
3494

    
3495
static Object* Runtime_NumberSub(Arguments args) {
3496
  NoHandleAllocation ha;
3497
  ASSERT(args.length() == 2);
3498

    
3499
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3500
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3501
  return Heap::AllocateHeapNumber(x - y);
3502
}
3503

    
3504

    
3505
static Object* Runtime_NumberMul(Arguments args) {
3506
  NoHandleAllocation ha;
3507
  ASSERT(args.length() == 2);
3508

    
3509
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3510
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3511
  return Heap::AllocateHeapNumber(x * y);
3512
}
3513

    
3514

    
3515
static Object* Runtime_NumberUnaryMinus(Arguments args) {
3516
  NoHandleAllocation ha;
3517
  ASSERT(args.length() == 1);
3518

    
3519
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3520
  return Heap::AllocateHeapNumber(-x);
3521
}
3522

    
3523

    
3524
static Object* Runtime_NumberDiv(Arguments args) {
3525
  NoHandleAllocation ha;
3526
  ASSERT(args.length() == 2);
3527

    
3528
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3529
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3530
  return Heap::NewNumberFromDouble(x / y);
3531
}
3532

    
3533

    
3534
static Object* Runtime_NumberMod(Arguments args) {
3535
  NoHandleAllocation ha;
3536
  ASSERT(args.length() == 2);
3537

    
3538
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3539
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3540

    
3541
#ifdef WIN32
3542
  // Workaround MS fmod bugs. ECMA-262 says:
3543
  // dividend is finite and divisor is an infinity => result equals dividend
3544
  // dividend is a zero and divisor is nonzero finite => result equals dividend
3545
  if (!(isfinite(x) && (!isfinite(y) && !isnan(y))) &&
3546
      !(x == 0 && (y != 0 && isfinite(y))))
3547
#endif
3548
  x = fmod(x, y);
3549
  // NewNumberFromDouble may return a Smi instead of a Number object
3550
  return Heap::NewNumberFromDouble(x);
3551
}
3552

    
3553

    
3554
static Object* Runtime_StringAdd(Arguments args) {
3555
  NoHandleAllocation ha;
3556
  ASSERT(args.length() == 2);
3557

    
3558
  CONVERT_CHECKED(String, str1, args[0]);
3559
  CONVERT_CHECKED(String, str2, args[1]);
3560
  int len1 = str1->length();
3561
  int len2 = str2->length();
3562
  if (len1 == 0) return str2;
3563
  if (len2 == 0) return str1;
3564
  int length_sum = len1 + len2;
3565
  // Make sure that an out of memory exception is thrown if the length
3566
  // of the new cons string is too large to fit in a Smi.
3567
  if (length_sum > Smi::kMaxValue || length_sum < 0) {
3568
    Top::context()->mark_out_of_memory();
3569
    return Failure::OutOfMemoryException();
3570
  }
3571
  return Heap::AllocateConsString(str1, str2);
3572
}
3573

    
3574

    
3575
template<typename sinkchar>
3576
static inline void StringBuilderConcatHelper(String* special,
3577
                                             sinkchar* sink,
3578
                                             FixedArray* fixed_array,
3579
                                             int array_length) {
3580
  int position = 0;
3581
  for (int i = 0; i < array_length; i++) {
3582
    Object* element = fixed_array->get(i);
3583
    if (element->IsSmi()) {
3584
      int encoded_slice = Smi::cast(element)->value();
3585
      int pos = StringBuilderSubstringPosition::decode(encoded_slice);
3586
      int len = StringBuilderSubstringLength::decode(encoded_slice);
3587
      String::WriteToFlat(special,
3588
                          sink + position,
3589
                          pos,
3590
                          pos + len);
3591
      position += len;
3592
    } else {
3593
      String* string = String::cast(element);
3594
      int element_length = string->length();
3595
      String::WriteToFlat(string, sink + position, 0, element_length);
3596
      position += element_length;
3597
    }
3598
  }
3599
}
3600

    
3601

    
3602
static Object* Runtime_StringBuilderConcat(Arguments args) {
3603
  NoHandleAllocation ha;
3604
  ASSERT(args.length() == 2);
3605
  CONVERT_CHECKED(JSArray, array, args[0]);
3606
  CONVERT_CHECKED(String, special, args[1]);
3607
  int special_length = special->length();
3608
  Object* smi_array_length = array->length();
3609
  if (!smi_array_length->IsSmi()) {
3610
    Top::context()->mark_out_of_memory();
3611
    return Failure::OutOfMemoryException();
3612
  }
3613
  int array_length = Smi::cast(smi_array_length)->value();
3614
  if (!array->HasFastElements()) {
3615
    return Top::Throw(Heap::illegal_argument_symbol());
3616
  }
3617
  FixedArray* fixed_array = FixedArray::cast(array->elements());
3618
  if (fixed_array->length() < array_length) {
3619
    array_length = fixed_array->length();
3620
  }
3621

    
3622
  if (array_length == 0) {
3623
    return Heap::empty_string();
3624
  } else if (array_length == 1) {
3625
    Object* first = fixed_array->get(0);
3626
    if (first->IsString()) return first;
3627
  }
3628

    
3629
  bool ascii = StringShape(special).IsAsciiRepresentation();
3630
  int position = 0;
3631
  for (int i = 0; i < array_length; i++) {
3632
    Object* elt = fixed_array->get(i);
3633
    if (elt->IsSmi()) {
3634
      int len = Smi::cast(elt)->value();
3635
      int pos = len >> 11;
3636
      len &= 0x7ff;
3637
      if (pos + len > special_length) {
3638
        return Top::Throw(Heap::illegal_argument_symbol());
3639
      }
3640
      position += len;
3641
    } else if (elt->IsString()) {
3642
      String* element = String::cast(elt);
3643
      int element_length = element->length();
3644
      if (!Smi::IsValid(element_length + position)) {
3645
        Top::context()->mark_out_of_memory();
3646
        return Failure::OutOfMemoryException();
3647
      }
3648
      position += element_length;
3649
      if (ascii && !StringShape(element).IsAsciiRepresentation()) {
3650
        ascii = false;
3651
      }
3652
    } else {
3653
      return Top::Throw(Heap::illegal_argument_symbol());
3654
    }
3655
  }
3656

    
3657
  int length = position;
3658
  Object* object;
3659

    
3660
  if (ascii) {
3661
    object = Heap::AllocateRawAsciiString(length);
3662
    if (object->IsFailure()) return object;
3663
    SeqAsciiString* answer = SeqAsciiString::cast(object);
3664
    StringBuilderConcatHelper(special,
3665
                              answer->GetChars(),
3666
                              fixed_array,
3667
                              array_length);
3668
    return answer;
3669
  } else {
3670
    object = Heap::AllocateRawTwoByteString(length);
3671
    if (object->IsFailure()) return object;
3672
    SeqTwoByteString* answer = SeqTwoByteString::cast(object);
3673
    StringBuilderConcatHelper(special,
3674
                              answer->GetChars(),
3675
                              fixed_array,
3676
                              array_length);
3677
    return answer;
3678
  }
3679
}
3680

    
3681

    
3682
static Object* Runtime_NumberOr(Arguments args) {
3683
  NoHandleAllocation ha;
3684
  ASSERT(args.length() == 2);
3685

    
3686
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
3687
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
3688
  return Heap::NumberFromInt32(x | y);
3689
}
3690

    
3691

    
3692
static Object* Runtime_NumberAnd(Arguments args) {
3693
  NoHandleAllocation ha;
3694
  ASSERT(args.length() == 2);
3695

    
3696
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
3697
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
3698
  return Heap::NumberFromInt32(x & y);
3699
}
3700

    
3701

    
3702
static Object* Runtime_NumberXor(Arguments args) {
3703
  NoHandleAllocation ha;
3704
  ASSERT(args.length() == 2);
3705

    
3706
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
3707
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
3708
  return Heap::NumberFromInt32(x ^ y);
3709
}
3710

    
3711

    
3712
static Object* Runtime_NumberNot(Arguments args) {
3713
  NoHandleAllocation ha;
3714
  ASSERT(args.length() == 1);
3715

    
3716
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
3717
  return Heap::NumberFromInt32(~x);
3718
}
3719

    
3720

    
3721
static Object* Runtime_NumberShl(Arguments args) {
3722
  NoHandleAllocation ha;
3723
  ASSERT(args.length() == 2);
3724

    
3725
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
3726
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
3727
  return Heap::NumberFromInt32(x << (y & 0x1f));
3728
}
3729

    
3730

    
3731
static Object* Runtime_NumberShr(Arguments args) {
3732
  NoHandleAllocation ha;
3733
  ASSERT(args.length() == 2);
3734

    
3735
  CONVERT_NUMBER_CHECKED(uint32_t, x, Uint32, args[0]);
3736
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
3737
  return Heap::NumberFromUint32(x >> (y & 0x1f));
3738
}
3739

    
3740

    
3741
static Object* Runtime_NumberSar(Arguments args) {
3742
  NoHandleAllocation ha;
3743
  ASSERT(args.length() == 2);
3744

    
3745
  CONVERT_NUMBER_CHECKED(int32_t, x, Int32, args[0]);
3746
  CONVERT_NUMBER_CHECKED(int32_t, y, Int32, args[1]);
3747
  return Heap::NumberFromInt32(ArithmeticShiftRight(x, y & 0x1f));
3748
}
3749

    
3750

    
3751
static Object* Runtime_NumberEquals(Arguments args) {
3752
  NoHandleAllocation ha;
3753
  ASSERT(args.length() == 2);
3754

    
3755
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3756
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3757
  if (isnan(x)) return Smi::FromInt(NOT_EQUAL);
3758
  if (isnan(y)) return Smi::FromInt(NOT_EQUAL);
3759
  if (x == y) return Smi::FromInt(EQUAL);
3760
  Object* result;
3761
  if ((fpclassify(x) == FP_ZERO) && (fpclassify(y) == FP_ZERO)) {
3762
    result = Smi::FromInt(EQUAL);
3763
  } else {
3764
    result = Smi::FromInt(NOT_EQUAL);
3765
  }
3766
  return result;
3767
}
3768

    
3769

    
3770
static Object* Runtime_StringEquals(Arguments args) {
3771
  NoHandleAllocation ha;
3772
  ASSERT(args.length() == 2);
3773

    
3774
  CONVERT_CHECKED(String, x, args[0]);
3775
  CONVERT_CHECKED(String, y, args[1]);
3776

    
3777
  bool not_equal = !x->Equals(y);
3778
  // This is slightly convoluted because the value that signifies
3779
  // equality is 0 and inequality is 1 so we have to negate the result
3780
  // from String::Equals.
3781
  ASSERT(not_equal == 0 || not_equal == 1);
3782
  STATIC_CHECK(EQUAL == 0);
3783
  STATIC_CHECK(NOT_EQUAL == 1);
3784
  return Smi::FromInt(not_equal);
3785
}
3786

    
3787

    
3788
static Object* Runtime_NumberCompare(Arguments args) {
3789
  NoHandleAllocation ha;
3790
  ASSERT(args.length() == 3);
3791

    
3792
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3793
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3794
  if (isnan(x) || isnan(y)) return args[2];
3795
  if (x == y) return Smi::FromInt(EQUAL);
3796
  if (isless(x, y)) return Smi::FromInt(LESS);
3797
  return Smi::FromInt(GREATER);
3798
}
3799

    
3800

    
3801
// Compare two Smis as if they were converted to strings and then
3802
// compared lexicographically.
3803
static Object* Runtime_SmiLexicographicCompare(Arguments args) {
3804
  NoHandleAllocation ha;
3805
  ASSERT(args.length() == 2);
3806

    
3807
  // Arrays for the individual characters of the two Smis.  Smis are
3808
  // 31 bit integers and 10 decimal digits are therefore enough.
3809
  static int x_elms[10];
3810
  static int y_elms[10];
3811

    
3812
  // Extract the integer values from the Smis.
3813
  CONVERT_CHECKED(Smi, x, args[0]);
3814
  CONVERT_CHECKED(Smi, y, args[1]);
3815
  int x_value = x->value();
3816
  int y_value = y->value();
3817

    
3818
  // If the integers are equal so are the string representations.
3819
  if (x_value == y_value) return Smi::FromInt(EQUAL);
3820

    
3821
  // If one of the integers are zero the normal integer order is the
3822
  // same as the lexicographic order of the string representations.
3823
  if (x_value == 0 || y_value == 0) return Smi::FromInt(x_value - y_value);
3824

    
3825
  // If only one of the integers is negative the negative number is
3826
  // smallest because the char code of '-' is less than the char code
3827
  // of any digit.  Otherwise, we make both values positive.
3828
  if (x_value < 0 || y_value < 0) {
3829
    if (y_value >= 0) return Smi::FromInt(LESS);
3830
    if (x_value >= 0) return Smi::FromInt(GREATER);
3831
    x_value = -x_value;
3832
    y_value = -y_value;
3833
  }
3834

    
3835
  // Convert the integers to arrays of their decimal digits.
3836
  int x_index = 0;
3837
  int y_index = 0;
3838
  while (x_value > 0) {
3839
    x_elms[x_index++] = x_value % 10;
3840
    x_value /= 10;
3841
  }
3842
  while (y_value > 0) {
3843
    y_elms[y_index++] = y_value % 10;
3844
    y_value /= 10;
3845
  }
3846

    
3847
  // Loop through the arrays of decimal digits finding the first place
3848
  // where they differ.
3849
  while (--x_index >= 0 && --y_index >= 0) {
3850
    int diff = x_elms[x_index] - y_elms[y_index];
3851
    if (diff != 0) return Smi::FromInt(diff);
3852
  }
3853

    
3854
  // If one array is a suffix of the other array, the longest array is
3855
  // the representation of the largest of the Smis in the
3856
  // lexicographic ordering.
3857
  return Smi::FromInt(x_index - y_index);
3858
}
3859

    
3860

    
3861
static Object* Runtime_StringCompare(Arguments args) {
3862
  NoHandleAllocation ha;
3863
  ASSERT(args.length() == 2);
3864

    
3865
  CONVERT_CHECKED(String, x, args[0]);
3866
  CONVERT_CHECKED(String, y, args[1]);
3867

    
3868
  // A few fast case tests before we flatten.
3869
  if (x == y) return Smi::FromInt(EQUAL);
3870
  if (y->length() == 0) {
3871
    if (x->length() == 0) return Smi::FromInt(EQUAL);
3872
    return Smi::FromInt(GREATER);
3873
  } else if (x->length() == 0) {
3874
    return Smi::FromInt(LESS);
3875
  }
3876

    
3877
  int d = x->Get(0) - y->Get(0);
3878
  if (d < 0) return Smi::FromInt(LESS);
3879
  else if (d > 0) return Smi::FromInt(GREATER);
3880

    
3881
  x->TryFlattenIfNotFlat();
3882
  y->TryFlattenIfNotFlat();
3883

    
3884
  static StringInputBuffer bufx;
3885
  static StringInputBuffer bufy;
3886
  bufx.Reset(x);
3887
  bufy.Reset(y);
3888
  while (bufx.has_more() && bufy.has_more()) {
3889
    int d = bufx.GetNext() - bufy.GetNext();
3890
    if (d < 0) return Smi::FromInt(LESS);
3891
    else if (d > 0) return Smi::FromInt(GREATER);
3892
  }
3893

    
3894
  // x is (non-trivial) prefix of y:
3895
  if (bufy.has_more()) return Smi::FromInt(LESS);
3896
  // y is prefix of x:
3897
  return Smi::FromInt(bufx.has_more() ? GREATER : EQUAL);
3898
}
3899

    
3900

    
3901
static Object* Runtime_Math_abs(Arguments args) {
3902
  NoHandleAllocation ha;
3903
  ASSERT(args.length() == 1);
3904

    
3905
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3906
  return Heap::AllocateHeapNumber(fabs(x));
3907
}
3908

    
3909

    
3910
static Object* Runtime_Math_acos(Arguments args) {
3911
  NoHandleAllocation ha;
3912
  ASSERT(args.length() == 1);
3913

    
3914
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3915
  return Heap::AllocateHeapNumber(acos(x));
3916
}
3917

    
3918

    
3919
static Object* Runtime_Math_asin(Arguments args) {
3920
  NoHandleAllocation ha;
3921
  ASSERT(args.length() == 1);
3922

    
3923
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3924
  return Heap::AllocateHeapNumber(asin(x));
3925
}
3926

    
3927

    
3928
static Object* Runtime_Math_atan(Arguments args) {
3929
  NoHandleAllocation ha;
3930
  ASSERT(args.length() == 1);
3931

    
3932
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3933
  return Heap::AllocateHeapNumber(atan(x));
3934
}
3935

    
3936

    
3937
static Object* Runtime_Math_atan2(Arguments args) {
3938
  NoHandleAllocation ha;
3939
  ASSERT(args.length() == 2);
3940

    
3941
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3942
  CONVERT_DOUBLE_CHECKED(y, args[1]);
3943
  double result;
3944
  if (isinf(x) && isinf(y)) {
3945
    // Make sure that the result in case of two infinite arguments
3946
    // is a multiple of Pi / 4. The sign of the result is determined
3947
    // by the first argument (x) and the sign of the second argument
3948
    // determines the multiplier: one or three.
3949
    static double kPiDividedBy4 = 0.78539816339744830962;
3950
    int multiplier = (x < 0) ? -1 : 1;
3951
    if (y < 0) multiplier *= 3;
3952
    result = multiplier * kPiDividedBy4;
3953
  } else {
3954
    result = atan2(x, y);
3955
  }
3956
  return Heap::AllocateHeapNumber(result);
3957
}
3958

    
3959

    
3960
static Object* Runtime_Math_ceil(Arguments args) {
3961
  NoHandleAllocation ha;
3962
  ASSERT(args.length() == 1);
3963

    
3964
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3965
  return Heap::NumberFromDouble(ceiling(x));
3966
}
3967

    
3968

    
3969
static Object* Runtime_Math_cos(Arguments args) {
3970
  NoHandleAllocation ha;
3971
  ASSERT(args.length() == 1);
3972

    
3973
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3974
  return Heap::AllocateHeapNumber(cos(x));
3975
}
3976

    
3977

    
3978
static Object* Runtime_Math_exp(Arguments args) {
3979
  NoHandleAllocation ha;
3980
  ASSERT(args.length() == 1);
3981

    
3982
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3983
  return Heap::AllocateHeapNumber(exp(x));
3984
}
3985

    
3986

    
3987
static Object* Runtime_Math_floor(Arguments args) {
3988
  NoHandleAllocation ha;
3989
  ASSERT(args.length() == 1);
3990

    
3991
  CONVERT_DOUBLE_CHECKED(x, args[0]);
3992
  return Heap::NumberFromDouble(floor(x));
3993
}
3994

    
3995

    
3996
static Object* Runtime_Math_log(Arguments args) {
3997
  NoHandleAllocation ha;
3998
  ASSERT(args.length() == 1);
3999

    
4000
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4001
  return Heap::AllocateHeapNumber(log(x));
4002
}
4003

    
4004

    
4005
static Object* Runtime_Math_pow(Arguments args) {
4006
  NoHandleAllocation ha;
4007
  ASSERT(args.length() == 2);
4008

    
4009
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4010
  CONVERT_DOUBLE_CHECKED(y, args[1]);
4011
  if (isnan(y) || ((x == 1 || x == -1) && isinf(y))) {
4012
    return Heap::nan_value();
4013
  } else if (y == 0) {
4014
    return Smi::FromInt(1);
4015
  } else {
4016
    return Heap::AllocateHeapNumber(pow(x, y));
4017
  }
4018
}
4019

    
4020
// Returns a number value with positive sign, greater than or equal to
4021
// 0 but less than 1, chosen randomly.
4022
static Object* Runtime_Math_random(Arguments args) {
4023
  NoHandleAllocation ha;
4024
  ASSERT(args.length() == 0);
4025

    
4026
  // To get much better precision, we combine the results of two
4027
  // invocations of random(). The result is computed by normalizing a
4028
  // double in the range [0, RAND_MAX + 1) obtained by adding the
4029
  // high-order bits in the range [0, RAND_MAX] with the low-order
4030
  // bits in the range [0, 1).
4031
  double lo = static_cast<double>(random()) * (1.0 / (RAND_MAX + 1.0));
4032
  double hi = static_cast<double>(random());
4033
  double result = (hi + lo) * (1.0 / (RAND_MAX + 1.0));
4034
  ASSERT(result >= 0 && result < 1);
4035
  return Heap::AllocateHeapNumber(result);
4036
}
4037

    
4038

    
4039
static Object* Runtime_Math_round(Arguments args) {
4040
  NoHandleAllocation ha;
4041
  ASSERT(args.length() == 1);
4042

    
4043
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4044
  if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
4045
  return Heap::NumberFromDouble(floor(x + 0.5));
4046
}
4047

    
4048

    
4049
static Object* Runtime_Math_sin(Arguments args) {
4050
  NoHandleAllocation ha;
4051
  ASSERT(args.length() == 1);
4052

    
4053
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4054
  return Heap::AllocateHeapNumber(sin(x));
4055
}
4056

    
4057

    
4058
static Object* Runtime_Math_sqrt(Arguments args) {
4059
  NoHandleAllocation ha;
4060
  ASSERT(args.length() == 1);
4061

    
4062
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4063
  return Heap::AllocateHeapNumber(sqrt(x));
4064
}
4065

    
4066

    
4067
static Object* Runtime_Math_tan(Arguments args) {
4068
  NoHandleAllocation ha;
4069
  ASSERT(args.length() == 1);
4070

    
4071
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4072
  return Heap::AllocateHeapNumber(tan(x));
4073
}
4074

    
4075

    
4076
// The NewArguments function is only used when constructing the
4077
// arguments array when calling non-functions from JavaScript in
4078
// runtime.js:CALL_NON_FUNCTION.
4079
static Object* Runtime_NewArguments(Arguments args) {
4080
  NoHandleAllocation ha;
4081
  ASSERT(args.length() == 1);
4082

    
4083
  // ECMA-262, 3rd., 10.1.8, p.39
4084
  CONVERT_CHECKED(JSFunction, callee, args[0]);
4085

    
4086
  // Compute the frame holding the arguments.
4087
  JavaScriptFrameIterator it;
4088
  it.AdvanceToArgumentsFrame();
4089
  JavaScriptFrame* frame = it.frame();
4090

    
4091
  const int length = frame->GetProvidedParametersCount();
4092
  Object* result = Heap::AllocateArgumentsObject(callee, length);
4093
  if (result->IsFailure()) return result;
4094
  if (length > 0) {
4095
    Object* obj =  Heap::AllocateFixedArray(length);
4096
    if (obj->IsFailure()) return obj;
4097
    FixedArray* array = FixedArray::cast(obj);
4098
    ASSERT(array->length() == length);
4099
    WriteBarrierMode mode = array->GetWriteBarrierMode();
4100
    for (int i = 0; i < length; i++) {
4101
      array->set(i, frame->GetParameter(i), mode);
4102
    }
4103
    JSObject::cast(result)->set_elements(array);
4104
  }
4105
  return result;
4106
}
4107

    
4108

    
4109
static Object* Runtime_NewArgumentsFast(Arguments args) {
4110
  NoHandleAllocation ha;
4111
  ASSERT(args.length() == 3);
4112

    
4113
  JSFunction* callee = JSFunction::cast(args[0]);
4114
  Object** parameters = reinterpret_cast<Object**>(args[1]);
4115
  const int length = Smi::cast(args[2])->value();
4116

    
4117
  Object* result = Heap::AllocateArgumentsObject(callee, length);
4118
  if (result->IsFailure()) return result;
4119
  ASSERT(Heap::InNewSpace(result));
4120

    
4121
  // Allocate the elements if needed.
4122
  if (length > 0) {
4123
    // Allocate the fixed array.
4124
    Object* obj = Heap::AllocateRawFixedArray(length);
4125
    if (obj->IsFailure()) return obj;
4126
    reinterpret_cast<Array*>(obj)->set_map(Heap::fixed_array_map());
4127
    FixedArray* array = FixedArray::cast(obj);
4128
    array->set_length(length);
4129
    WriteBarrierMode mode = array->GetWriteBarrierMode();
4130
    for (int i = 0; i < length; i++) {
4131
      array->set(i, *--parameters, mode);
4132
    }
4133
    JSObject::cast(result)->set_elements(FixedArray::cast(obj),
4134
                                         SKIP_WRITE_BARRIER);
4135
  }
4136
  return result;
4137
}
4138

    
4139

    
4140
static Object* Runtime_NewClosure(Arguments args) {
4141
  HandleScope scope;
4142
  ASSERT(args.length() == 2);
4143
  CONVERT_ARG_CHECKED(JSFunction, boilerplate, 0);
4144
  CONVERT_ARG_CHECKED(Context, context, 1);
4145

    
4146
  Handle<JSFunction> result =
4147
      Factory::NewFunctionFromBoilerplate(boilerplate, context);
4148
  return *result;
4149
}
4150

    
4151

    
4152
static Object* Runtime_NewObject(Arguments args) {
4153
  NoHandleAllocation ha;
4154
  ASSERT(args.length() == 1);
4155

    
4156
  Object* constructor = args[0];
4157
  if (constructor->IsJSFunction()) {
4158
    JSFunction* function = JSFunction::cast(constructor);
4159

    
4160
    // Handle stepping into constructors if step into is active.
4161
    if (Debug::StepInActive()) {
4162
      HandleScope scope;
4163
      Debug::HandleStepIn(Handle<JSFunction>(function), 0, true);
4164
    }
4165

    
4166
    if (function->has_initial_map() &&
4167
        function->initial_map()->instance_type() == JS_FUNCTION_TYPE) {
4168
      // The 'Function' function ignores the receiver object when
4169
      // called using 'new' and creates a new JSFunction object that
4170
      // is returned.  The receiver object is only used for error
4171
      // reporting if an error occurs when constructing the new
4172
      // JSFunction.  AllocateJSObject should not be used to allocate
4173
      // JSFunctions since it does not properly initialize the shared
4174
      // part of the function.  Since the receiver is ignored anyway,
4175
      // we use the global object as the receiver instead of a new
4176
      // JSFunction object.  This way, errors are reported the same
4177
      // way whether or not 'Function' is called using 'new'.
4178
      return Top::context()->global();
4179
    }
4180
    return Heap::AllocateJSObject(function);
4181
  }
4182

    
4183
  HandleScope scope;
4184
  Handle<Object> cons(constructor);
4185
  // The constructor is not a function; throw a type error.
4186
  Handle<Object> type_error =
4187
    Factory::NewTypeError("not_constructor", HandleVector(&cons, 1));
4188
  return Top::Throw(*type_error);
4189
}
4190

    
4191

    
4192
static Object* Runtime_LazyCompile(Arguments args) {
4193
  HandleScope scope;
4194
  ASSERT(args.length() == 1);
4195

    
4196
  Handle<JSFunction> function = args.at<JSFunction>(0);
4197
#ifdef DEBUG
4198
  if (FLAG_trace_lazy) {
4199
    PrintF("[lazy: ");
4200
    function->shared()->name()->Print();
4201
    PrintF("]\n");
4202
  }
4203
#endif
4204

    
4205
  // Compile the target function.
4206
  ASSERT(!function->is_compiled());
4207
  if (!CompileLazy(function, KEEP_EXCEPTION)) {
4208
    return Failure::Exception();
4209
  }
4210

    
4211
  return function->code();
4212
}
4213

    
4214

    
4215
static Object* Runtime_GetCalledFunction(Arguments args) {
4216
  HandleScope scope;
4217
  ASSERT(args.length() == 0);
4218
  StackFrameIterator it;
4219
  // Get past the JS-to-C exit frame.
4220
  ASSERT(it.frame()->is_exit());
4221
  it.Advance();
4222
  // Get past the CALL_NON_FUNCTION activation frame.
4223
  ASSERT(it.frame()->is_java_script());
4224
  it.Advance();
4225
  // Argument adaptor frames do not copy the function; we have to skip
4226
  // past them to get to the real calling frame.
4227
  if (it.frame()->is_arguments_adaptor()) it.Advance();
4228
  // Get the function from the top of the expression stack of the
4229
  // calling frame.
4230
  StandardFrame* frame = StandardFrame::cast(it.frame());
4231
  int index = frame->ComputeExpressionsCount() - 1;
4232
  Object* result = frame->GetExpression(index);
4233
  return result;
4234
}
4235

    
4236

    
4237
static Object* Runtime_GetFunctionDelegate(Arguments args) {
4238
  HandleScope scope;
4239
  ASSERT(args.length() == 1);
4240
  RUNTIME_ASSERT(!args[0]->IsJSFunction());
4241
  return *Execution::GetFunctionDelegate(args.at<Object>(0));
4242
}
4243

    
4244

    
4245
static Object* Runtime_NewContext(Arguments args) {
4246
  NoHandleAllocation ha;
4247
  ASSERT(args.length() == 1);
4248

    
4249
  CONVERT_CHECKED(JSFunction, function, args[0]);
4250
  int length = ScopeInfo<>::NumberOfContextSlots(function->code());
4251
  Object* result = Heap::AllocateFunctionContext(length, function);
4252
  if (result->IsFailure()) return result;
4253

    
4254
  Top::set_context(Context::cast(result));
4255

    
4256
  return result;  // non-failure
4257
}
4258

    
4259
static Object* PushContextHelper(Object* object, bool is_catch_context) {
4260
  // Convert the object to a proper JavaScript object.
4261
  Object* js_object = object;
4262
  if (!js_object->IsJSObject()) {
4263
    js_object = js_object->ToObject();
4264
    if (js_object->IsFailure()) {
4265
      if (!Failure::cast(js_object)->IsInternalError()) return js_object;
4266
      HandleScope scope;
4267
      Handle<Object> handle(object);
4268
      Handle<Object> result =
4269
          Factory::NewTypeError("with_expression", HandleVector(&handle, 1));
4270
      return Top::Throw(*result);
4271
    }
4272
  }
4273

    
4274
  Object* result =
4275
      Heap::AllocateWithContext(Top::context(),
4276
                                JSObject::cast(js_object),
4277
                                is_catch_context);
4278
  if (result->IsFailure()) return result;
4279

    
4280
  Context* context = Context::cast(result);
4281
  Top::set_context(context);
4282

    
4283
  return result;
4284
}
4285

    
4286

    
4287
static Object* Runtime_PushContext(Arguments args) {
4288
  NoHandleAllocation ha;
4289
  ASSERT(args.length() == 1);
4290
  return PushContextHelper(args[0], false);
4291
}
4292

    
4293

    
4294
static Object* Runtime_PushCatchContext(Arguments args) {
4295
  NoHandleAllocation ha;
4296
  ASSERT(args.length() == 1);
4297
  return PushContextHelper(args[0], true);
4298
}
4299

    
4300

    
4301
static Object* Runtime_LookupContext(Arguments args) {
4302
  HandleScope scope;
4303
  ASSERT(args.length() == 2);
4304

    
4305
  CONVERT_ARG_CHECKED(Context, context, 0);
4306
  CONVERT_ARG_CHECKED(String, name, 1);
4307

    
4308
  int index;
4309
  PropertyAttributes attributes;
4310
  ContextLookupFlags flags = FOLLOW_CHAINS;
4311
  Handle<Object> holder =
4312
      context->Lookup(name, flags, &index, &attributes);
4313

    
4314
  if (index < 0 && !holder.is_null()) {
4315
    ASSERT(holder->IsJSObject());
4316
    return *holder;
4317
  }
4318

    
4319
  // No intermediate context found. Use global object by default.
4320
  return Top::context()->global();
4321
}
4322

    
4323

    
4324
// A mechanism to return pairs of Object*'s. This is somewhat
4325
// compiler-dependent as it assumes that a 64-bit value (a long long)
4326
// is returned via two registers (edx:eax on ia32). Both the ia32 and
4327
// arm platform support this; it is mostly an issue of "coaxing" the
4328
// compiler to do the right thing.
4329
//
4330
// TODO(1236026): This is a non-portable hack that should be removed.
4331
typedef uint64_t ObjectPair;
4332
static inline ObjectPair MakePair(Object* x, Object* y) {
4333
  return reinterpret_cast<uint32_t>(x) |
4334
      (reinterpret_cast<ObjectPair>(y) << 32);
4335
}
4336

    
4337

    
4338
static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
4339
  ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
4340
  USE(attributes);
4341
  return x->IsTheHole() ? Heap::undefined_value() : x;
4342
}
4343

    
4344

    
4345
static JSObject* ComputeReceiverForNonGlobal(JSObject* holder) {
4346
  ASSERT(!holder->IsGlobalObject());
4347
  Context* top = Top::context();
4348
  // Get the context extension function.
4349
  JSFunction* context_extension_function =
4350
      top->global_context()->context_extension_function();
4351
  // If the holder isn't a context extension object, we just return it
4352
  // as the receiver. This allows arguments objects to be used as
4353
  // receivers, but only if they are put in the context scope chain
4354
  // explicitly via a with-statement.
4355
  Object* constructor = holder->map()->constructor();
4356
  if (constructor != context_extension_function) return holder;
4357
  // Fall back to using the global object as the receiver if the
4358
  // property turns out to be a local variable allocated in a context
4359
  // extension object - introduced via eval.
4360
  return top->global()->global_receiver();
4361
}
4362

    
4363

    
4364
static ObjectPair LoadContextSlotHelper(Arguments args, bool throw_error) {
4365
  HandleScope scope;
4366
  ASSERT(args.length() == 2);
4367

    
4368
  if (!args[0]->IsContext() || !args[1]->IsString()) {
4369
    return MakePair(IllegalOperation(), NULL);
4370
  }
4371
  Handle<Context> context = args.at<Context>(0);
4372
  Handle<String> name = args.at<String>(1);
4373

    
4374
  int index;
4375
  PropertyAttributes attributes;
4376
  ContextLookupFlags flags = FOLLOW_CHAINS;
4377
  Handle<Object> holder =
4378
      context->Lookup(name, flags, &index, &attributes);
4379

    
4380
  // If the index is non-negative, the slot has been found in a local
4381
  // variable or a parameter. Read it from the context object or the
4382
  // arguments object.
4383
  if (index >= 0) {
4384
    // If the "property" we were looking for is a local variable or an
4385
    // argument in a context, the receiver is the global object; see
4386
    // ECMA-262, 3rd., 10.1.6 and 10.2.3.
4387
    JSObject* receiver = Top::context()->global()->global_receiver();
4388
    Object* value = (holder->IsContext())
4389
        ? Context::cast(*holder)->get(index)
4390
        : JSObject::cast(*holder)->GetElement(index);
4391
    return MakePair(Unhole(value, attributes), receiver);
4392
  }
4393

    
4394
  // If the holder is found, we read the property from it.
4395
  if (!holder.is_null() && holder->IsJSObject()) {
4396
    ASSERT(Handle<JSObject>::cast(holder)->HasProperty(*name));
4397
    JSObject* object = JSObject::cast(*holder);
4398
    JSObject* receiver;
4399
    if (object->IsGlobalObject()) {
4400
      receiver = GlobalObject::cast(object)->global_receiver();
4401
    } else if (context->is_exception_holder(*holder)) {
4402
      receiver = Top::context()->global()->global_receiver();
4403
    } else {
4404
      receiver = ComputeReceiverForNonGlobal(object);
4405
    }
4406
    // No need to unhole the value here. This is taken care of by the
4407
    // GetProperty function.
4408
    Object* value = object->GetProperty(*name);
4409
    return MakePair(value, receiver);
4410
  }
4411

    
4412
  if (throw_error) {
4413
    // The property doesn't exist - throw exception.
4414
    Handle<Object> reference_error =
4415
        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
4416
    return MakePair(Top::Throw(*reference_error), NULL);
4417
  } else {
4418
    // The property doesn't exist - return undefined
4419
    return MakePair(Heap::undefined_value(), Heap::undefined_value());
4420
  }
4421
}
4422

    
4423

    
4424
static ObjectPair Runtime_LoadContextSlot(Arguments args) {
4425
  return LoadContextSlotHelper(args, true);
4426
}
4427

    
4428

    
4429
static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) {
4430
  return LoadContextSlotHelper(args, false);
4431
}
4432

    
4433

    
4434
static Object* Runtime_StoreContextSlot(Arguments args) {
4435
  HandleScope scope;
4436
  ASSERT(args.length() == 3);
4437

    
4438
  Handle<Object> value(args[0]);
4439
  CONVERT_ARG_CHECKED(Context, context, 1);
4440
  CONVERT_ARG_CHECKED(String, name, 2);
4441

    
4442
  int index;
4443
  PropertyAttributes attributes;
4444
  ContextLookupFlags flags = FOLLOW_CHAINS;
4445
  Handle<Object> holder =
4446
      context->Lookup(name, flags, &index, &attributes);
4447

    
4448
  if (index >= 0) {
4449
    if (holder->IsContext()) {
4450
      // Ignore if read_only variable.
4451
      if ((attributes & READ_ONLY) == 0) {
4452
        Handle<Context>::cast(holder)->set(index, *value);
4453
      }
4454
    } else {
4455
      ASSERT((attributes & READ_ONLY) == 0);
4456
      Object* result =
4457
          Handle<JSObject>::cast(holder)->SetElement(index, *value);
4458
      USE(result);
4459
      ASSERT(!result->IsFailure());
4460
    }
4461
    return *value;
4462
  }
4463

    
4464
  // Slow case: The property is not in a FixedArray context.
4465
  // It is either in an JSObject extension context or it was not found.
4466
  Handle<JSObject> context_ext;
4467

    
4468
  if (!holder.is_null()) {
4469
    // The property exists in the extension context.
4470
    context_ext = Handle<JSObject>::cast(holder);
4471
  } else {
4472
    // The property was not found. It needs to be stored in the global context.
4473
    ASSERT(attributes == ABSENT);
4474
    attributes = NONE;
4475
    context_ext = Handle<JSObject>(Top::context()->global());
4476
  }
4477

    
4478
  // Set the property, but ignore if read_only variable on the context
4479
  // extension object itself.
4480
  if ((attributes & READ_ONLY) == 0 ||
4481
      (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) {
4482
    Handle<Object> set = SetProperty(context_ext, name, value, attributes);
4483
    if (set.is_null()) {
4484
      // Failure::Exception is converted to a null handle in the
4485
      // handle-based methods such as SetProperty.  We therefore need
4486
      // to convert null handles back to exceptions.
4487
      ASSERT(Top::has_pending_exception());
4488
      return Failure::Exception();
4489
    }
4490
  }
4491
  return *value;
4492
}
4493

    
4494

    
4495
static Object* Runtime_Throw(Arguments args) {
4496
  HandleScope scope;
4497
  ASSERT(args.length() == 1);
4498

    
4499
  return Top::Throw(args[0]);
4500
}
4501

    
4502

    
4503
static Object* Runtime_ReThrow(Arguments args) {
4504
  HandleScope scope;
4505
  ASSERT(args.length() == 1);
4506

    
4507
  return Top::ReThrow(args[0]);
4508
}
4509

    
4510

    
4511
static Object* Runtime_ThrowReferenceError(Arguments args) {
4512
  HandleScope scope;
4513
  ASSERT(args.length() == 1);
4514

    
4515
  Handle<Object> name(args[0]);
4516
  Handle<Object> reference_error =
4517
    Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
4518
  return Top::Throw(*reference_error);
4519
}
4520

    
4521

    
4522
static Object* Runtime_StackOverflow(Arguments args) {
4523
  NoHandleAllocation na;
4524
  return Top::StackOverflow();
4525
}
4526

    
4527

    
4528
static Object* Runtime_DebugBreak(Arguments args) {
4529
  ASSERT(args.length() == 0);
4530
  return Execution::DebugBreakHelper();
4531
}
4532

    
4533

    
4534
static Object* Runtime_StackGuard(Arguments args) {
4535
  ASSERT(args.length() == 1);
4536

    
4537
  // First check if this is a real stack overflow.
4538
  if (StackGuard::IsStackOverflow()) {
4539
    return Runtime_StackOverflow(args);
4540
  }
4541

    
4542
  return Execution::HandleStackGuardInterrupt();
4543
}
4544

    
4545

    
4546
// NOTE: These PrintXXX functions are defined for all builds (not just
4547
// DEBUG builds) because we may want to be able to trace function
4548
// calls in all modes.
4549
static void PrintString(String* str) {
4550
  // not uncommon to have empty strings
4551
  if (str->length() > 0) {
4552
    SmartPointer<char> s =
4553
        str->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
4554
    PrintF("%s", *s);
4555
  }
4556
}
4557

    
4558

    
4559
static void PrintObject(Object* obj) {
4560
  if (obj->IsSmi()) {
4561
    PrintF("%d", Smi::cast(obj)->value());
4562
  } else if (obj->IsString() || obj->IsSymbol()) {
4563
    PrintString(String::cast(obj));
4564
  } else if (obj->IsNumber()) {
4565
    PrintF("%g", obj->Number());
4566
  } else if (obj->IsFailure()) {
4567
    PrintF("<failure>");
4568
  } else if (obj->IsUndefined()) {
4569
    PrintF("<undefined>");
4570
  } else if (obj->IsNull()) {
4571
    PrintF("<null>");
4572
  } else if (obj->IsTrue()) {
4573
    PrintF("<true>");
4574
  } else if (obj->IsFalse()) {
4575
    PrintF("<false>");
4576
  } else {
4577
    PrintF("%p", obj);
4578
  }
4579
}
4580

    
4581

    
4582
static int StackSize() {
4583
  int n = 0;
4584
  for (JavaScriptFrameIterator it; !it.done(); it.Advance()) n++;
4585
  return n;
4586
}
4587

    
4588

    
4589
static void PrintTransition(Object* result) {
4590
  // indentation
4591
  { const int nmax = 80;
4592
    int n = StackSize();
4593
    if (n <= nmax)
4594
      PrintF("%4d:%*s", n, n, "");
4595
    else
4596
      PrintF("%4d:%*s", n, nmax, "...");
4597
  }
4598

    
4599
  if (result == NULL) {
4600
    // constructor calls
4601
    JavaScriptFrameIterator it;
4602
    JavaScriptFrame* frame = it.frame();
4603
    if (frame->IsConstructor()) PrintF("new ");
4604
    // function name
4605
    Object* fun = frame->function();
4606
    if (fun->IsJSFunction()) {
4607
      PrintObject(JSFunction::cast(fun)->shared()->name());
4608
    } else {
4609
      PrintObject(fun);
4610
    }
4611
    // function arguments
4612
    // (we are intentionally only printing the actually
4613
    // supplied parameters, not all parameters required)
4614
    PrintF("(this=");
4615
    PrintObject(frame->receiver());
4616
    const int length = frame->GetProvidedParametersCount();
4617
    for (int i = 0; i < length; i++) {
4618
      PrintF(", ");
4619
      PrintObject(frame->GetParameter(i));
4620
    }
4621
    PrintF(") {\n");
4622

    
4623
  } else {
4624
    // function result
4625
    PrintF("} -> ");
4626
    PrintObject(result);
4627
    PrintF("\n");
4628
  }
4629
}
4630

    
4631

    
4632
static Object* Runtime_TraceEnter(Arguments args) {
4633
  ASSERT(args.length() == 0);
4634
  NoHandleAllocation ha;
4635
  PrintTransition(NULL);
4636
  return Heap::undefined_value();
4637
}
4638

    
4639

    
4640
static Object* Runtime_TraceExit(Arguments args) {
4641
  NoHandleAllocation ha;
4642
  PrintTransition(args[0]);
4643
  return args[0];  // return TOS
4644
}
4645

    
4646

    
4647
static Object* Runtime_DebugPrint(Arguments args) {
4648
  NoHandleAllocation ha;
4649
  ASSERT(args.length() == 1);
4650

    
4651
#ifdef DEBUG
4652
  if (args[0]->IsString()) {
4653
    // If we have a string, assume it's a code "marker"
4654
    // and print some interesting cpu debugging info.
4655
    JavaScriptFrameIterator it;
4656
    JavaScriptFrame* frame = it.frame();
4657
    PrintF("fp = %p, sp = %p, pp = %p: ",
4658
           frame->fp(), frame->sp(), frame->pp());
4659
  } else {
4660
    PrintF("DebugPrint: ");
4661
  }
4662
  args[0]->Print();
4663
#else
4664
  // ShortPrint is available in release mode. Print is not.
4665
  args[0]->ShortPrint();
4666
#endif
4667
  PrintF("\n");
4668
  Flush();
4669

    
4670
  return args[0];  // return TOS
4671
}
4672

    
4673

    
4674
static Object* Runtime_DebugTrace(Arguments args) {
4675
  ASSERT(args.length() == 0);
4676
  NoHandleAllocation ha;
4677
  Top::PrintStack();
4678
  return Heap::undefined_value();
4679
}
4680

    
4681

    
4682
static Object* Runtime_DateCurrentTime(Arguments args) {
4683
  NoHandleAllocation ha;
4684
  ASSERT(args.length() == 0);
4685

    
4686
  // According to ECMA-262, section 15.9.1, page 117, the precision of
4687
  // the number in a Date object representing a particular instant in
4688
  // time is milliseconds. Therefore, we floor the result of getting
4689
  // the OS time.
4690
  double millis = floor(OS::TimeCurrentMillis());
4691
  return Heap::NumberFromDouble(millis);
4692
}
4693

    
4694

    
4695
static Object* Runtime_DateParseString(Arguments args) {
4696
  HandleScope scope;
4697
  ASSERT(args.length() == 2);
4698

    
4699
  CONVERT_ARG_CHECKED(String, str, 0);
4700
  FlattenString(str);
4701

    
4702
  CONVERT_ARG_CHECKED(JSArray, output, 1);
4703
  RUNTIME_ASSERT(output->HasFastElements());
4704

    
4705
  AssertNoAllocation no_allocation;
4706

    
4707
  FixedArray* output_array = output->elements();
4708
  RUNTIME_ASSERT(output_array->length() >= DateParser::OUTPUT_SIZE);
4709
  bool result;
4710
  if (StringShape(*str).IsAsciiRepresentation()) {
4711
    result = DateParser::Parse(str->ToAsciiVector(), output_array);
4712
  } else {
4713
    ASSERT(StringShape(*str).IsTwoByteRepresentation());
4714
    result = DateParser::Parse(str->ToUC16Vector(), output_array);
4715
  }
4716

    
4717
  if (result) {
4718
    return *output;
4719
  } else {
4720
    return Heap::null_value();
4721
  }
4722
}
4723

    
4724

    
4725
static Object* Runtime_DateLocalTimezone(Arguments args) {
4726
  NoHandleAllocation ha;
4727
  ASSERT(args.length() == 1);
4728

    
4729
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4730
  char* zone = OS::LocalTimezone(x);
4731
  return Heap::AllocateStringFromUtf8(CStrVector(zone));
4732
}
4733

    
4734

    
4735
static Object* Runtime_DateLocalTimeOffset(Arguments args) {
4736
  NoHandleAllocation ha;
4737
  ASSERT(args.length() == 0);
4738

    
4739
  return Heap::NumberFromDouble(OS::LocalTimeOffset());
4740
}
4741

    
4742

    
4743
static Object* Runtime_DateDaylightSavingsOffset(Arguments args) {
4744
  NoHandleAllocation ha;
4745
  ASSERT(args.length() == 1);
4746

    
4747
  CONVERT_DOUBLE_CHECKED(x, args[0]);
4748
  return Heap::NumberFromDouble(OS::DaylightSavingsOffset(x));
4749
}
4750

    
4751

    
4752
static Object* Runtime_NumberIsFinite(Arguments args) {
4753
  NoHandleAllocation ha;
4754
  ASSERT(args.length() == 1);
4755

    
4756
  CONVERT_DOUBLE_CHECKED(value, args[0]);
4757
  Object* result;
4758
  if (isnan(value) || (fpclassify(value) == FP_INFINITE)) {
4759
    result = Heap::false_value();
4760
  } else {
4761
    result = Heap::true_value();
4762
  }
4763
  return result;
4764
}
4765

    
4766

    
4767
static Object* Runtime_GlobalReceiver(Arguments args) {
4768
  ASSERT(args.length() == 1);
4769
  Object* global = args[0];
4770
  if (!global->IsJSGlobalObject()) return Heap::null_value();
4771
  return JSGlobalObject::cast(global)->global_receiver();
4772
}
4773

    
4774

    
4775
static Object* Runtime_CompileString(Arguments args) {
4776
  HandleScope scope;
4777
  ASSERT(args.length() == 2);
4778
  CONVERT_ARG_CHECKED(String, source, 0);
4779
  CONVERT_ARG_CHECKED(Smi, line_offset, 1);
4780

    
4781
  // Compile source string in the global context.
4782
  Handle<Context> context(Top::context()->global_context());
4783
  Handle<JSFunction> boilerplate =
4784
      Compiler::CompileEval(source, context, line_offset->value(), true);
4785
  if (boilerplate.is_null()) return Failure::Exception();
4786
  Handle<JSFunction> fun =
4787
      Factory::NewFunctionFromBoilerplate(boilerplate, context);
4788
  return *fun;
4789
}
4790

    
4791

    
4792
static Handle<JSFunction> GetBuiltinFunction(String* name) {
4793
  LookupResult result;
4794
  Top::global_context()->builtins()->LocalLookup(name, &result);
4795
  return Handle<JSFunction>(JSFunction::cast(result.GetValue()));
4796
}
4797

    
4798

    
4799
static Object* CompileDirectEval(Handle<String> source) {
4800
  // Compute the eval context.
4801
  HandleScope scope;
4802
  StackFrameLocator locator;
4803
  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
4804
  Handle<Context> context(Context::cast(frame->context()));
4805
  bool is_global = context->IsGlobalContext();
4806

    
4807
  // Compile source string in the current context.
4808
  Handle<JSFunction> boilerplate =
4809
      Compiler::CompileEval(source, context, 0, is_global);
4810
  if (boilerplate.is_null()) return Failure::Exception();
4811
  Handle<JSFunction> fun =
4812
    Factory::NewFunctionFromBoilerplate(boilerplate, context);
4813
  return *fun;
4814
}
4815

    
4816

    
4817
static Object* Runtime_ResolvePossiblyDirectEval(Arguments args) {
4818
  ASSERT(args.length() == 2);
4819

    
4820
  HandleScope scope;
4821

    
4822
  CONVERT_ARG_CHECKED(JSFunction, callee, 0);
4823

    
4824
  Handle<Object> receiver;
4825

    
4826
  // Find where the 'eval' symbol is bound. It is unaliased only if
4827
  // it is bound in the global context.
4828
  StackFrameLocator locator;
4829
  JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
4830
  Handle<Context> context(Context::cast(frame->context()));
4831
  int index;
4832
  PropertyAttributes attributes;
4833
  while (!context.is_null()) {
4834
    receiver = context->Lookup(Factory::eval_symbol(), FOLLOW_PROTOTYPE_CHAIN,
4835
                               &index, &attributes);
4836
    // Stop search when eval is found or when the global context is
4837
    // reached.
4838
    if (attributes != ABSENT || context->IsGlobalContext()) break;
4839
    if (context->is_function_context()) {
4840
      context = Handle<Context>(Context::cast(context->closure()->context()));
4841
    } else {
4842
      context = Handle<Context>(context->previous());
4843
    }
4844
  }
4845

    
4846
  // If eval could not be resolved, it has been deleted and we need to
4847
  // throw a reference error.
4848
  if (attributes == ABSENT) {
4849
    Handle<Object> name = Factory::eval_symbol();
4850
    Handle<Object> reference_error =
4851
        Factory::NewReferenceError("not_defined", HandleVector(&name, 1));
4852
    return Top::Throw(*reference_error);
4853
  }
4854

    
4855
  if (context->IsGlobalContext()) {
4856
    // 'eval' is bound in the global context, but it may have been overwritten.
4857
    // Compare it to the builtin 'GlobalEval' function to make sure.
4858
    Handle<JSFunction> global_eval =
4859
      GetBuiltinFunction(Heap::global_eval_symbol());
4860
    if (global_eval.is_identical_to(callee)) {
4861
      // A direct eval call.
4862
      if (args[1]->IsString()) {
4863
        CONVERT_ARG_CHECKED(String, source, 1);
4864
        // A normal eval call on a string. Compile it and return the
4865
        // compiled function bound in the local context.
4866
        Object* compiled_source = CompileDirectEval(source);
4867
        if (compiled_source->IsFailure()) return compiled_source;
4868
        receiver = Handle<Object>(frame->receiver());
4869
        callee = Handle<JSFunction>(JSFunction::cast(compiled_source));
4870
      } else {
4871
        // An eval call that is not called on a string. Global eval
4872
        // deals better with this.
4873
        receiver = Handle<Object>(Top::global_context()->global());
4874
      }
4875
    } else {
4876
      // 'eval' is overwritten. Just call the function with the given arguments.
4877
      receiver = Handle<Object>(Top::global_context()->global());
4878
    }
4879
  } else {
4880
    // 'eval' is not bound in the global context. Just call the function
4881
    // with the given arguments. This is not necessarily the global eval.
4882
    if (receiver->IsContext()) {
4883
      context = Handle<Context>::cast(receiver);
4884
      receiver = Handle<Object>(context->get(index));
4885
    }
4886
  }
4887

    
4888
  Handle<FixedArray> call = Factory::NewFixedArray(2);
4889
  call->set(0, *callee);
4890
  call->set(1, *receiver);
4891
  return *call;
4892
}
4893

    
4894

    
4895
static Object* Runtime_CompileScript(Arguments args) {
4896
  HandleScope scope;
4897
  ASSERT(args.length() == 4);
4898

    
4899
  CONVERT_ARG_CHECKED(String, source, 0);
4900
  CONVERT_ARG_CHECKED(String, script, 1);
4901
  CONVERT_CHECKED(Smi, line_attrs, args[2]);
4902
  int line = line_attrs->value();
4903
  CONVERT_CHECKED(Smi, col_attrs, args[3]);
4904
  int col = col_attrs->value();
4905
  Handle<JSFunction> boilerplate =
4906
      Compiler::Compile(source, script, line, col, NULL, NULL);
4907
  if (boilerplate.is_null()) return Failure::Exception();
4908
  Handle<JSFunction> fun =
4909
      Factory::NewFunctionFromBoilerplate(boilerplate,
4910
                                          Handle<Context>(Top::context()));
4911
  return *fun;
4912
}
4913

    
4914

    
4915
static Object* Runtime_SetNewFunctionAttributes(Arguments args) {
4916
  // This utility adjusts the property attributes for newly created Function
4917
  // object ("new Function(...)") by changing the map.
4918
  // All it does is changing the prototype property to enumerable
4919
  // as specified in ECMA262, 15.3.5.2.
4920
  HandleScope scope;
4921
  ASSERT(args.length() == 1);
4922
  CONVERT_ARG_CHECKED(JSFunction, func, 0);
4923
  ASSERT(func->map()->instance_type() ==
4924
         Top::function_instance_map()->instance_type());
4925
  ASSERT(func->map()->instance_size() ==
4926
         Top::function_instance_map()->instance_size());
4927
  func->set_map(*Top::function_instance_map());
4928
  return *func;
4929
}
4930

    
4931

    
4932
// Push an array unto an array of arrays if it is not already in the
4933
// array.  Returns true if the element was pushed on the stack and
4934
// false otherwise.
4935
static Object* Runtime_PushIfAbsent(Arguments args) {
4936
  ASSERT(args.length() == 2);
4937
  CONVERT_CHECKED(JSArray, array, args[0]);
4938
  CONVERT_CHECKED(JSArray, element, args[1]);
4939
  RUNTIME_ASSERT(array->HasFastElements());
4940
  int length = Smi::cast(array->length())->value();
4941
  FixedArray* elements = FixedArray::cast(array->elements());
4942
  for (int i = 0; i < length; i++) {
4943
    if (elements->get(i) == element) return Heap::false_value();
4944
  }
4945
  Object* obj = array->SetFastElement(length, element);
4946
  if (obj->IsFailure()) return obj;
4947
  return Heap::true_value();
4948
}
4949

    
4950

    
4951
/**
4952
 * A simple visitor visits every element of Array's.
4953
 * The backend storage can be a fixed array for fast elements case,
4954
 * or a dictionary for sparse array. Since Dictionary is a subtype
4955
 * of FixedArray, the class can be used by both fast and slow cases.
4956
 * The second parameter of the constructor, fast_elements, specifies
4957
 * whether the storage is a FixedArray or Dictionary.
4958
 *
4959
 * An index limit is used to deal with the situation that a result array
4960
 * length overflows 32-bit non-negative integer.
4961
 */
4962
class ArrayConcatVisitor {
4963
 public:
4964
  ArrayConcatVisitor(Handle<FixedArray> storage,
4965
                     uint32_t index_limit,
4966
                     bool fast_elements) :
4967
      storage_(storage), index_limit_(index_limit),
4968
      fast_elements_(fast_elements), index_offset_(0) { }
4969

    
4970
  void visit(uint32_t i, Handle<Object> elm) {
4971
    uint32_t index = i + index_offset_;
4972
    if (index >= index_limit_) return;
4973

    
4974
    if (fast_elements_) {
4975
      ASSERT(index < static_cast<uint32_t>(storage_->length()));
4976
      storage_->set(index, *elm);
4977

    
4978
    } else {
4979
      Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_);
4980
      Handle<Dictionary> result =
4981
          Factory::DictionaryAtNumberPut(dict, index, elm);
4982
      if (!result.is_identical_to(dict))
4983
        storage_ = result;
4984
    }
4985
  }
4986

    
4987
  void increase_index_offset(uint32_t delta) {
4988
    index_offset_ += delta;
4989
  }
4990

    
4991
 private:
4992
  Handle<FixedArray> storage_;
4993
  uint32_t index_limit_;
4994
  bool fast_elements_;
4995
  uint32_t index_offset_;
4996
};
4997

    
4998

    
4999
/**
5000
 * A helper function that visits elements of a JSObject. Only elements
5001
 * whose index between 0 and range (exclusive) are visited.
5002
 *
5003
 * If the third parameter, visitor, is not NULL, the visitor is called
5004
 * with parameters, 'visitor_index_offset + element index' and the element.
5005
 *
5006
 * It returns the number of visisted elements.
5007
 */
5008
static uint32_t IterateElements(Handle<JSObject> receiver,
5009
                                uint32_t range,
5010
                                ArrayConcatVisitor* visitor) {
5011
  uint32_t num_of_elements = 0;
5012

    
5013
  if (receiver->HasFastElements()) {
5014
    Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
5015
    uint32_t len = elements->length();
5016
    if (range < len) len = range;
5017

    
5018
    for (uint32_t j = 0; j < len; j++) {
5019
      Handle<Object> e(elements->get(j));
5020
      if (!e->IsTheHole()) {
5021
        num_of_elements++;
5022
        if (visitor)
5023
          visitor->visit(j, e);
5024
      }
5025
    }
5026

    
5027
  } else {
5028
    Handle<Dictionary> dict(receiver->element_dictionary());
5029
    uint32_t capacity = dict->Capacity();
5030
    for (uint32_t j = 0; j < capacity; j++) {
5031
      Handle<Object> k(dict->KeyAt(j));
5032
      if (dict->IsKey(*k)) {
5033
        ASSERT(k->IsNumber());
5034
        uint32_t index = static_cast<uint32_t>(k->Number());
5035
        if (index < range) {
5036
          num_of_elements++;
5037
          if (visitor) {
5038
            visitor->visit(index,
5039
                           Handle<Object>(dict->ValueAt(j)));
5040
          }
5041
        }
5042
      }
5043
    }
5044
  }
5045

    
5046
  return num_of_elements;
5047
}
5048

    
5049

    
5050
/**
5051
 * A helper function that visits elements of an Array object, and elements
5052
 * on its prototypes.
5053
 *
5054
 * Elements on prototypes are visited first, and only elements whose indices
5055
 * less than Array length are visited.
5056
 *
5057
 * If a ArrayConcatVisitor object is given, the visitor is called with
5058
 * parameters, element's index + visitor_index_offset and the element.
5059
 */
5060
static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
5061
                                                 ArrayConcatVisitor* visitor) {
5062
  uint32_t range = static_cast<uint32_t>(array->length()->Number());
5063
  Handle<Object> obj = array;
5064

    
5065
  static const int kEstimatedPrototypes = 3;
5066
  List< Handle<JSObject> > objects(kEstimatedPrototypes);
5067

    
5068
  // Visit prototype first. If an element on the prototype is shadowed by
5069
  // the inheritor using the same index, the ArrayConcatVisitor visits
5070
  // the prototype element before the shadowing element.
5071
  // The visitor can simply overwrite the old value by new value using
5072
  // the same index.  This follows Array::concat semantics.
5073
  while (!obj->IsNull()) {
5074
    objects.Add(Handle<JSObject>::cast(obj));
5075
    obj = Handle<Object>(obj->GetPrototype());
5076
  }
5077

    
5078
  uint32_t nof_elements = 0;
5079
  for (int i = objects.length() - 1; i >= 0; i--) {
5080
    Handle<JSObject> obj = objects[i];
5081
    nof_elements +=
5082
        IterateElements(Handle<JSObject>::cast(obj), range, visitor);
5083
  }
5084

    
5085
  return nof_elements;
5086
}
5087

    
5088

    
5089
/**
5090
 * A helper function of Runtime_ArrayConcat.
5091
 *
5092
 * The first argument is an Array of arrays and objects. It is the
5093
 * same as the arguments array of Array::concat JS function.
5094
 *
5095
 * If an argument is an Array object, the function visits array
5096
 * elements.  If an argument is not an Array object, the function
5097
 * visits the object as if it is an one-element array.
5098
 *
5099
 * If the result array index overflows 32-bit integer, the rounded
5100
 * non-negative number is used as new length. For example, if one
5101
 * array length is 2^32 - 1, second array length is 1, the
5102
 * concatenated array length is 0.
5103
 */
5104
static uint32_t IterateArguments(Handle<JSArray> arguments,
5105
                                 ArrayConcatVisitor* visitor) {
5106
  uint32_t visited_elements = 0;
5107
  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
5108

    
5109
  for (uint32_t i = 0; i < num_of_args; i++) {
5110
    Handle<Object> obj(arguments->GetElement(i));
5111
    if (obj->IsJSArray()) {
5112
      Handle<JSArray> array = Handle<JSArray>::cast(obj);
5113
      uint32_t len = static_cast<uint32_t>(array->length()->Number());
5114
      uint32_t nof_elements =
5115
          IterateArrayAndPrototypeElements(array, visitor);
5116
      // Total elements of array and its prototype chain can be more than
5117
      // the array length, but ArrayConcat can only concatenate at most
5118
      // the array length number of elements.
5119
      visited_elements += (nof_elements > len) ? len : nof_elements;
5120
      if (visitor) visitor->increase_index_offset(len);
5121

    
5122
    } else {
5123
      if (visitor) {
5124
        visitor->visit(0, obj);
5125
        visitor->increase_index_offset(1);
5126
      }
5127
      visited_elements++;
5128
    }
5129
  }
5130
  return visited_elements;
5131
}
5132

    
5133

    
5134
/**
5135
 * Array::concat implementation.
5136
 * See ECMAScript 262, 15.4.4.4.
5137
 */
5138
static Object* Runtime_ArrayConcat(Arguments args) {
5139
  ASSERT(args.length() == 1);
5140
  HandleScope handle_scope;
5141

    
5142
  CONVERT_CHECKED(JSArray, arg_arrays, args[0]);
5143
  Handle<JSArray> arguments(arg_arrays);
5144

    
5145
  // Pass 1: estimate the number of elements of the result
5146
  // (it could be more than real numbers if prototype has elements).
5147
  uint32_t result_length = 0;
5148
  uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
5149

    
5150
  { AssertNoAllocation nogc;
5151
    for (uint32_t i = 0; i < num_of_args; i++) {
5152
      Object* obj = arguments->GetElement(i);
5153
      if (obj->IsJSArray()) {
5154
        result_length +=
5155
            static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
5156
      } else {
5157
        result_length++;
5158
      }
5159
    }
5160
  }
5161

    
5162
  // Allocate an empty array, will set length and content later.
5163
  Handle<JSArray> result = Factory::NewJSArray(0);
5164

    
5165
  uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
5166
  // If estimated number of elements is more than half of length, a
5167
  // fixed array (fast case) is more time and space-efficient than a
5168
  // dictionary.
5169
  bool fast_case = (estimate_nof_elements * 2) >= result_length;
5170

    
5171
  Handle<FixedArray> storage;
5172
  if (fast_case) {
5173
    // The backing storage array must have non-existing elements to
5174
    // preserve holes across concat operations.
5175
    storage = Factory::NewFixedArrayWithHoles(result_length);
5176

    
5177
  } else {
5178
    // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
5179
    uint32_t at_least_space_for = estimate_nof_elements +
5180
                                  (estimate_nof_elements >> 2);
5181
    storage = Handle<FixedArray>::cast(
5182
                  Factory::NewDictionary(at_least_space_for));
5183
  }
5184

    
5185
  Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
5186

    
5187
  ArrayConcatVisitor visitor(storage, result_length, fast_case);
5188

    
5189
  IterateArguments(arguments, &visitor);
5190

    
5191
  result->set_length(*len);
5192
  result->set_elements(*storage);
5193

    
5194
  return *result;
5195
}
5196

    
5197

    
5198
// This will not allocate (flatten the string), but it may run
5199
// very slowly for very deeply nested ConsStrings.  For debugging use only.
5200
static Object* Runtime_GlobalPrint(Arguments args) {
5201
  NoHandleAllocation ha;
5202
  ASSERT(args.length() == 1);
5203

    
5204
  CONVERT_CHECKED(String, string, args[0]);
5205
  StringInputBuffer buffer(string);
5206
  while (buffer.has_more()) {
5207
    uint16_t character = buffer.GetNext();
5208
    PrintF("%c", character);
5209
  }
5210
  return string;
5211
}
5212

    
5213

    
5214
static Object* Runtime_RemoveArrayHoles(Arguments args) {
5215
  ASSERT(args.length() == 1);
5216
  // Ignore the case if this is not a JSArray.
5217
  if (!args[0]->IsJSArray()) return args[0];
5218
  return JSArray::cast(args[0])->RemoveHoles();
5219
}
5220

    
5221

    
5222
// Move contents of argument 0 (an array) to argument 1 (an array)
5223
static Object* Runtime_MoveArrayContents(Arguments args) {
5224
  ASSERT(args.length() == 2);
5225
  CONVERT_CHECKED(JSArray, from, args[0]);
5226
  CONVERT_CHECKED(JSArray, to, args[1]);
5227
  to->SetContent(FixedArray::cast(from->elements()));
5228
  to->set_length(from->length());
5229
  from->SetContent(Heap::empty_fixed_array());
5230
  from->set_length(0);
5231
  return to;
5232
}
5233

    
5234

    
5235
// How many elements does this array have?
5236
static Object* Runtime_EstimateNumberOfElements(Arguments args) {
5237
  ASSERT(args.length() == 1);
5238
  CONVERT_CHECKED(JSArray, array, args[0]);
5239
  HeapObject* elements = array->elements();
5240
  if (elements->IsDictionary()) {
5241
    return Smi::FromInt(Dictionary::cast(elements)->NumberOfElements());
5242
  } else {
5243
    return array->length();
5244
  }
5245
}
5246

    
5247

    
5248
// Returns an array that tells you where in the [0, length) interval an array
5249
// might have elements.  Can either return keys or intervals.  Keys can have
5250
// gaps in (undefined).  Intervals can also span over some undefined keys.
5251
static Object* Runtime_GetArrayKeys(Arguments args) {
5252
  ASSERT(args.length() == 2);
5253
  HandleScope scope;
5254
  CONVERT_CHECKED(JSArray, raw_array, args[0]);
5255
  Handle<JSArray> array(raw_array);
5256
  CONVERT_NUMBER_CHECKED(uint32_t, length, Uint32, args[1]);
5257
  if (array->elements()->IsDictionary()) {
5258
    // Create an array and get all the keys into it, then remove all the
5259
    // keys that are not integers in the range 0 to length-1.
5260
    Handle<FixedArray> keys = GetKeysInFixedArrayFor(array);
5261
    int keys_length = keys->length();
5262
    for (int i = 0; i < keys_length; i++) {
5263
      Object* key = keys->get(i);
5264
      uint32_t index;
5265
      if (!Array::IndexFromObject(key, &index) || index >= length) {
5266
        // Zap invalid keys.
5267
        keys->set_undefined(i);
5268
      }
5269
    }
5270
    return *Factory::NewJSArrayWithElements(keys);
5271
  } else {
5272
    Handle<FixedArray> single_interval = Factory::NewFixedArray(2);
5273
    // -1 means start of array.
5274
    single_interval->set(0,
5275
                         Smi::FromInt(-1),
5276
                         SKIP_WRITE_BARRIER);
5277
    Handle<Object> length_object =
5278
        Factory::NewNumber(static_cast<double>(length));
5279
    single_interval->set(1, *length_object);
5280
    return *Factory::NewJSArrayWithElements(single_interval);
5281
  }
5282
}
5283

    
5284

    
5285
// DefineAccessor takes an optional final argument which is the
5286
// property attributes (eg, DONT_ENUM, DONT_DELETE).  IMPORTANT: due
5287
// to the way accessors are implemented, it is set for both the getter
5288
// and setter on the first call to DefineAccessor and ignored on
5289
// subsequent calls.
5290
static Object* Runtime_DefineAccessor(Arguments args) {
5291
  RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
5292
  // Compute attributes.
5293
  PropertyAttributes attributes = NONE;
5294
  if (args.length() == 5) {
5295
    CONVERT_CHECKED(Smi, attrs, args[4]);
5296
    int value = attrs->value();
5297
    // Only attribute bits should be set.
5298
    ASSERT((value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
5299
    attributes = static_cast<PropertyAttributes>(value);
5300
  }
5301

    
5302
  CONVERT_CHECKED(JSObject, obj, args[0]);
5303
  CONVERT_CHECKED(String, name, args[1]);
5304
  CONVERT_CHECKED(Smi, flag, args[2]);
5305
  CONVERT_CHECKED(JSFunction, fun, args[3]);
5306
  return obj->DefineAccessor(name, flag->value() == 0, fun, attributes);
5307
}
5308

    
5309

    
5310
static Object* Runtime_LookupAccessor(Arguments args) {
5311
  ASSERT(args.length() == 3);
5312
  CONVERT_CHECKED(JSObject, obj, args[0]);
5313
  CONVERT_CHECKED(String, name, args[1]);
5314
  CONVERT_CHECKED(Smi, flag, args[2]);
5315
  return obj->LookupAccessor(name, flag->value() == 0);
5316
}
5317

    
5318

    
5319
// Helper functions for wrapping and unwrapping stack frame ids.
5320
static Smi* WrapFrameId(StackFrame::Id id) {
5321
  ASSERT(IsAligned(OffsetFrom(id), 4));
5322
  return Smi::FromInt(id >> 2);
5323
}
5324

    
5325

    
5326
static StackFrame::Id UnwrapFrameId(Smi* wrapped) {
5327
  return static_cast<StackFrame::Id>(wrapped->value() << 2);
5328
}
5329

    
5330

    
5331
// Adds a JavaScript function as a debug event listener.
5332
// args[0]: debug event listener function to set or null or undefined for
5333
//          clearing the event listener function
5334
// args[1]: object supplied during callback
5335
static Object* Runtime_SetDebugEventListener(Arguments args) {
5336
  ASSERT(args.length() == 2);
5337
  RUNTIME_ASSERT(args[0]->IsJSFunction() ||
5338
                 args[0]->IsUndefined() ||
5339
                 args[0]->IsNull());
5340
  Handle<Object> callback = args.at<Object>(0);
5341
  Handle<Object> data = args.at<Object>(1);
5342
  Debugger::SetEventListener(callback, data);
5343

    
5344
  return Heap::undefined_value();
5345
}
5346

    
5347

    
5348
static Object* Runtime_Break(Arguments args) {
5349
  ASSERT(args.length() == 0);
5350
  StackGuard::DebugBreak();
5351
  return Heap::undefined_value();
5352
}
5353

    
5354

    
5355
// Find the length of the prototype chain that is to to handled as one. If a
5356
// prototype object is hidden it is to be viewed as part of the the object it
5357
// is prototype for.
5358
static int LocalPrototypeChainLength(JSObject* obj) {
5359
  int count = 1;
5360
  Object* proto = obj->GetPrototype();
5361
  while (proto->IsJSObject() &&
5362
         JSObject::cast(proto)->map()->is_hidden_prototype()) {
5363
    count++;
5364
    proto = JSObject::cast(proto)->GetPrototype();
5365
  }
5366
  return count;
5367
}
5368

    
5369

    
5370
static Object* DebugLookupResultValue(Object* receiver, LookupResult* result,
5371
                                      bool* caught_exception) {
5372
  Object* value;
5373
  switch (result->type()) {
5374
    case NORMAL: {
5375
      Dictionary* dict =
5376
          JSObject::cast(result->holder())->property_dictionary();
5377
      value = dict->ValueAt(result->GetDictionaryEntry());
5378
      if (value->IsTheHole()) {
5379
        return Heap::undefined_value();
5380
      }
5381
      return value;
5382
    }
5383
    case FIELD:
5384
      value =
5385
          JSObject::cast(
5386
              result->holder())->FastPropertyAt(result->GetFieldIndex());
5387
      if (value->IsTheHole()) {
5388
        return Heap::undefined_value();
5389
      }
5390
      return value;
5391
    case CONSTANT_FUNCTION:
5392
      return result->GetConstantFunction();
5393
    case CALLBACKS: {
5394
      Object* structure = result->GetCallbackObject();
5395
      if (structure->IsProxy()) {
5396
        AccessorDescriptor* callback =
5397
            reinterpret_cast<AccessorDescriptor*>(
5398
                Proxy::cast(structure)->proxy());
5399
        value = (callback->getter)(receiver, callback->data);
5400
        if (value->IsException()) {
5401
          value = Top::pending_exception();
5402
          Top::clear_pending_exception();
5403
          if (caught_exception != NULL) {
5404
            *caught_exception = true;
5405
          }
5406
        }
5407
        return value;
5408
      } else {
5409
        return Heap::undefined_value();
5410
      }
5411
    }
5412
    case INTERCEPTOR:
5413
    case MAP_TRANSITION:
5414
    case CONSTANT_TRANSITION:
5415
    case NULL_DESCRIPTOR:
5416
      return Heap::undefined_value();
5417
    default:
5418
      UNREACHABLE();
5419
  }
5420
  UNREACHABLE();
5421
  return Heap::undefined_value();
5422
}
5423

    
5424

    
5425
// Get debugger related details for an object property.
5426
// args[0]: object holding property
5427
// args[1]: name of the property
5428
//
5429
// The array returned contains the following information:
5430
// 0: Property value
5431
// 1: Property details
5432
// 2: Property value is exception
5433
// 3: Getter function if defined
5434
// 4: Setter function if defined
5435
// Items 2-4 are only filled if the property has either a getter or a setter
5436
// defined through __defineGetter__ and/or __defineSetter__.
5437
static Object* Runtime_DebugGetPropertyDetails(Arguments args) {
5438
  HandleScope scope;
5439

    
5440
  ASSERT(args.length() == 2);
5441

    
5442
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5443
  CONVERT_ARG_CHECKED(String, name, 1);
5444

    
5445
  // Skip the global proxy as it has no properties and always delegates to the
5446
  // real global object.
5447
  if (obj->IsJSGlobalProxy()) {
5448
    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5449
  }
5450

    
5451

    
5452
  // Check if the name is trivially convertible to an index and get the element
5453
  // if so.
5454
  uint32_t index;
5455
  if (name->AsArrayIndex(&index)) {
5456
    Handle<FixedArray> details = Factory::NewFixedArray(2);
5457
    details->set(0, Runtime::GetElementOrCharAt(obj, index));
5458
    details->set(1, PropertyDetails(NONE, NORMAL).AsSmi());
5459
    return *Factory::NewJSArrayWithElements(details);
5460
  }
5461

    
5462
  // Find the number of objects making up this.
5463
  int length = LocalPrototypeChainLength(*obj);
5464

    
5465
  // Try local lookup on each of the objects.
5466
  LookupResult result;
5467
  Handle<JSObject> jsproto = obj;
5468
  for (int i = 0; i < length; i++) {
5469
    jsproto->LocalLookup(*name, &result);
5470
    if (result.IsProperty()) {
5471
      break;
5472
    }
5473
    if (i < length - 1) {
5474
      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5475
    }
5476
  }
5477

    
5478
  if (result.IsProperty()) {
5479
    bool caught_exception = false;
5480
    Object* value = DebugLookupResultValue(*obj, &result,
5481
                                           &caught_exception);
5482
    if (value->IsFailure()) return value;
5483
    Handle<Object> value_handle(value);
5484
    // If the callback object is a fixed array then it contains JavaScript
5485
    // getter and/or setter.
5486
    bool hasJavaScriptAccessors = result.type() == CALLBACKS &&
5487
                                  result.GetCallbackObject()->IsFixedArray();
5488
    Handle<FixedArray> details =
5489
        Factory::NewFixedArray(hasJavaScriptAccessors ? 5 : 2);
5490
    details->set(0, *value_handle);
5491
    details->set(1, result.GetPropertyDetails().AsSmi());
5492
    if (hasJavaScriptAccessors) {
5493
      details->set(2,
5494
                   caught_exception ? Heap::true_value() : Heap::false_value());
5495
      details->set(3, FixedArray::cast(result.GetCallbackObject())->get(0));
5496
      details->set(4, FixedArray::cast(result.GetCallbackObject())->get(1));
5497
    }
5498

    
5499
    return *Factory::NewJSArrayWithElements(details);
5500
  }
5501
  return Heap::undefined_value();
5502
}
5503

    
5504

    
5505
static Object* Runtime_DebugGetProperty(Arguments args) {
5506
  HandleScope scope;
5507

    
5508
  ASSERT(args.length() == 2);
5509

    
5510
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5511
  CONVERT_ARG_CHECKED(String, name, 1);
5512

    
5513
  LookupResult result;
5514
  obj->Lookup(*name, &result);
5515
  if (result.IsProperty()) {
5516
    return DebugLookupResultValue(*obj, &result, NULL);
5517
  }
5518
  return Heap::undefined_value();
5519
}
5520

    
5521

    
5522
// Return the names of the local named properties.
5523
// args[0]: object
5524
static Object* Runtime_DebugLocalPropertyNames(Arguments args) {
5525
  HandleScope scope;
5526
  ASSERT(args.length() == 1);
5527
  if (!args[0]->IsJSObject()) {
5528
    return Heap::undefined_value();
5529
  }
5530
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5531

    
5532
  // Skip the global proxy as it has no properties and always delegates to the
5533
  // real global object.
5534
  if (obj->IsJSGlobalProxy()) {
5535
    obj = Handle<JSObject>(JSObject::cast(obj->GetPrototype()));
5536
  }
5537

    
5538
  // Find the number of objects making up this.
5539
  int length = LocalPrototypeChainLength(*obj);
5540

    
5541
  // Find the number of local properties for each of the objects.
5542
  int* local_property_count = NewArray<int>(length);
5543
  int total_property_count = 0;
5544
  Handle<JSObject> jsproto = obj;
5545
  for (int i = 0; i < length; i++) {
5546
    int n;
5547
    n = jsproto->NumberOfLocalProperties(static_cast<PropertyAttributes>(NONE));
5548
    local_property_count[i] = n;
5549
    total_property_count += n;
5550
    if (i < length - 1) {
5551
      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5552
    }
5553
  }
5554

    
5555
  // Allocate an array with storage for all the property names.
5556
  Handle<FixedArray> names = Factory::NewFixedArray(total_property_count);
5557

    
5558
  // Get the property names.
5559
  jsproto = obj;
5560
  for (int i = 0; i < length; i++) {
5561
    jsproto->GetLocalPropertyNames(*names,
5562
                                   i == 0 ? 0 : local_property_count[i - 1]);
5563
    if (i < length - 1) {
5564
      jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype()));
5565
    }
5566
  }
5567

    
5568
  DeleteArray(local_property_count);
5569
  return *Factory::NewJSArrayWithElements(names);
5570
}
5571

    
5572

    
5573
// Return the names of the local indexed properties.
5574
// args[0]: object
5575
static Object* Runtime_DebugLocalElementNames(Arguments args) {
5576
  HandleScope scope;
5577
  ASSERT(args.length() == 1);
5578
  if (!args[0]->IsJSObject()) {
5579
    return Heap::undefined_value();
5580
  }
5581
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5582

    
5583
  int n = obj->NumberOfLocalElements(static_cast<PropertyAttributes>(NONE));
5584
  Handle<FixedArray> names = Factory::NewFixedArray(n);
5585
  obj->GetLocalElementKeys(*names, static_cast<PropertyAttributes>(NONE));
5586
  return *Factory::NewJSArrayWithElements(names);
5587
}
5588

    
5589

    
5590
// Return the property type calculated from the property details.
5591
// args[0]: smi with property details.
5592
static Object* Runtime_DebugPropertyTypeFromDetails(Arguments args) {
5593
  ASSERT(args.length() == 1);
5594
  CONVERT_CHECKED(Smi, details, args[0]);
5595
  PropertyType type = PropertyDetails(details).type();
5596
  return Smi::FromInt(static_cast<int>(type));
5597
}
5598

    
5599

    
5600
// Return the property attribute calculated from the property details.
5601
// args[0]: smi with property details.
5602
static Object* Runtime_DebugPropertyAttributesFromDetails(Arguments args) {
5603
  ASSERT(args.length() == 1);
5604
  CONVERT_CHECKED(Smi, details, args[0]);
5605
  PropertyAttributes attributes = PropertyDetails(details).attributes();
5606
  return Smi::FromInt(static_cast<int>(attributes));
5607
}
5608

    
5609

    
5610
// Return the property insertion index calculated from the property details.
5611
// args[0]: smi with property details.
5612
static Object* Runtime_DebugPropertyIndexFromDetails(Arguments args) {
5613
  ASSERT(args.length() == 1);
5614
  CONVERT_CHECKED(Smi, details, args[0]);
5615
  int index = PropertyDetails(details).index();
5616
  return Smi::FromInt(index);
5617
}
5618

    
5619

    
5620
// Return information on whether an object has a named or indexed interceptor.
5621
// args[0]: object
5622
static Object* Runtime_DebugInterceptorInfo(Arguments args) {
5623
  HandleScope scope;
5624
  ASSERT(args.length() == 1);
5625
  if (!args[0]->IsJSObject()) {
5626
    return Smi::FromInt(0);
5627
  }
5628
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5629

    
5630
  int result = 0;
5631
  if (obj->HasNamedInterceptor()) result |= 2;
5632
  if (obj->HasIndexedInterceptor()) result |= 1;
5633

    
5634
  return Smi::FromInt(result);
5635
}
5636

    
5637

    
5638
// Return property names from named interceptor.
5639
// args[0]: object
5640
static Object* Runtime_DebugNamedInterceptorPropertyNames(Arguments args) {
5641
  HandleScope scope;
5642
  ASSERT(args.length() == 1);
5643
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5644

    
5645
  if (obj->HasNamedInterceptor()) {
5646
    v8::Handle<v8::Array> result = GetKeysForNamedInterceptor(obj, obj);
5647
    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5648
  }
5649
  return Heap::undefined_value();
5650
}
5651

    
5652

    
5653
// Return element names from indexed interceptor.
5654
// args[0]: object
5655
static Object* Runtime_DebugIndexedInterceptorElementNames(Arguments args) {
5656
  HandleScope scope;
5657
  ASSERT(args.length() == 1);
5658
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5659

    
5660
  if (obj->HasIndexedInterceptor()) {
5661
    v8::Handle<v8::Array> result = GetKeysForIndexedInterceptor(obj, obj);
5662
    if (!result.IsEmpty()) return *v8::Utils::OpenHandle(*result);
5663
  }
5664
  return Heap::undefined_value();
5665
}
5666

    
5667

    
5668
// Return property value from named interceptor.
5669
// args[0]: object
5670
// args[1]: property name
5671
static Object* Runtime_DebugNamedInterceptorPropertyValue(Arguments args) {
5672
  HandleScope scope;
5673
  ASSERT(args.length() == 2);
5674
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5675
  RUNTIME_ASSERT(obj->HasNamedInterceptor());
5676
  CONVERT_ARG_CHECKED(String, name, 1);
5677

    
5678
  PropertyAttributes attributes;
5679
  return obj->GetPropertyWithInterceptor(*obj, *name, &attributes);
5680
}
5681

    
5682

    
5683
// Return element value from indexed interceptor.
5684
// args[0]: object
5685
// args[1]: index
5686
static Object* Runtime_DebugIndexedInterceptorElementValue(Arguments args) {
5687
  HandleScope scope;
5688
  ASSERT(args.length() == 2);
5689
  CONVERT_ARG_CHECKED(JSObject, obj, 0);
5690
  RUNTIME_ASSERT(obj->HasIndexedInterceptor());
5691
  CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]);
5692

    
5693
  return obj->GetElementWithInterceptor(*obj, index);
5694
}
5695

    
5696

    
5697
static Object* Runtime_CheckExecutionState(Arguments args) {
5698
  ASSERT(args.length() >= 1);
5699
  CONVERT_NUMBER_CHECKED(int, break_id, Int32, args[0]);
5700
  // Check that the break id is valid.
5701
  if (Debug::break_id() == 0 || break_id != Debug::break_id()) {
5702
    return Top::Throw(Heap::illegal_execution_state_symbol());
5703
  }
5704

    
5705
  return Heap::true_value();
5706
}
5707

    
5708

    
5709
static Object* Runtime_GetFrameCount(Arguments args) {
5710
  HandleScope scope;
5711
  ASSERT(args.length() == 1);
5712

    
5713
  // Check arguments.
5714
  Object* result = Runtime_CheckExecutionState(args);
5715
  if (result->IsFailure()) return result;
5716

    
5717
  // Count all frames which are relevant to debugging stack trace.
5718
  int n = 0;
5719
  StackFrame::Id id = Debug::break_frame_id();
5720
  if (id == StackFrame::NO_ID) {
5721
    // If there is no JavaScript stack frame count is 0.
5722
    return Smi::FromInt(0);
5723
  }
5724
  for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) n++;
5725
  return Smi::FromInt(n);
5726
}
5727

    
5728

    
5729
static const int kFrameDetailsFrameIdIndex = 0;
5730
static const int kFrameDetailsReceiverIndex = 1;
5731
static const int kFrameDetailsFunctionIndex = 2;
5732
static const int kFrameDetailsArgumentCountIndex = 3;
5733
static const int kFrameDetailsLocalCountIndex = 4;
5734
static const int kFrameDetailsSourcePositionIndex = 5;
5735
static const int kFrameDetailsConstructCallIndex = 6;
5736
static const int kFrameDetailsDebuggerFrameIndex = 7;
5737
static const int kFrameDetailsFirstDynamicIndex = 8;
5738

    
5739
// Return an array with frame details
5740
// args[0]: number: break id
5741
// args[1]: number: frame index
5742
//
5743
// The array returned contains the following information:
5744
// 0: Frame id
5745
// 1: Receiver
5746
// 2: Function
5747
// 3: Argument count
5748
// 4: Local count
5749
// 5: Source position
5750
// 6: Constructor call
5751
// 7: Debugger frame
5752
// Arguments name, value
5753
// Locals name, value
5754
static Object* Runtime_GetFrameDetails(Arguments args) {
5755
  HandleScope scope;
5756
  ASSERT(args.length() == 2);
5757

    
5758
  // Check arguments.
5759
  Object* check = Runtime_CheckExecutionState(args);
5760
  if (check->IsFailure()) return check;
5761
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
5762

    
5763
  // Find the relevant frame with the requested index.
5764
  StackFrame::Id id = Debug::break_frame_id();
5765
  if (id == StackFrame::NO_ID) {
5766
    // If there are no JavaScript stack frames return undefined.
5767
    return Heap::undefined_value();
5768
  }
5769
  int count = 0;
5770
  JavaScriptFrameIterator it(id);
5771
  for (; !it.done(); it.Advance()) {
5772
    if (count == index) break;
5773
    count++;
5774
  }
5775
  if (it.done()) return Heap::undefined_value();
5776

    
5777
  // Traverse the saved contexts chain to find the active context for the
5778
  // selected frame.
5779
  SaveContext* save = Top::save_context();
5780
  while (save != NULL && !save->below(it.frame())) {
5781
    save = save->prev();
5782
  }
5783
  ASSERT(save != NULL);
5784

    
5785
  // Get the frame id.
5786
  Handle<Object> frame_id(WrapFrameId(it.frame()->id()));
5787

    
5788
  // Find source position.
5789
  int position = it.frame()->code()->SourcePosition(it.frame()->pc());
5790

    
5791
  // Check for constructor frame.
5792
  bool constructor = it.frame()->IsConstructor();
5793

    
5794
  // Get code and read scope info from it for local variable information.
5795
  Handle<Code> code(it.frame()->code());
5796
  ScopeInfo<> info(*code);
5797

    
5798
  // Get the context.
5799
  Handle<Context> context(Context::cast(it.frame()->context()));
5800

    
5801
  // Get the locals names and values into a temporary array.
5802
  //
5803
  // TODO(1240907): Hide compiler-introduced stack variables
5804
  // (e.g. .result)?  For users of the debugger, they will probably be
5805
  // confusing.
5806
  Handle<FixedArray> locals = Factory::NewFixedArray(info.NumberOfLocals() * 2);
5807
  for (int i = 0; i < info.NumberOfLocals(); i++) {
5808
    // Name of the local.
5809
    locals->set(i * 2, *info.LocalName(i));
5810

    
5811
    // Fetch the value of the local - either from the stack or from a
5812
    // heap-allocated context.
5813
    if (i < info.number_of_stack_slots()) {
5814
      locals->set(i * 2 + 1, it.frame()->GetExpression(i));
5815
    } else {
5816
      Handle<String> name = info.LocalName(i);
5817
      // Traverse the context chain to the function context as all local
5818
      // variables stored in the context will be on the function context.
5819
      while (!context->is_function_context()) {
5820
        context = Handle<Context>(context->previous());
5821
      }
5822
      ASSERT(context->is_function_context());
5823
      locals->set(i * 2 + 1,
5824
                  context->get(ScopeInfo<>::ContextSlotIndex(*code, *name,
5825
                                                             NULL)));
5826
    }
5827
  }
5828

    
5829
  // Now advance to the arguments adapter frame (if any). If contains all
5830
  // the provided parameters and
5831

    
5832
  // Now advance to the arguments adapter frame (if any). It contains all
5833
  // the provided parameters whereas the function frame always have the number
5834
  // of arguments matching the functions parameters. The rest of the
5835
  // information (except for what is collected above) is the same.
5836
  it.AdvanceToArgumentsFrame();
5837

    
5838
  // Find the number of arguments to fill. At least fill the number of
5839
  // parameters for the function and fill more if more parameters are provided.
5840
  int argument_count = info.number_of_parameters();
5841
  if (argument_count < it.frame()->GetProvidedParametersCount()) {
5842
    argument_count = it.frame()->GetProvidedParametersCount();
5843
  }
5844

    
5845
  // Calculate the size of the result.
5846
  int details_size = kFrameDetailsFirstDynamicIndex +
5847
                     2 * (argument_count + info.NumberOfLocals());
5848
  Handle<FixedArray> details = Factory::NewFixedArray(details_size);
5849

    
5850
  // Add the frame id.
5851
  details->set(kFrameDetailsFrameIdIndex, *frame_id);
5852

    
5853
  // Add the function (same as in function frame).
5854
  details->set(kFrameDetailsFunctionIndex, it.frame()->function());
5855

    
5856
  // Add the arguments count.
5857
  details->set(kFrameDetailsArgumentCountIndex, Smi::FromInt(argument_count));
5858

    
5859
  // Add the locals count
5860
  details->set(kFrameDetailsLocalCountIndex,
5861
               Smi::FromInt(info.NumberOfLocals()));
5862

    
5863
  // Add the source position.
5864
  if (position != RelocInfo::kNoPosition) {
5865
    details->set(kFrameDetailsSourcePositionIndex, Smi::FromInt(position));
5866
  } else {
5867
    details->set(kFrameDetailsSourcePositionIndex, Heap::undefined_value());
5868
  }
5869

    
5870
  // Add the constructor information.
5871
  details->set(kFrameDetailsConstructCallIndex, Heap::ToBoolean(constructor));
5872

    
5873
  // Add information on whether this frame is invoked in the debugger context.
5874
  details->set(kFrameDetailsDebuggerFrameIndex,
5875
               Heap::ToBoolean(*save->context() == *Debug::debug_context()));
5876

    
5877
  // Fill the dynamic part.
5878
  int details_index = kFrameDetailsFirstDynamicIndex;
5879

    
5880
  // Add arguments name and value.
5881
  for (int i = 0; i < argument_count; i++) {
5882
    // Name of the argument.
5883
    if (i < info.number_of_parameters()) {
5884
      details->set(details_index++, *info.parameter_name(i));
5885
    } else {
5886
      details->set(details_index++, Heap::undefined_value());
5887
    }
5888

    
5889
    // Parameter value.
5890
    if (i < it.frame()->GetProvidedParametersCount()) {
5891
      details->set(details_index++, it.frame()->GetParameter(i));
5892
    } else {
5893
      details->set(details_index++, Heap::undefined_value());
5894
    }
5895
  }
5896

    
5897
  // Add locals name and value from the temporary copy from the function frame.
5898
  for (int i = 0; i < info.NumberOfLocals() * 2; i++) {
5899
    details->set(details_index++, locals->get(i));
5900
  }
5901

    
5902
  // Add the receiver (same as in function frame).
5903
  // THIS MUST BE DONE LAST SINCE WE MIGHT ADVANCE
5904
  // THE FRAME ITERATOR TO WRAP THE RECEIVER.
5905
  Handle<Object> receiver(it.frame()->receiver());
5906
  if (!receiver->IsJSObject()) {
5907
    // If the receiver is NOT a JSObject we have hit an optimization
5908
    // where a value object is not converted into a wrapped JS objects.
5909
    // To hide this optimization from the debugger, we wrap the receiver
5910
    // by creating correct wrapper object based on the calling frame's
5911
    // global context.
5912
    it.Advance();
5913
    Handle<Context> calling_frames_global_context(
5914
        Context::cast(Context::cast(it.frame()->context())->global_context()));
5915
    receiver = Factory::ToObject(receiver, calling_frames_global_context);
5916
  }
5917
  details->set(kFrameDetailsReceiverIndex, *receiver);
5918

    
5919
  ASSERT_EQ(details_size, details_index);
5920
  return *Factory::NewJSArrayWithElements(details);
5921
}
5922

    
5923

    
5924
static Object* Runtime_GetCFrames(Arguments args) {
5925
  HandleScope scope;
5926
  ASSERT(args.length() == 1);
5927
  Object* result = Runtime_CheckExecutionState(args);
5928
  if (result->IsFailure()) return result;
5929

    
5930
  static const int kMaxCFramesSize = 200;
5931
  OS::StackFrame frames[kMaxCFramesSize];
5932
  int frames_count = OS::StackWalk(frames, kMaxCFramesSize);
5933
  if (frames_count == OS::kStackWalkError) {
5934
    return Heap::undefined_value();
5935
  }
5936

    
5937
  Handle<String> address_str = Factory::LookupAsciiSymbol("address");
5938
  Handle<String> text_str = Factory::LookupAsciiSymbol("text");
5939
  Handle<FixedArray> frames_array = Factory::NewFixedArray(frames_count);
5940
  for (int i = 0; i < frames_count; i++) {
5941
    Handle<JSObject> frame_value = Factory::NewJSObject(Top::object_function());
5942
    frame_value->SetProperty(
5943
        *address_str,
5944
        *Factory::NewNumberFromInt(reinterpret_cast<int>(frames[i].address)),
5945
        NONE);
5946

    
5947
    // Get the stack walk text for this frame.
5948
    Handle<String> frame_text;
5949
    if (strlen(frames[i].text) > 0) {
5950
      Vector<const char> str(frames[i].text, strlen(frames[i].text));
5951
      frame_text = Factory::NewStringFromAscii(str);
5952
    }
5953

    
5954
    if (!frame_text.is_null()) {
5955
      frame_value->SetProperty(*text_str, *frame_text, NONE);
5956
    }
5957

    
5958
    frames_array->set(i, *frame_value);
5959
  }
5960
  return *Factory::NewJSArrayWithElements(frames_array);
5961
}
5962

    
5963

    
5964
static Object* Runtime_GetThreadCount(Arguments args) {
5965
  HandleScope scope;
5966
  ASSERT(args.length() == 1);
5967

    
5968
  // Check arguments.
5969
  Object* result = Runtime_CheckExecutionState(args);
5970
  if (result->IsFailure()) return result;
5971

    
5972
  // Count all archived V8 threads.
5973
  int n = 0;
5974
  for (ThreadState* thread = ThreadState::FirstInUse();
5975
       thread != NULL;
5976
       thread = thread->Next()) {
5977
    n++;
5978
  }
5979

    
5980
  // Total number of threads is current thread and archived threads.
5981
  return Smi::FromInt(n + 1);
5982
}
5983

    
5984

    
5985
static const int kThreadDetailsCurrentThreadIndex = 0;
5986
static const int kThreadDetailsThreadIdIndex = 1;
5987
static const int kThreadDetailsSize = 2;
5988

    
5989
// Return an array with thread details
5990
// args[0]: number: break id
5991
// args[1]: number: thread index
5992
//
5993
// The array returned contains the following information:
5994
// 0: Is current thread?
5995
// 1: Thread id
5996
static Object* Runtime_GetThreadDetails(Arguments args) {
5997
  HandleScope scope;
5998
  ASSERT(args.length() == 2);
5999

    
6000
  // Check arguments.
6001
  Object* check = Runtime_CheckExecutionState(args);
6002
  if (check->IsFailure()) return check;
6003
  CONVERT_NUMBER_CHECKED(int, index, Int32, args[1]);
6004

    
6005
  // Allocate array for result.
6006
  Handle<FixedArray> details = Factory::NewFixedArray(kThreadDetailsSize);
6007

    
6008
  // Thread index 0 is current thread.
6009
  if (index == 0) {
6010
    // Fill the details.
6011
    details->set(kThreadDetailsCurrentThreadIndex, Heap::true_value());
6012
    details->set(kThreadDetailsThreadIdIndex,
6013
                 Smi::FromInt(ThreadManager::CurrentId()));
6014
  } else {
6015
    // Find the thread with the requested index.
6016
    int n = 1;
6017
    ThreadState* thread = ThreadState::FirstInUse();
6018
    while (index != n && thread != NULL) {
6019
      thread = thread->Next();
6020
      n++;
6021
    }
6022
    if (thread == NULL) {
6023
      return Heap::undefined_value();
6024
    }
6025

    
6026
    // Fill the details.
6027
    details->set(kThreadDetailsCurrentThreadIndex, Heap::false_value());
6028
    details->set(kThreadDetailsThreadIdIndex, Smi::FromInt(thread->id()));
6029
  }
6030

    
6031
  // Convert to JS array and return.
6032
  return *Factory::NewJSArrayWithElements(details);
6033
}
6034

    
6035

    
6036
static Object* Runtime_GetBreakLocations(Arguments args) {
6037
  HandleScope scope;
6038
  ASSERT(args.length() == 1);
6039

    
6040
  CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
6041
  Handle<SharedFunctionInfo> shared(raw_fun->shared());
6042
  // Find the number of break points
6043
  Handle<Object> break_locations = Debug::GetSourceBreakLocations(shared);
6044
  if (break_locations->IsUndefined()) return Heap::undefined_value();
6045
  // Return array as JS array
6046
  return *Factory::NewJSArrayWithElements(
6047
      Handle<FixedArray>::cast(break_locations));
6048
}
6049

    
6050

    
6051
// Set a break point in a function
6052
// args[0]: function
6053
// args[1]: number: break source position (within the function source)
6054
// args[2]: number: break point object
6055
static Object* Runtime_SetFunctionBreakPoint(Arguments args) {
6056
  HandleScope scope;
6057
  ASSERT(args.length() == 3);
6058
  CONVERT_ARG_CHECKED(JSFunction, raw_fun, 0);
6059
  Handle<SharedFunctionInfo> shared(raw_fun->shared());
6060
  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
6061
  RUNTIME_ASSERT(source_position >= 0);
6062
  Handle<Object> break_point_object_arg = args.at<Object>(2);
6063

    
6064
  // Set break point.
6065
  Debug::SetBreakPoint(shared, source_position, break_point_object_arg);
6066

    
6067
  return Heap::undefined_value();
6068
}
6069

    
6070

    
6071
Object* Runtime::FindSharedFunctionInfoInScript(Handle<Script> script,
6072
                                                int position) {
6073
  // Iterate the heap looking for SharedFunctionInfo generated from the
6074
  // script. The inner most SharedFunctionInfo containing the source position
6075
  // for the requested break point is found.
6076
  // NOTE: This might reqire several heap iterations. If the SharedFunctionInfo
6077
  // which is found is not compiled it is compiled and the heap is iterated
6078
  // again as the compilation might create inner functions from the newly
6079
  // compiled function and the actual requested break point might be in one of
6080
  // these functions.
6081
  bool done = false;
6082
  // The current candidate for the source position:
6083
  int target_start_position = RelocInfo::kNoPosition;
6084
  Handle<SharedFunctionInfo> target;
6085
  // The current candidate for the last function in script:
6086
  Handle<SharedFunctionInfo> last;
6087
  while (!done) {
6088
    HeapIterator iterator;
6089
    while (iterator.has_next()) {
6090
      HeapObject* obj = iterator.next();
6091
      ASSERT(obj != NULL);
6092
      if (obj->IsSharedFunctionInfo()) {
6093
        Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
6094
        if (shared->script() == *script) {
6095
          // If the SharedFunctionInfo found has the requested script data and
6096
          // contains the source position it is a candidate.
6097
          int start_position = shared->function_token_position();
6098
          if (start_position == RelocInfo::kNoPosition) {
6099
            start_position = shared->start_position();
6100
          }
6101
          if (start_position <= position &&
6102
              position <= shared->end_position()) {
6103
            // If there is no candidate or this function is within the current
6104
            // candidate this is the new candidate.
6105
            if (target.is_null()) {
6106
              target_start_position = start_position;
6107
              target = shared;
6108
            } else {
6109
              if (target_start_position < start_position &&
6110
                  shared->end_position() < target->end_position()) {
6111
                target_start_position = start_position;
6112
                target = shared;
6113
              }
6114
            }
6115
          }
6116

    
6117
          // Keep track of the last function in the script.
6118
          if (last.is_null() ||
6119
              shared->end_position() > last->start_position()) {
6120
            last = shared;
6121
          }
6122
        }
6123
      }
6124
    }
6125

    
6126
    // Make sure some candidate is selected.
6127
    if (target.is_null()) {
6128
      if (!last.is_null()) {
6129
        // Position after the last function - use last.
6130
        target = last;
6131
      } else {
6132
        // Unable to find function - possibly script without any function.
6133
        return Heap::undefined_value();
6134
      }
6135
    }
6136

    
6137
    // If the candidate found is compiled we are done. NOTE: when lazy
6138
    // compilation of inner functions is introduced some additional checking
6139
    // needs to be done here to compile inner functions.
6140
    done = target->is_compiled();
6141
    if (!done) {
6142
      // If the candidate is not compiled compile it to reveal any inner
6143
      // functions which might contain the requested source position.
6144
      CompileLazyShared(target, KEEP_EXCEPTION, 0);
6145
    }
6146
  }
6147

    
6148
  return *target;
6149
}
6150

    
6151

    
6152
// Change the state of a break point in a script. NOTE: Regarding performance
6153
// see the NOTE for GetScriptFromScriptData.
6154
// args[0]: script to set break point in
6155
// args[1]: number: break source position (within the script source)
6156
// args[2]: number: break point object
6157
static Object* Runtime_SetScriptBreakPoint(Arguments args) {
6158
  HandleScope scope;
6159
  ASSERT(args.length() == 3);
6160
  CONVERT_ARG_CHECKED(JSValue, wrapper, 0);
6161
  CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
6162
  RUNTIME_ASSERT(source_position >= 0);
6163
  Handle<Object> break_point_object_arg = args.at<Object>(2);
6164

    
6165
  // Get the script from the script wrapper.
6166
  RUNTIME_ASSERT(wrapper->value()->IsScript());
6167
  Handle<Script> script(Script::cast(wrapper->value()));
6168

    
6169
  Object* result = Runtime::FindSharedFunctionInfoInScript(
6170
      script, source_position);
6171
  if (!result->IsUndefined()) {
6172
    Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
6173
    // Find position within function. The script position might be before the
6174
    // source position of the first function.
6175
    int position;
6176
    if (shared->start_position() > source_position) {
6177
      position = 0;
6178
    } else {
6179
      position = source_position - shared->start_position();
6180
    }
6181
    Debug::SetBreakPoint(shared, position, break_point_object_arg);
6182
  }
6183
  return  Heap::undefined_value();
6184
}
6185

    
6186

    
6187
// Clear a break point
6188
// args[0]: number: break point object
6189
static Object* Runtime_ClearBreakPoint(Arguments args) {
6190
  HandleScope scope;
6191
  ASSERT(args.length() == 1);
6192
  Handle<Object> break_point_object_arg = args.at<Object>(0);
6193

    
6194
  // Clear break point.
6195
  Debug::ClearBreakPoint(break_point_object_arg);
6196

    
6197
  return Heap::undefined_value();
6198
}
6199

    
6200

    
6201
// Change the state of break on exceptions
6202
// args[0]: boolean indicating uncaught exceptions
6203
// args[1]: boolean indicating on/off
6204
static Object* Runtime_ChangeBreakOnException(Arguments args) {
6205
  HandleScope scope;
6206
  ASSERT(args.length() == 2);
6207
  ASSERT(args[0]->IsNumber());
6208
  ASSERT(args[1]->IsBoolean());
6209

    
6210
  // Update break point state
6211
  ExceptionBreakType type =
6212
      static_cast<ExceptionBreakType>(NumberToUint32(args[0]));
6213
  bool enable = args[1]->ToBoolean()->IsTrue();
6214
  Debug::ChangeBreakOnException(type, enable);
6215
  return Heap::undefined_value();
6216
}
6217

    
6218

    
6219
// Prepare for stepping
6220
// args[0]: break id for checking execution state
6221
// args[1]: step action from the enumeration StepAction
6222
// args[2]: number of times to perform the step
6223
static Object* Runtime_PrepareStep(Arguments args) {
6224
  HandleScope scope;
6225
  ASSERT(args.length() == 3);
6226
  // Check arguments.
6227
  Object* check = Runtime_CheckExecutionState(args);
6228
  if (check->IsFailure()) return check;
6229
  if (!args[1]->IsNumber() || !args[2]->IsNumber()) {
6230
    return Top::Throw(Heap::illegal_argument_symbol());
6231
  }
6232

    
6233
  // Get the step action and check validity.
6234
  StepAction step_action = static_cast<StepAction>(NumberToInt32(args[1]));
6235
  if (step_action != StepIn &&
6236
      step_action != StepNext &&
6237
      step_action != StepOut &&
6238
      step_action != StepInMin &&
6239
      step_action != StepMin) {
6240
    return Top::Throw(Heap::illegal_argument_symbol());
6241
  }
6242

    
6243
  // Get the number of steps.
6244
  int step_count = NumberToInt32(args[2]);
6245
  if (step_count < 1) {
6246
    return Top::Throw(Heap::illegal_argument_symbol());
6247
  }
6248

    
6249
  // Prepare step.
6250
  Debug::PrepareStep(static_cast<StepAction>(step_action), step_count);
6251
  return Heap::undefined_value();
6252
}
6253

    
6254

    
6255
// Clear all stepping set by PrepareStep.
6256
static Object* Runtime_ClearStepping(Arguments args) {
6257
  HandleScope scope;
6258
  ASSERT(args.length() == 0);
6259
  Debug::ClearStepping();
6260
  return Heap::undefined_value();
6261
}
6262

    
6263

    
6264
// Creates a copy of the with context chain. The copy of the context chain is
6265
// is linked to the function context supplied.
6266
static Handle<Context> CopyWithContextChain(Handle<Context> context_chain,
6267
                                            Handle<Context> function_context) {
6268
  // At the bottom of the chain. Return the function context to link to.
6269
  if (context_chain->is_function_context()) {
6270
    return function_context;
6271
  }
6272

    
6273
  // Recursively copy the with contexts.
6274
  Handle<Context> previous(context_chain->previous());
6275
  Handle<JSObject> extension(JSObject::cast(context_chain->extension()));
6276
  return Factory::NewWithContext(
6277
      CopyWithContextChain(function_context, previous),
6278
      extension,
6279
      context_chain->IsCatchContext());
6280
}
6281

    
6282

    
6283
// Helper function to find or create the arguments object for
6284
// Runtime_DebugEvaluate.
6285
static Handle<Object> GetArgumentsObject(JavaScriptFrame* frame,
6286
                                         Handle<JSFunction> function,
6287
                                         Handle<Code> code,
6288
                                         const ScopeInfo<>* sinfo,
6289
                                         Handle<Context> function_context) {
6290
  // Try to find the value of 'arguments' to pass as parameter. If it is not
6291
  // found (that is the debugged function does not reference 'arguments' and
6292
  // does not support eval) then create an 'arguments' object.
6293
  int index;
6294
  if (sinfo->number_of_stack_slots() > 0) {
6295
    index = ScopeInfo<>::StackSlotIndex(*code, Heap::arguments_symbol());
6296
    if (index != -1) {
6297
      return Handle<Object>(frame->GetExpression(index));
6298
    }
6299
  }
6300

    
6301
  if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) {
6302
    index = ScopeInfo<>::ContextSlotIndex(*code, Heap::arguments_symbol(),
6303
                                          NULL);
6304
    if (index != -1) {
6305
      return Handle<Object>(function_context->get(index));
6306
    }
6307
  }
6308

    
6309
  const int length = frame->GetProvidedParametersCount();
6310
  Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length);
6311
  Handle<FixedArray> array = Factory::NewFixedArray(length);
6312
  WriteBarrierMode mode = array->GetWriteBarrierMode();
6313
  for (int i = 0; i < length; i++) {
6314
    array->set(i, frame->GetParameter(i), mode);
6315
  }
6316
  arguments->set_elements(*array);
6317
  return arguments;
6318
}
6319

    
6320

    
6321
// Evaluate a piece of JavaScript in the context of a stack frame for
6322
// debugging. This is accomplished by creating a new context which in its
6323
// extension part has all the parameters and locals of the function on the
6324
// stack frame. A function which calls eval with the code to evaluate is then
6325
// compiled in this context and called in this context. As this context
6326
// replaces the context of the function on the stack frame a new (empty)
6327
// function is created as well to be used as the closure for the context.
6328
// This function and the context acts as replacements for the function on the
6329
// stack frame presenting the same view of the values of parameters and
6330
// local variables as if the piece of JavaScript was evaluated at the point
6331
// where the function on the stack frame is currently stopped.
6332
static Object* Runtime_DebugEvaluate(Arguments args) {
6333
  HandleScope scope;
6334

    
6335
  // Check the execution state and decode arguments frame and source to be
6336
  // evaluated.
6337
  ASSERT(args.length() == 4);
6338
  Object* check_result = Runtime_CheckExecutionState(args);
6339
  if (check_result->IsFailure()) return check_result;
6340
  CONVERT_CHECKED(Smi, wrapped_id, args[1]);
6341
  CONVERT_ARG_CHECKED(String, source, 2);
6342
  CONVERT_BOOLEAN_CHECKED(disable_break, args[3]);
6343

    
6344
  // Handle the processing of break.
6345
  DisableBreak disable_break_save(disable_break);
6346

    
6347
  // Get the frame where the debugging is performed.
6348
  StackFrame::Id id = UnwrapFrameId(wrapped_id);
6349
  JavaScriptFrameIterator it(id);
6350
  JavaScriptFrame* frame = it.frame();
6351
  Handle<JSFunction> function(JSFunction::cast(frame->function()));
6352
  Handle<Code> code(function->code());
6353
  ScopeInfo<> sinfo(*code);
6354

    
6355
  // Traverse the saved contexts chain to find the active context for the
6356
  // selected frame.
6357
  SaveContext* save = Top::save_context();
6358
  while (save != NULL && !save->below(frame)) {
6359
    save = save->prev();
6360
  }
6361
  ASSERT(save != NULL);
6362
  SaveContext savex;
6363
  Top::set_context(*(save->context()));
6364

    
6365
  // Create the (empty) function replacing the function on the stack frame for
6366
  // the purpose of evaluating in the context created below. It is important
6367
  // that this function does not describe any parameters and local variables
6368
  // in the context. If it does then this will cause problems with the lookup
6369
  // in Context::Lookup, where context slots for parameters and local variables
6370
  // are looked at before the extension object.
6371
  Handle<JSFunction> go_between =
6372
      Factory::NewFunction(Factory::empty_string(), Factory::undefined_value());
6373
  go_between->set_context(function->context());
6374
#ifdef DEBUG
6375
  ScopeInfo<> go_between_sinfo(go_between->shared()->code());
6376
  ASSERT(go_between_sinfo.number_of_parameters() == 0);
6377
  ASSERT(go_between_sinfo.number_of_context_slots() == 0);
6378
#endif
6379

    
6380
  // Allocate and initialize a context extension object with all the
6381
  // arguments, stack locals heap locals and extension properties of the
6382
  // debugged function.
6383
  Handle<JSObject> context_ext = Factory::NewJSObject(Top::object_function());
6384
  // First fill all parameters to the context extension.
6385
  for (int i = 0; i < sinfo.number_of_parameters(); ++i) {
6386
    SetProperty(context_ext,
6387
                sinfo.parameter_name(i),
6388
                Handle<Object>(frame->GetParameter(i)), NONE);
6389
  }
6390
  // Second fill all stack locals to the context extension.
6391
  for (int i = 0; i < sinfo.number_of_stack_slots(); i++) {
6392
    SetProperty(context_ext,
6393
                sinfo.stack_slot_name(i),
6394
                Handle<Object>(frame->GetExpression(i)), NONE);
6395
  }
6396
  // Third fill all context locals to the context extension.
6397
  Handle<Context> frame_context(Context::cast(frame->context()));
6398
  Handle<Context> function_context(frame_context->fcontext());
6399
  for (int i = Context::MIN_CONTEXT_SLOTS;
6400
       i < sinfo.number_of_context_slots();
6401
       ++i) {
6402
    int context_index =
6403
        ScopeInfo<>::ContextSlotIndex(*code, *sinfo.context_slot_name(i), NULL);
6404
    SetProperty(context_ext,
6405
                sinfo.context_slot_name(i),
6406
                Handle<Object>(function_context->get(context_index)), NONE);
6407
  }
6408
  // Finally copy any properties from the function context extension. This will
6409
  // be variables introduced by eval.
6410
  if (function_context->has_extension() &&
6411
      !function_context->IsGlobalContext()) {
6412
    Handle<JSObject> ext(JSObject::cast(function_context->extension()));
6413
    Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext);
6414
    for (int i = 0; i < keys->length(); i++) {
6415
      // Names of variables introduced by eval are strings.
6416
      ASSERT(keys->get(i)->IsString());
6417
      Handle<String> key(String::cast(keys->get(i)));
6418
      SetProperty(context_ext, key, GetProperty(ext, key), NONE);
6419
    }
6420
  }
6421

    
6422
  // Allocate a new context for the debug evaluation and set the extension
6423
  // object build.
6424
  Handle<Context> context =
6425
      Factory::NewFunctionContext(Context::MIN_CONTEXT_SLOTS, go_between);
6426
  context->set_extension(*context_ext);
6427
  // Copy any with contexts present and chain them in front of this context.
6428
  context = CopyWithContextChain(frame_context, context);
6429

    
6430
  // Wrap the evaluation statement in a new function compiled in the newly
6431
  // created context. The function has one parameter which has to be called
6432
  // 'arguments'. This it to have access to what would have been 'arguments' in
6433
  // the function being debugged.
6434
  // function(arguments,__source__) {return eval(__source__);}
6435
  static const char* source_str =
6436
      "function(arguments,__source__){return eval(__source__);}";
6437
  static const int source_str_length = strlen(source_str);
6438
  Handle<String> function_source =
6439
      Factory::NewStringFromAscii(Vector<const char>(source_str,
6440
                                                     source_str_length));
6441
  Handle<JSFunction> boilerplate =
6442
      Compiler::CompileEval(function_source,
6443
                            context,
6444
                            0,
6445
                            context->IsGlobalContext());
6446
  if (boilerplate.is_null()) return Failure::Exception();
6447
  Handle<JSFunction> compiled_function =
6448
      Factory::NewFunctionFromBoilerplate(boilerplate, context);
6449

    
6450
  // Invoke the result of the compilation to get the evaluation function.
6451
  bool has_pending_exception;
6452
  Handle<Object> receiver(frame->receiver());
6453
  Handle<Object> evaluation_function =
6454
      Execution::Call(compiled_function, receiver, 0, NULL,
6455
                      &has_pending_exception);
6456
  if (has_pending_exception) return Failure::Exception();
6457

    
6458
  Handle<Object> arguments = GetArgumentsObject(frame, function, code, &sinfo,
6459
                                                function_context);
6460

    
6461
  // Invoke the evaluation function and return the result.
6462
  const int argc = 2;
6463
  Object** argv[argc] = { arguments.location(),
6464
                          Handle<Object>::cast(source).location() };
6465
  Handle<Object> result =
6466
      Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver,
6467
                      argc, argv, &has_pending_exception);
6468
  if (has_pending_exception) return Failure::Exception();
6469
  return *result;
6470
}
6471

    
6472

    
6473
static Object* Runtime_DebugEvaluateGlobal(Arguments args) {
6474
  HandleScope scope;
6475

    
6476
  // Check the execution state and decode arguments frame and source to be
6477
  // evaluated.
6478
  ASSERT(args.length() == 3);
6479
  Object* check_result = Runtime_CheckExecutionState(args);
6480
  if (check_result->IsFailure()) return check_result;
6481
  CONVERT_ARG_CHECKED(String, source, 1);
6482
  CONVERT_BOOLEAN_CHECKED(disable_break, args[2]);
6483

    
6484
  // Handle the processing of break.
6485
  DisableBreak disable_break_save(disable_break);
6486

    
6487
  // Enter the top context from before the debugger was invoked.
6488
  SaveContext save;
6489
  SaveContext* top = &save;
6490
  while (top != NULL && *top->context() == *Debug::debug_context()) {
6491
    top = top->prev();
6492
  }
6493
  if (top != NULL) {
6494
    Top::set_context(*top->context());
6495
  }
6496

    
6497
  // Get the global context now set to the top context from before the
6498
  // debugger was invoked.
6499
  Handle<Context> context = Top::global_context();
6500

    
6501
  // Compile the source to be evaluated.
6502
  Handle<JSFunction> boilerplate =
6503
      Handle<JSFunction>(Compiler::CompileEval(source, context, 0, true));
6504
  if (boilerplate.is_null()) return Failure::Exception();
6505
  Handle<JSFunction> compiled_function =
6506
      Handle<JSFunction>(Factory::NewFunctionFromBoilerplate(boilerplate,
6507
                                                             context));
6508

    
6509
  // Invoke the result of the compilation to get the evaluation function.
6510
  bool has_pending_exception;
6511
  Handle<Object> receiver = Top::global();
6512
  Handle<Object> result =
6513
    Execution::Call(compiled_function, receiver, 0, NULL,
6514
                    &has_pending_exception);
6515
  if (has_pending_exception) return Failure::Exception();
6516
  return *result;
6517
}
6518

    
6519

    
6520
// If an object given is an external string, check that the underlying
6521
// resource is accessible. For other kinds of objects, always return true.
6522
static bool IsExternalStringValid(Object* str) {
6523
  if (!str->IsString() || !StringShape(String::cast(str)).IsExternal()) {
6524
    return true;
6525
  }
6526
  if (StringShape(String::cast(str)).IsAsciiRepresentation()) {
6527
    return ExternalAsciiString::cast(str)->resource() != NULL;
6528
  } else if (StringShape(String::cast(str)).IsTwoByteRepresentation()) {
6529
    return ExternalTwoByteString::cast(str)->resource() != NULL;
6530
  } else {
6531
    return true;
6532
  }
6533
}
6534

    
6535

    
6536
// Helper function used by Runtime_DebugGetLoadedScripts below.
6537
static int DebugGetLoadedScripts(FixedArray* instances, int instances_size) {
6538
  NoHandleAllocation ha;
6539
  AssertNoAllocation no_alloc;
6540

    
6541
  // Scan heap for Script objects.
6542
  int count = 0;
6543
  HeapIterator iterator;
6544
  while (iterator.has_next()) {
6545
    HeapObject* obj = iterator.next();
6546
    ASSERT(obj != NULL);
6547
    if (obj->IsScript() && IsExternalStringValid(Script::cast(obj)->source())) {
6548
      if (instances != NULL && count < instances_size) {
6549
        instances->set(count, obj);
6550
      }
6551
      count++;
6552
    }
6553
  }
6554

    
6555
  return count;
6556
}
6557

    
6558

    
6559
static Object* Runtime_DebugGetLoadedScripts(Arguments args) {
6560
  HandleScope scope;
6561
  ASSERT(args.length() == 0);
6562

    
6563
  // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
6564
  // rid of all the cached script wrappers and the second gets rid of the
6565
  // scripts which is no longer referenced.
6566
  Heap::CollectAllGarbage();
6567
  Heap::CollectAllGarbage();
6568

    
6569
  // Get the number of scripts.
6570
  int count;
6571
  count = DebugGetLoadedScripts(NULL, 0);
6572

    
6573
  // Allocate an array to hold the result.
6574
  Handle<FixedArray> instances = Factory::NewFixedArray(count);
6575

    
6576
  // Fill the script objects.
6577
  count = DebugGetLoadedScripts(*instances, count);
6578

    
6579
  // Convert the script objects to proper JS objects.
6580
  for (int i = 0; i < count; i++) {
6581
    Handle<Script> script = Handle<Script>(Script::cast(instances->get(i)));
6582
    // Get the script wrapper in a local handle before calling GetScriptWrapper,
6583
    // because using
6584
    //   instances->set(i, *GetScriptWrapper(script))
6585
    // is unsafe as GetScriptWrapper might call GC and the C++ compiler might
6586
    // already have deferenced the instances handle.
6587
    Handle<JSValue> wrapper = GetScriptWrapper(script);
6588
    instances->set(i, *wrapper);
6589
  }
6590

    
6591
  // Return result as a JS array.
6592
  Handle<JSObject> result = Factory::NewJSObject(Top::array_function());
6593
  Handle<JSArray>::cast(result)->SetContent(*instances);
6594
  return *result;
6595
}
6596

    
6597

    
6598
// Helper function used by Runtime_DebugReferencedBy below.
6599
static int DebugReferencedBy(JSObject* target,
6600
                             Object* instance_filter, int max_references,
6601
                             FixedArray* instances, int instances_size,
6602
                             JSFunction* arguments_function) {
6603
  NoHandleAllocation ha;
6604
  AssertNoAllocation no_alloc;
6605

    
6606
  // Iterate the heap.
6607
  int count = 0;
6608
  JSObject* last = NULL;
6609
  HeapIterator iterator;
6610
  while (iterator.has_next() &&
6611
         (max_references == 0 || count < max_references)) {
6612
    // Only look at all JSObjects.
6613
    HeapObject* heap_obj = iterator.next();
6614
    if (heap_obj->IsJSObject()) {
6615
      // Skip context extension objects and argument arrays as these are
6616
      // checked in the context of functions using them.
6617
      JSObject* obj = JSObject::cast(heap_obj);
6618
      if (obj->IsJSContextExtensionObject() ||
6619
          obj->map()->constructor() == arguments_function) {
6620
        continue;
6621
      }
6622

    
6623
      // Check if the JS object has a reference to the object looked for.
6624
      if (obj->ReferencesObject(target)) {
6625
        // Check instance filter if supplied. This is normally used to avoid
6626
        // references from mirror objects (see Runtime_IsInPrototypeChain).
6627
        if (!instance_filter->IsUndefined()) {
6628
          Object* V = obj;
6629
          while (true) {
6630
            Object* prototype = V->GetPrototype();
6631
            if (prototype->IsNull()) {
6632
              break;
6633
            }
6634
            if (instance_filter == prototype) {
6635
              obj = NULL;  // Don't add this object.
6636
              break;
6637
            }
6638
            V = prototype;
6639
          }
6640
        }
6641

    
6642
        if (obj != NULL) {
6643
          // Valid reference found add to instance array if supplied an update
6644
          // count.
6645
          if (instances != NULL && count < instances_size) {
6646
            instances->set(count, obj);
6647
          }
6648
          last = obj;
6649
          count++;
6650
        }
6651
      }
6652
    }
6653
  }
6654

    
6655
  // Check for circular reference only. This can happen when the object is only
6656
  // referenced from mirrors and has a circular reference in which case the
6657
  // object is not really alive and would have been garbage collected if not
6658
  // referenced from the mirror.
6659
  if (count == 1 && last == target) {
6660
    count = 0;
6661
  }
6662

    
6663
  // Return the number of referencing objects found.
6664
  return count;
6665
}
6666

    
6667

    
6668
// Scan the heap for objects with direct references to an object
6669
// args[0]: the object to find references to
6670
// args[1]: constructor function for instances to exclude (Mirror)
6671
// args[2]: the the maximum number of objects to return
6672
static Object* Runtime_DebugReferencedBy(Arguments args) {
6673
  ASSERT(args.length() == 3);
6674

    
6675
  // First perform a full GC in order to avoid references from dead objects.
6676
  Heap::CollectAllGarbage();
6677

    
6678
  // Check parameters.
6679
  CONVERT_CHECKED(JSObject, target, args[0]);
6680
  Object* instance_filter = args[1];
6681
  RUNTIME_ASSERT(instance_filter->IsUndefined() ||
6682
                 instance_filter->IsJSObject());
6683
  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[2]);
6684
  RUNTIME_ASSERT(max_references >= 0);
6685

    
6686
  // Get the constructor function for context extension and arguments array.
6687
  JSObject* arguments_boilerplate =
6688
      Top::context()->global_context()->arguments_boilerplate();
6689
  JSFunction* arguments_function =
6690
      JSFunction::cast(arguments_boilerplate->map()->constructor());
6691

    
6692
  // Get the number of referencing objects.
6693
  int count;
6694
  count = DebugReferencedBy(target, instance_filter, max_references,
6695
                            NULL, 0, arguments_function);
6696

    
6697
  // Allocate an array to hold the result.
6698
  Object* object = Heap::AllocateFixedArray(count);
6699
  if (object->IsFailure()) return object;
6700
  FixedArray* instances = FixedArray::cast(object);
6701

    
6702
  // Fill the referencing objects.
6703
  count = DebugReferencedBy(target, instance_filter, max_references,
6704
                            instances, count, arguments_function);
6705

    
6706
  // Return result as JS array.
6707
  Object* result =
6708
      Heap::AllocateJSObject(
6709
          Top::context()->global_context()->array_function());
6710
  if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
6711
  return result;
6712
}
6713

    
6714

    
6715
// Helper function used by Runtime_DebugConstructedBy below.
6716
static int DebugConstructedBy(JSFunction* constructor, int max_references,
6717
                              FixedArray* instances, int instances_size) {
6718
  AssertNoAllocation no_alloc;
6719

    
6720
  // Iterate the heap.
6721
  int count = 0;
6722
  HeapIterator iterator;
6723
  while (iterator.has_next() &&
6724
         (max_references == 0 || count < max_references)) {
6725
    // Only look at all JSObjects.
6726
    HeapObject* heap_obj = iterator.next();
6727
    if (heap_obj->IsJSObject()) {
6728
      JSObject* obj = JSObject::cast(heap_obj);
6729
      if (obj->map()->constructor() == constructor) {
6730
        // Valid reference found add to instance array if supplied an update
6731
        // count.
6732
        if (instances != NULL && count < instances_size) {
6733
          instances->set(count, obj);
6734
        }
6735
        count++;
6736
      }
6737
    }
6738
  }
6739

    
6740
  // Return the number of referencing objects found.
6741
  return count;
6742
}
6743

    
6744

    
6745
// Scan the heap for objects constructed by a specific function.
6746
// args[0]: the constructor to find instances of
6747
// args[1]: the the maximum number of objects to return
6748
static Object* Runtime_DebugConstructedBy(Arguments args) {
6749
  ASSERT(args.length() == 2);
6750

    
6751
  // First perform a full GC in order to avoid dead objects.
6752
  Heap::CollectAllGarbage();
6753

    
6754
  // Check parameters.
6755
  CONVERT_CHECKED(JSFunction, constructor, args[0]);
6756
  CONVERT_NUMBER_CHECKED(int32_t, max_references, Int32, args[1]);
6757
  RUNTIME_ASSERT(max_references >= 0);
6758

    
6759
  // Get the number of referencing objects.
6760
  int count;
6761
  count = DebugConstructedBy(constructor, max_references, NULL, 0);
6762

    
6763
  // Allocate an array to hold the result.
6764
  Object* object = Heap::AllocateFixedArray(count);
6765
  if (object->IsFailure()) return object;
6766
  FixedArray* instances = FixedArray::cast(object);
6767

    
6768
  // Fill the referencing objects.
6769
  count = DebugConstructedBy(constructor, max_references, instances, count);
6770

    
6771
  // Return result as JS array.
6772
  Object* result =
6773
      Heap::AllocateJSObject(
6774
          Top::context()->global_context()->array_function());
6775
  if (!result->IsFailure()) JSArray::cast(result)->SetContent(instances);
6776
  return result;
6777
}
6778

    
6779

    
6780
// Find the effective prototype object as returned by __proto__.
6781
// args[0]: the object to find the prototype for.
6782
static Object* Runtime_DebugGetPrototype(Arguments args) {
6783
  ASSERT(args.length() == 1);
6784

    
6785
  CONVERT_CHECKED(JSObject, obj, args[0]);
6786

    
6787
  // Use the __proto__ accessor.
6788
  return Accessors::ObjectPrototype.getter(obj, NULL);
6789
}
6790

    
6791

    
6792
static Object* Runtime_SystemBreak(Arguments args) {
6793
  ASSERT(args.length() == 0);
6794
  CPU::DebugBreak();
6795
  return Heap::undefined_value();
6796
}
6797

    
6798

    
6799
// Finds the script object from the script data. NOTE: This operation uses
6800
// heap traversal to find the function generated for the source position
6801
// for the requested break point. For lazily compiled functions several heap
6802
// traversals might be required rendering this operation as a rather slow
6803
// operation. However for setting break points which is normally done through
6804
// some kind of user interaction the performance is not crucial.
6805
static Handle<Object> Runtime_GetScriptFromScriptName(
6806
    Handle<String> script_name) {
6807
  // Scan the heap for Script objects to find the script with the requested
6808
  // script data.
6809
  Handle<Script> script;
6810
  HeapIterator iterator;
6811
  while (script.is_null() && iterator.has_next()) {
6812
    HeapObject* obj = iterator.next();
6813
    // If a script is found check if it has the script data requested.
6814
    if (obj->IsScript()) {
6815
      if (Script::cast(obj)->name()->IsString()) {
6816
        if (String::cast(Script::cast(obj)->name())->Equals(*script_name)) {
6817
          script = Handle<Script>(Script::cast(obj));
6818
        }
6819
      }
6820
    }
6821
  }
6822

    
6823
  // If no script with the requested script data is found return undefined.
6824
  if (script.is_null()) return Factory::undefined_value();
6825

    
6826
  // Return the script found.
6827
  return GetScriptWrapper(script);
6828
}
6829

    
6830

    
6831
// Get the script object from script data. NOTE: Regarding performance
6832
// see the NOTE for GetScriptFromScriptData.
6833
// args[0]: script data for the script to find the source for
6834
static Object* Runtime_GetScript(Arguments args) {
6835
  HandleScope scope;
6836

    
6837
  ASSERT(args.length() == 1);
6838

    
6839
  CONVERT_CHECKED(String, script_name, args[0]);
6840

    
6841
  // Find the requested script.
6842
  Handle<Object> result =
6843
      Runtime_GetScriptFromScriptName(Handle<String>(script_name));
6844
  return *result;
6845
}
6846

    
6847

    
6848
static Object* Runtime_FunctionGetAssemblerCode(Arguments args) {
6849
#ifdef DEBUG
6850
  HandleScope scope;
6851
  ASSERT(args.length() == 1);
6852
  // Get the function and make sure it is compiled.
6853
  CONVERT_ARG_CHECKED(JSFunction, func, 0);
6854
  if (!func->is_compiled() && !CompileLazy(func, KEEP_EXCEPTION)) {
6855
    return Failure::Exception();
6856
  }
6857
  func->code()->PrintLn();
6858
#endif  // DEBUG
6859
  return Heap::undefined_value();
6860
}
6861

    
6862

    
6863
static Object* Runtime_Abort(Arguments args) {
6864
  ASSERT(args.length() == 2);
6865
  OS::PrintError("abort: %s\n", reinterpret_cast<char*>(args[0]) +
6866
                                    Smi::cast(args[1])->value());
6867
  Top::PrintStack();
6868
  OS::Abort();
6869
  UNREACHABLE();
6870
  return NULL;
6871
}
6872

    
6873

    
6874
#ifdef DEBUG
6875
// ListNatives is ONLY used by the fuzz-natives.js in debug mode
6876
// Exclude the code in release mode.
6877
static Object* Runtime_ListNatives(Arguments args) {
6878
  ASSERT(args.length() == 0);
6879
  HandleScope scope;
6880
  Handle<JSArray> result = Factory::NewJSArray(0);
6881
  int index = 0;
6882
#define ADD_ENTRY(Name, argc)                                                \
6883
  {                                                                          \
6884
    HandleScope inner;                                                       \
6885
    Handle<String> name =                                                    \
6886
      Factory::NewStringFromAscii(Vector<const char>(#Name, strlen(#Name))); \
6887
    Handle<JSArray> pair = Factory::NewJSArray(0);                           \
6888
    SetElement(pair, 0, name);                                               \
6889
    SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc)));                    \
6890
    SetElement(result, index++, pair);                                       \
6891
  }
6892
  RUNTIME_FUNCTION_LIST(ADD_ENTRY)
6893
#undef ADD_ENTRY
6894
  return *result;
6895
}
6896
#endif
6897

    
6898

    
6899
static Object* Runtime_Log(Arguments args) {
6900
  ASSERT(args.length() == 2);
6901
  CONVERT_CHECKED(String, format, args[0]);
6902
  CONVERT_CHECKED(JSArray, elms, args[1]);
6903
  Vector<const char> chars = format->ToAsciiVector();
6904
  Logger::LogRuntime(chars, elms);
6905
  return Heap::undefined_value();
6906
}
6907

    
6908

    
6909
static Object* Runtime_IS_VAR(Arguments args) {
6910
  UNREACHABLE();  // implemented as macro in the parser
6911
  return NULL;
6912
}
6913

    
6914

    
6915
// ----------------------------------------------------------------------------
6916
// Implementation of Runtime
6917

    
6918
#define F(name, nargs)                                                 \
6919
  { #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
6920
    static_cast<int>(Runtime::k##name) },
6921

    
6922
static Runtime::Function Runtime_functions[] = {
6923
  RUNTIME_FUNCTION_LIST(F)
6924
  { NULL, NULL, NULL, 0, -1 }
6925
};
6926

    
6927
#undef F
6928

    
6929

    
6930
Runtime::Function* Runtime::FunctionForId(FunctionId fid) {
6931
  ASSERT(0 <= fid && fid < kNofFunctions);
6932
  return &Runtime_functions[fid];
6933
}
6934

    
6935

    
6936
Runtime::Function* Runtime::FunctionForName(const char* name) {
6937
  for (Function* f = Runtime_functions; f->name != NULL; f++) {
6938
    if (strcmp(f->name, name) == 0) {
6939
      return f;
6940
    }
6941
  }
6942
  return NULL;
6943
}
6944

    
6945

    
6946
void Runtime::PerformGC(Object* result) {
6947
  Failure* failure = Failure::cast(result);
6948
  if (failure->IsRetryAfterGC()) {
6949
    // Try to do a garbage collection; ignore it if it fails. The C
6950
    // entry stub will throw an out-of-memory exception in that case.
6951
    Heap::CollectGarbage(failure->requested(), failure->allocation_space());
6952
  } else {
6953
    // Handle last resort GC and make sure to allow future allocations
6954
    // to grow the heap without causing GCs (if possible).
6955
    Counters::gc_last_resort_from_js.Increment();
6956
    Heap::CollectAllGarbage();
6957
  }
6958
}
6959

    
6960

    
6961
} }  // namespace v8::internal